В чем разница между ZonedDateTime и OffsetDateTime?

155

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

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

Женя
источник
4
В основном ZonedDateTimeтакже содержит информацию о часовых поясах, включая переключение летнего времени и т. Д. Из того, что я прочитал.
fge

Ответы:

187

Q: В чем разница между java 8 ZonedDateTime и OffsetDateTime?

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

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

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

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

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

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


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

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

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

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

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

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

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


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

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

Стивен С
источник