Является ли 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-