Является ли Java 8 новым Java Date Time API заботой о DST?

Я думаю использовать новый java 8 API Time Time. Я немного поработал с Google и нашел jodaTime хорошим выбором для java, но все равно заинтересован в том, как работает этот новый API.

Я сохраняю все время в значениях UTC в своем хранилище данных и буду преобразовывать их в значение локального часового пояса, основанное на пользовательском часовом поясе. Я могу найти много статей, показывающих, как использовать новый Java Date Time API. Однако я не уверен, что API позаботится об изменениях ДСТ? Или у нас есть лучший способ обработки Date?

Я просто изучаю новый API дат, поэтому подумал о том, чтобы услышать ваши мысли о работе с DateTime и отображать его на основе UserZone Time.

Ответ 1

Это зависит от того, какой класс вы используете:

  • Instant - мгновенная точка на глобальной временной линии (UTC) и не связана с часовым поясом.
  • LocalDate и LocalDateTime не имеют понятия зоны времени, но вызов now(), конечно, даст вам правильное время.
  • OffsetDateTime имеет временную зону, но не поддерживает летнее время.
  • ZonedDateTime имеет полную поддержку часовых поясов.

Для преобразования между ними обычно требуется временная зона, поэтому для ответа на ваш вопрос:

    Да, Java 8 Дата/Время может заботиться о DST, если вы используете его правильно.

Ответ 2

Ответ Andreas является правильным.

Пример кода

Позвольте проверить его с помощью некоторого кода. DST в США и Канада истекает в этом году в 02:00 1 ноября 2015 года.

Давайте начнем с 1:00 в "локальном" дате-времени, что означает не привязанный к временной шкале и игнорирующий проблему часовых поясов. Добавьте час, и мы получим 2 часа ночи. Имеет смысл.

LocalDateTime localDateTime = LocalDateTime.of( 2015 , Month.NOVEMBER , 1 , 1 , 0 ); // 1 AM anywhere. Not tied the timeline nor to any time zone.
LocalDateTime localDateTimeOneHourLater = localDateTime.plusHours( 1 ); // 2 AM anywhere, in no particular time zone, ignoring DST.

Далее мы получаем конкретный, с определенным часовым поясом. Мы берем это 1 AM в любом месте и помещаем его в часовой пояс America/Los_Angeles (западное побережье Соединенных Штатов).

ZoneId zoneId_LosAngeles = ZoneId.of( "America/Los_Angeles" );
ZonedDateTime before = localDateTime.atZone( zoneId_LosAngeles ); // Assign a time zone, tying this vague date-time idea/generality to an actual moment on the time line.

Теперь добавьте час и посмотрите, что получилось. Если DST игнорируется, то получите 2 AM. Если DST соблюдается, то получите 1 AM... при достижении 2 AM время настенных часов возвращается к 1 часу, но с новым смещением, из-UTC. Это освещается осенью (осенью) в качестве fall back.

ZonedDateTime after = before.plusHours( 1 ); // 2 AM? Nope, 1 AM because DST Daylight Saving Time expires at 2 AM Nov 1, 2015.

Дамп для консоли.

System.out.println( "localDateTime : " + localDateTime );
System.out.println( "localDateTimeOneHourLater : " + localDateTimeOneHourLater );
System.out.println( "before : " + before );
System.out.println( "after : " + after );

При запуске мы получаем этот вывод. Без часового пояса, 1 AM + 1 час = 2 AM. Помните, что это "локальные" значения даты и времени, не UTC. Они представляют собой лишь смутное представление о дате-времени, а не о фактическом моменте на временной шкале.

localDateTime : 2015-11-01T01:00
localDateTimeOneHourLater : 2015-11-01T02:00

Но с временными зонами, применяемыми в день истечения ДСТ, мы получаем разные результаты. Обратите внимание, что время суток остается 01:00, но offset-from-UTC изменяется от -07:00 до -08:00.

before : 2015-11-01T01:00-07:00[America/Los_Angeles]
after : 2015-11-01T01:00-08:00[America/Los_Angeles]

Возможно, это было бы более ясным и более легким для проверки, если мы входим в UTC. Мы можем сделать это просто, обратившись к объектам before и after как объекты Instant. System.out.println затем неявно вызывает toString.

System.out.println( "before.toInstant : " + before.toInstant() );
System.out.println( "after.toInstant : " + after.toInstant() );

При запуске.

before.toInstant : 2015-11-01T08:00:00Z
after.toInstant : 2015-11-01T09:00:00Z

Ответ 3

Да, API Java будет учитывать изменения DST.

В этом руководстве объясняется, как преобразовать даты между часовыми поясами и как выбрать правильный класс для представления даты: https://docs.oracle.com/javase/tutorial/datetime/iso/timezones.html

Вы также можете посмотреть на этот класс, который представляет правила для каждой зоны: http://docs.oracle.com/javase/8/docs/api/java/time/zone/ZoneRules.html

В частности, этот метод может рассказать вам, если конкретный момент заключается в экономии дневного света: http://docs.oracle.com/javase/8/docs/api/java/time/zone/ZoneRules.html#isDaylightSavings-java.time.Instant-