Почему 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 не поддерживает ЛЕТ. Разве разработчики просто отказались от этого?

(В моем фактическом коде я попытался вычесть Period.ofYears(3), но цитируемые Мгновенные методы - это те, которые вызываются в конце).

Ответ 1

Я пытаюсь понять, что мне кажется чем-то очень логичным.

Вот код для метода 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. Константы определяют единицы только до дней. Постоянные, указанные выше дни, не определены (в LocalDate и LocalDateTime нет).

Ответ 2

Я полагаю, это происходит потому, что Instant не содержит информации о часовом поясе. Это означает, что один и тот же момент можно интерпретировать как разные значения даты и времени в разных часовых поясах. Предположим, у нас есть Instant, который представлен как 2016.01.01 00:30:00, скажем, в UTC + 2 часовом поясе. Тот же Мгновенный означает 2015.12.31 23:30:00 в UTC + 1 часовой пояс. 2016 год високосный, его продолжительность составляет 366 дней, поэтому чтобы получить Мгновенный минус 1 год, мы должны вычесть из него 366 дней. Но 2015 год не високосный, его продолжительность составляет 365 дней, поэтому мы должны вычесть 365 дней из Мгновенного. Эта двусмысленность вызывает тот факт, что Instant не поддерживает ChronoUnit.YEARS. Подобная проблема приводит к тому, что Instant не поддерживает ChronoUnit.MONTHS. И, вероятно, отсутствие информации о DST приводит к тому, что Instant не поддерживает ChronoUnit.WEEKS.