Java API для получения границ перехода на летнее время в течение года
У меня есть диапазон дат (начальная и конечная даты) и требуется знать, попадает ли это в переход на летнее время.
Есть ли какой-либо Java API, доступный для проверки этого или любой Java-код для достижения этого?
2 ответа:
Переход на летнее время происходит в разные даты в каждой стране / регионе, поэтому первое, что нужно знать, - это название часового пояса, который вы проверяете.
Я пишу этот ответ, используя как Joda-Time, так и новый Java Date/Time API, и оба используют список имен часовых поясов IANA (в формате
Continent/City
). Оба API также избегают использовать 3-буквенные имена , потому что они неоднозначны и не стандартны.Для кода ниже я буду использовать
America/Sao_Paulo
(the часовой пояс, где я живу, который имеет DST меняется каждый год), но вы можете заменить его на нужный вам часовой пояс.Приведенный ниже код показывает, как проверить, находится ли дата в DST, и найти следующую дату, когда произойдет изменение DST. Итак, если у вас есть начальная и конечная даты и вы хотите знать, находятся ли они в пределах изменения DST, вы можете проверить, находятся ли они в DST или нет, а также найти следующие и предыдущие изменения DST (и проверить, находятся ли даты между этими изменениями - мне не ясно, как ваша дата будет изменена). проверка должна быть сделана).
также имейте в виду, что Joda-Time находится в режиме обслуживания и заменяется новыми API, поэтому я не рекомендую начинать новый проект с него. Даже на веб-сайтеjoda говорится: "обратите внимание, что Joda-Time считается в значительной степени "законченным" проектом. Никаких серьезных улучшений не планируется. Если вы используете Java SE 8, пожалуйста, перейдите на java.время (JSR-310).".
Джода-Время
Можно использовать класс
org.joda.time.DateTimeZone
. К знайте все доступные часовые пояса, звонитеDateTimeZone.getAvailableIDs()
.Приведенный ниже код проверяет, находится ли дата в DST, а также находит следующую дату, когда произойдет изменение DST:
// create timezone object DateTimeZone zone = DateTimeZone.forID("America/Sao_Paulo"); // check if a date is in DST DateTime inDst = new DateTime(2017, 1, 1, 10, 0, zone); // isStandardOffset returns false (it's in DST) System.out.println(zone.isStandardOffset(inDst.getMillis())); // check when it'll be the next DST change DateTime nextDstChange = new DateTime(zone.nextTransition(inDst.getMillis()), zone); System.out.println(nextDstChange); // 2017-02-18T23:00:00.000-03:00 // check if a date is in DST DateTime noDst = new DateTime(2017, 6, 18, 10, 0, zone); // isStandardOffset returns true (it's not in DST) System.out.println(zone.isStandardOffset(noDst.getMillis())); // check when it'll be the next DST change nextDstChange = new DateTime(zone.nextTransition(noDst.getMillis()), zone); System.out.println(nextDstChange); // 2017-10-15T01:00:00.000-02:00
Если вы хотите найти предыдущее изменение DST (вместо следующего), вызовите
previousTransition()
вместоnextTransition()
.
Java new Date / Time API
Если вы используете Java 8, то новая java.время API уже приходит изначально.
Если вы используете Java , вы можете использовать ThreeTen Backport , отличный backport для новых классов даты и времени Java 8. А для Android есть ThreeTenABP (подробнее о том, как его использовать здесь).
Приведенный ниже код работает для обоих. Единственное различие-это имена пакетов (в Java 8 это
Код очень похож на версию Joda-Time. Главный различия:java.time
и в ThreeTen Backport (или ThreeTenABP для Android) этоorg.threeten.bp
), но классы и методы имена одинаковы.Несмотря на все эти различия, идея очень похожа:
- в то время как Joda-Time имеет
isStandardOffset()
, чтобы проверить, является ли дата не в DST, новый API имеетisDaylightSavings()
, чтобы проверить, находится ли дата в DST.- Joda-Time предоставляет методы непосредственно в классе
DateTimeZone
, но новый API имеет выделенный класс для своих правил DST(java.time.zone.ZoneRules
)- методы для следующего и предыдущего переходов возвращают a
java.time.zone.ZoneOffsetTransition
вместо прямого возврата даты (этот объект предоставляет дополнительную информацию об изменении DST, как показано ниже под).Если вы хотите найти предыдущее изменение DST вместо следующего, вы можете вызвать// create timezone object ZoneId zone = ZoneId.of("America/Sao_Paulo"); // get the timezone's rules ZoneRules rules = zone.getRules(); // check if a date is in DST ZonedDateTime inDST = ZonedDateTime.of(2017, 1, 1, 10, 0, 0, 0, zone); // isDaylightSavings returns true (it's in DST) System.out.println(rules.isDaylightSavings(inDST.toInstant())); // check when it'll be the next DST change ZoneOffsetTransition nextTransition = rules.nextTransition(inDST.toInstant()); // getInstant() returns the UTC instant; atZone converts to the specified timezone System.out.println(nextTransition.getInstant().atZone(zone)); // 2017-02-18T23:00-03:00[America/Sao_Paulo] // you can also check the date/time and offset before and after the DST change // in this case, at 19/02/2017, the clock is moved 1 hour back (from midnight to 11 PM) ZonedDateTime beforeDST = ZonedDateTime.of(nextTransition.getDateTimeBefore(), nextTransition.getOffsetBefore()); System.out.println(beforeDST); // 2017-02-19T00:00-02:00 ZonedDateTime afterDST = ZonedDateTime.of(nextTransition.getDateTimeAfter(), nextTransition.getOffsetAfter()); System.out.println(afterDST); // 2017-02-18T23:00-03:00 // check if a date is in DST ZonedDateTime noDST = ZonedDateTime.of(2017, 6, 1, 10, 0, 0, 0, zone); // isDaylightSavings returns false (it's not in DST) System.out.println(rules.isDaylightSavings(noDST.toInstant())); // check when it'll be the next DST change nextTransition = rules.nextTransition(noDST.toInstant()); // getInstant() returns the UTC instant; atZone converts to the specified timezone System.out.println(nextTransition.getInstant().atZone(zone)); // 2017-10-15T01:00-02:00[America/Sao_Paulo] // you can also check the date/time and offset before and after the DST change // in this case, at 15/10/2017, the clock is moved 1 hour forward (from midnight to 1 AM) beforeDST = ZonedDateTime.of(nextTransition.getDateTimeBefore(), nextTransition.getOffsetBefore()); System.out.println(beforeDST); // 2017-10-15T00:00-03:00 afterDST = ZonedDateTime.of(nextTransition.getDateTimeAfter(), nextTransition.getOffsetAfter()); System.out.println(afterDST); // 2017-10-15T01:00-02:00
rules.previousTransition()
вместоrules.nextTransition()
.
Конечно, есть. Их также несколько. Стандартный API для использования -
Совершенно очевидно, что сначала вам нужно решить, в каком часовом поясе вы хотите это сделать.java.time
.Вы отметили свой вопрос gmt, и это легко: GMT не имеет летнего времени (летнее время), поэтому в вашем диапазоне никогда не будет переключения. Если это то, что вы имели в виду, вам не нужно читать дальше.
Даты перехода на летнее время в Северной Америке и ЕС не совпадают, а на южное полушарие они все же совершенно разные. Также многие часовые пояса вообще не применяют ДСТ. Так что получите ваш предполагаемый часовой пояс из
ZoneId.of()
, предоставив строку в видеcontinent/city
, напримерEurope/Stockholm
. Он принимает несколько городов, я думаю, что есть по крайней мере один в каждом часовом поясе и один в каждой стране. ИспользуйтеZoneId.getRules()
для получения объектаZoneRules
. Пожалуйста, проверьтедокументацию для всех вещей, которые вы можете сделать с этим объектом. Я думаю, что попробовал быnextTransistion()
передать вашу дату начала. Если я получуnull
назад, не может быть переключения в диапазоне (вероятно, зона не применяет DST). Если я получуZoneOffsetTransition
обратно, используйте егоgetInstant()
и проверьте, лежит лиInstant
перед вашей конечной датой.Вы отметили свой вопрос jodatime, и да, Joda-Time тоже должен быть вариантом.
java.time
был описан в JSR-310. Он встроен в Java 8 и более поздние версии. Если вы еще не используете Java 8, используйтеThreeten Backport .Обратите внимание, что Джода-время считается в значительной степени "готовый проект. Никаких серьезных улучшений не планируется. При использовании Java SE 8, пожалуйста, перенесите to
java.time
(JSR-310).Цитируется издомашней страницы Joda-Time .