web-dev-qa-db-ja.com

InstantがChronoUnit.YEARSでの操作をサポートしないのはなぜですか?

これは私には予想外でした。

_> Clock clock = Clock.systemUTC();

> Instant.now(clock).minus(3, ChronoUnit.DAYS);
Java.time.Instant res4 = 2016-10-04T00:57:20.840Z

> Instant.now(clock).minus(3, ChronoUnit.YEARS);
Java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Years
_

回避策として、私はこれを行わなければなりません:

_> Instant.now(clock).atOffset(ZoneOffset.UTC).minus(3, ChronoUnit.YEARS).toInstant();
Java.time.Instant res11 = 2013-10-07T01:02:56.361Z
_

InstantがYEARSをサポートしていないのはなぜですか。開発者はそれをあきらめましたか?

(私の実際のコードでは、Period.ofYears(3)を減算しようとしましたが、引用されたInstantメソッドは、最後に呼び出されるものです)。

37
alexandroid

私は、非常に論理的なもののように見えるものに突き刺しています。

以下は、メソッドplus(long, TemporalUnit)minus(...)で使用される)のコードです。

     @Override
     public Instant plus(long amountToAdd, TemporalUnit unit) {
         if (unit instanceof ChronoUnit) {
             switch ((ChronoUnit) unit) {
                 case NANOS: return plusNanos(amountToAdd);
                 case MICROS: return plus(amountToAdd / 1000_000, (amountToAdd % 1000_000) * 1000);
                 case MILLIS: return plusMillis(amountToAdd);
                 case SECONDS: return plusSeconds(amountToAdd);
                 case MINUTES: return plusSeconds(Math.multiplyExact(amountToAdd, SECONDS_PER_MINUTE));
                 case HOURS: return plusSeconds(Math.multiplyExact(amountToAdd, SECONDS_PER_HOUR));
                 case HALF_DAYS: return plusSeconds(Math.multiplyExact(amountToAdd, SECONDS_PER_DAY / 2));
                 case DAYS: return plusSeconds(Math.multiplyExact(amountToAdd, SECONDS_PER_DAY));
             }
             throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit);
         }
         return unit.addTo(this, amountToAdd);
     }

結果は単位の秒表現を乗算することで計算され、年は論理的かつ一貫して秒で表現できないことが明らかな理由でわかります。


追加

上記の方法で使用されている定数がJava.time.LocalTime。定数は、日までの単位のみを定義します。日を超える定数は定義されていません(LocalDateLocalDateTimeにはどちらもありません)。

23
Yassin Hajaj

Instantにはタイムゾーンに関する情報が含まれていないため、このようになると思います。つまり、同じインスタントが異なるタイムゾーンの異なる日時値として解釈される可能性があります。 2016.01.01 00:30:00で表されるインスタントがあるとします。たとえば、UTC + 2タイムゾーンです。同じインスタントは、UTC + 1タイムゾーンでの2015.12.31 23:30:00を意味します。 2016年はうるう年で、長さは366日なので、インスタントマイナス1年を取得するには、366日を差し引く必要があります。ただし、2015年はうるう年ではなく、長さは365日なので、インスタントから365日を差し引く必要があります。このあいまいさが原因で、InstantはChronoUnit.YEARSをサポートしていません。同様の問題により、InstantはChronoUnit.MONTHSをサポートしません。また、DST情報がないと、InstantはChronoUnit.WEEKSをサポートしなくなります。

0