Ответ Рихтерса правильный и должен быть принят.
Как заметил Рихтерс, логики для перехода на летнее время (DST) или других аномалий нет. Политики произвольно переопределяют смещение от UTC , используемое в их часовых поясах . Они вносят эти изменения часто с небольшим предупреждением или даже без предупреждения, как Северная Корея сделала несколько недель назад.
java.time
Вот некоторые дополнительные мысли и пример кода с использованием современных java.time классов, которые следовали за классами Joda-Time, показанными в его Ответе.
Эти изменения отслеживаются в списке, поддерживаемом ICANN , известном как tzdata , ранее известном как база данных Olson. Ваша реализация Java, операционная система хоста и система базы данных, скорее всего, имеют свои собственные копии этих данных, которые необходимо заменять по мере необходимости, когда изменения происходят в режимах, которые вас интересуют. В этих изменениях нет логики, поэтому нет способа предсказать изменения программно. Ваш код должен вызывать свежую копию tzdata .
Так, например, между 25 и 31 октября мы должны проверить, является ли фактическая дата воскресеньем, до или после 2 часов ...
На самом деле вам не нужно определять точку отсечки. Хорошая библиотека времени и даты обрабатывает это автоматически.
Java обладает лучшими подобными библиотеками, ведущими в отрасли java.time классами. Когда вы запрашиваете время суток в определенную дату в определенном регионе (часовом поясе), если это время суток недопустимо, корректировка выполняется автоматически. Прочитайте документацию по ZonedDateTime
, чтобы понять алгоритм, использованный в этой настройке.
ZoneId z = ZoneId.of( "America/Montreal" );
LocalDate ld = LocalDate.of( 2018 , Month.MARCH , 11 ); // 2018-03-11.
LocalTime lt = LocalTime.of( 2 , 0 ); // 2 AM.
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z );
Обратите внимание, что результат - 3 часа ночи, а не запрошенный 2 часа ночи. В тот день в этой зоне не было двух часов ночи. Так что java.time настроен на 3 часа ночи, так как часы «Спрингс впереди» час.
zdt.toString (): 2018-03-11T03: 00-04: 00 [Америка / Монреаль]
Если вы чувствуете необходимость исследовать правила, определенные для часового пояса, используйте класс ZoneRules
.
Получите величину сдвига DST, использованного в настоящий момент.
Duration d = z.getRules().getDaylightSavings( Instant.now() ) ;
Получить следующее запланированное изменение, представленное в виде объекта ZoneOffsetTransition
.
ZoneId z = ZoneId.of( "America/Montreal" );
ZoneOffsetTransition t = z.getRules().nextTransition( Instant.now() );
String output = "For zone: " + z + ", on " + t.getDateTimeBefore() + " duration change: " + t.getDuration() + " to " + t.getDateTimeAfter();
Для зоны: Америка / Монреаль, с 2018-11-04T02: 00 изменение продолжительности: с PT-1H на 2018-11-04T01: 00
Укажите собственное имя часового пояса в формате continent/region
, например America/Montreal
, Africa/Casablanca
или Pacific/Auckland
. Никогда не используйте 3-4-буквенное сокращение, например EST
или IST
, поскольку они не истинные часовые пояса, не стандартизированы и даже не уникальны (!).
О java.time
Фреймворк java.time встроен в Java 8 и более поздние версии. Эти классы заменяют проблемные старые устаревшие классы даты и времени, такие как java.util.Date
, Calendar
, & SimpleDateFormat
.
Проект Joda-Time , теперь в режиме обслуживания , рекомендует выполнить переход на классы java.time .
Чтобы узнать больше, см. Учебное пособие по Oracle . И поиск переполнения стека для многих примеров и объяснений. Спецификация JSR 310 .
Вы можете обмениваться java.time объектами напрямую с вашей базой данных. Используйте драйвер JDBC , совместимый с JDBC 4.2 или более поздней версии. Нет необходимости в строках, нет необходимости в java.sql.*
классах.
Где получить классы java.time?
Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Здесь вы можете найти несколько полезных классов, таких как Interval
, YearWeek
, YearQuarter
и more .