Какая разница между java 8 ZonedDateTime и OffsetDateTime?

Я прочитал документацию, но я все еще не могу получить, когда я должен использовать тот или иной:

В соответствии с документацией OffsetDateTime следует использовать при записи даты в базу данных, но я не понимаю почему.

Ответ 1

Q: Какая разница между java 8 ZonedDateTime и OffsetDateTime?

Javadocs говорят это:

" OffsetDateTime, ZonedDateTime и Instant все хранят момент времени на временной ZonedDateTime с точностью до наносекунды. Instant является самым простым, просто представляющим момент. OffsetDateTime добавляет к OffsetDateTime смещение от UTC/Гринвич, что позволяет локальному времени и дате быть ZonedDateTime добавляет полные правила часовых поясов. "

Источник: https://docs.oracle.com/javase/8/docs/api/java/time/OffsetDateTime.html.

Таким образом, разница между OffsetDateTime и ZonedDateTime заключается в том, что последний включает в себя правила, которые охватывают корректировки летнего времени и различные другие аномалии.

Проще говоря:

Часовой пояс= (смещение от UTC + правила для аномалий)


Q: Согласно документации, OffsetDateTime следует использовать при записи даты в базу данных, но я не понимаю, почему.

Даты с местными временными смещениями всегда представляют одинаковые моменты времени и, следовательно, имеют стабильный порядок. В отличие от этого, значение дат с полной информацией о часовом поясе нестабильно из-за корректировок правил для соответствующих часовых поясов. (И это действительно происходит; например, для значений даты и времени в будущем.) Поэтому, если вы сохраните, а затем ZonedDateTime у реализации ZonedDateTime проблема:

  • Он может хранить вычисленное смещение... и извлеченный объект может иметь смещение, которое не согласуется с текущими правилами для идентификатора зоны.

  • Он может отбросить вычисленное смещение... и тогда извлеченный объект представляет точку на абсолютной/универсальной временной шкале, отличную от той, которая была сохранена.

Если вы используете сериализацию объектов Java, реализация Java 9 использует первый подход. Возможно, это "более правильный" способ справиться с этим, но это, похоже, не задокументировано. (Драйверы JDBC и привязки ORM, по-видимому, принимают аналогичные решения и, надеюсь, делают это правильно.)

Но если вы пишете приложение, которое вручную хранит значения даты/времени или полагаются на java.sql.DateTime, то справляться со сложностями идентификатора зоны... вероятно, чего-то следует избегать. Отсюда и совет.

Обратите внимание, что даты, значение/порядок которых нестабилен во времени, могут быть проблематичными для приложения. А поскольку изменения в правилах зон - крайний случай, проблемы могут возникнуть в неожиданные моменты.


(Возможная) вторая причина для совета состоит в том, что конструкция ZonedDateTime неоднозначна в определенных точках. Например, в период времени, когда вы "переводите часы назад", объединение локального времени и идентификатора зоны может дать вам два разных смещения. ZonedDateTime будет последовательно выбирать один над другим... но это не всегда правильный выбор.

Теперь это может быть проблемой для любых приложений, которые конструируют значения ZonedDateTime таким образом. Но с точки зрения того, что кто-то строит корпоративное приложение, это большая проблема, когда (возможно, неправильные) значения ZonedDateTime являются постоянными и используются позже.