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

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

  • OffsetDateTime
  • ZonedDateTime

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

2 ответа

Решение

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

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

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

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

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

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

Даты, значение / порядок которых нестабильны, проблематичны, если (например) вы создаете индекс базы данных для поля даты.

Принятый ответ дает очень подробное объяснение, возможно, приведенный ниже пример кода может предоставить вам короткую и четкую картину:

      Instant instant = Instant.now();
Clock clock = Clock.fixed(instant, ZoneId.of("America/New_York"));
OffsetDateTime offsetDateTime = OffsetDateTime.now(clock);
ZonedDateTime zonedDateTime = ZonedDateTime.now(clock);

System.out.println(offsetDateTime); // 2019-01-03T19:10:16.806-05:00
System.out.println(zonedDateTime);  // 2019-01-03T19:10:16.806-05:00[America/New_York]
System.out.println();

OffsetDateTime offsetPlusSixMonths = offsetDateTime.plusMonths(6);
ZonedDateTime zonedDateTimePlusSixMonths = zonedDateTime.plusMonths(6);

System.out.println(offsetPlusSixMonths); // 2019-07-03T19:10:16.806-05:00
System.out.println(zonedDateTimePlusSixMonths); // 2019-07-03T19:10:16.806-04:00[America/New_York]
System.out.println(zonedDateTimePlusSixMonths.toEpochSecond() - offsetPlusSixMonths.toEpochSecond()); // -3600

System.out.println();
System.out.println(zonedDateTimePlusSixMonths.toLocalDateTime()); // 2019-07-03T19:10:16.806
System.out.println(offsetPlusSixMonths.toLocalDateTime()); // 2019-07-03T19:10:16.806

Короче говоря, используйте только в том случае, если вы хотите учитывать летнее время, обычно разница в один час, как вы можете видеть в примере выше, смещение ZonedDateTime меняться от -5:00 к -04:00, в большинстве случаев ваша бизнес-логика может закончиться ошибкой.

(копия кода с https://www.youtube.com/watch?v=nEQhx9hGutQ)

Другие вопросы по тегам