Java API для получения границ перехода на летнее время в течение года


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

Есть ли какой-либо Java API, доступный для проверки этого или любой Java-код для достижения этого?

2 3

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 это java.time и в ThreeTen Backport (или ThreeTenABP для Android) это org.threeten.bp), но классы и методы имена одинаковы.

Код очень похож на версию Joda-Time. Главный различия:
  • в то время как Joda-Time имеет isStandardOffset(), чтобы проверить, является ли дата не в DST, новый API имеет isDaylightSavings(), чтобы проверить, находится ли дата в DST.
  • Joda-Time предоставляет методы непосредственно в классе DateTimeZone, но новый API имеет выделенный класс для своих правил DST(java.time.zone.ZoneRules)
  • методы для следующего и предыдущего переходов возвращают a java.time.zone.ZoneOffsetTransition вместо прямого возврата даты (этот объект предоставляет дополнительную информацию об изменении 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
Если вы хотите найти предыдущее изменение DST вместо следующего, вы можете вызвать rules.previousTransition() вместо rules.nextTransition().

Конечно, есть. Их также несколько. Стандартный API для использования - java.time.

Совершенно очевидно, что сначала вам нужно решить, в каком часовом поясе вы хотите это сделать.

Вы отметили свой вопрос gmt, и это легко: GMT не имеет летнего времени (летнее время), поэтому в вашем диапазоне никогда не будет переключения. Если это то, что вы имели в виду, вам не нужно читать дальше.

Даты перехода на летнее время в Северной Америке и ЕС не совпадают, а на южное полушарие они все же совершенно разные. Также многие часовые пояса вообще не применяют ДСТ. Так что получите ваш предполагаемый часовой пояс из ZoneId.of(), предоставив строку в виде continent/city, например Europe/Stockholm. Он принимает несколько городов, я думаю, что есть по крайней мере один в каждом часовом поясе и один в каждой стране. Используйте ZoneId.getRules() для получения объекта ZoneRules. Пожалуйста, проверьтедокументацию для всех вещей, которые вы можете сделать с этим объектом. Я думаю, что попробовал бы nextTransistion() передать вашу дату начала. Если я получу null назад, не может быть переключения в диапазоне (вероятно, зона не применяет DST). Если я получу ZoneOffsetTransition обратно, используйте его getInstant() и проверьте, лежит ли Instant перед вашей конечной датой.

java.time был описан в JSR-310. Он встроен в Java 8 и более поздние версии. Если вы еще не используете Java 8, используйтеThreeten Backport .

Вы отметили свой вопрос jodatime, и да, Joda-Time тоже должен быть вариантом.

Обратите внимание, что Джода-время считается в значительной степени "готовый проект. Никаких серьезных улучшений не планируется. При использовании Java SE 8, пожалуйста, перенесите to java.time (JSR-310).

Цитируется издомашней страницы Joda-Time .