确定Java中US ZoneIds的夏令时

时间:2018-03-13 13:24:19

标签: java timezone dst java-time

我需要知道Instant是否处于DST状态。我希望它能像那样工作:

ZoneId z = ZoneId.of("America/New_York");
ZoneRules zr = z.getRules();
TimeZone tz = TimeZone.getTimeZone(z);

Instant summer = ZonedDateTime.of(2018, 5, 1, 2, 2, 2, 2, z).toInstant();
Instant winter = ZonedDateTime.of(2018, 11, 1, 2, 2, 2, 2, z).toInstant();

System.out.println("ZoneRules winter: " + zr.isDaylightSavings(winter));
System.out.println("ZoneRules summer: " + zr.isDaylightSavings(summer));
System.out.println("TimeZone winter: " + tz.inDaylightTime(Date.from(winter)));
System.out.println("TimeZone summer: " + tz.inDaylightTime(Date.from(summer)));

但我的输出为" America / New_York"和其他美国时区总是:

ZoneRules winter: true
ZoneRules summer: true
TimeZone winter: true
TimeZone summer: true

ZoneRules.getOffset()也始终返回相同的值。

但是,在使用欧洲时区时,我没有看到相同的行为。使用ZoneId.of("Europe/London")ZoneId.of("Europe/Amsterdam"),我得到了预期的结果:

ZoneRules winter: false
ZoneRules summer: true
TimeZone winter: false
TimeZone summer: true

我错过了什么?

以下是一些example code on ideone

1 个答案:

答案 0 :(得分:1)

您的winter变量相当于纽约的 11月1日 st 2018 。但是在2018年,在纽约时区DST ends in November 4th,所以winter变量仍在DST中。

您可以使用nextTransition方法检查下一次转换的时间:

System.out.println(zr.nextTransition(winter));

这将打印:

  

过渡[重叠 2018-11-04 T02:00-04:00至-05:00]

意思是在11月4日 th ,凌晨2点,时钟将在1小时后设置("后退"部分"春季前进/后退规则"),偏移量将从-04:00更改为-05:00

您可以通过创建等效的Instant

来检查
// November 4th, at 02:02 AM (after DST transition)
Instant winter = ZonedDateTime.of(2018, 11, 4, 2, 2, 2, 2, z).toInstant();
System.out.println(zr.isDaylightSavings(winter)); // false

检查转换日期的另一种方法是循环遍历ZoneRules提供的转换:

zr.getTransitions().forEach(System.out::println);

某些区域每年都没有特定的转换(America/New_York的情况),但它们有转换规则(例如" DST从第三个开始) 10月的星期日"),所以如果您使用getTransitions()方法找不到特定年份的转换,您可以查看转换规则:

zr.getTransitionRules().forEach(r -> System.out.println(r.createTransition(2018)));

对于America/New_York,输出为:

  

过渡[2018-03-11T02:00-05:00至-04:00的差距]
  过渡[重叠 2018-11-04 T02:00-04:00至-05:00]