【问题标题】:Determine daylight saving time for US ZoneIds in Java在 Java 中确定美国 ZoneId 的夏令时
【发布时间】:2018-08-21 18:41:48
【问题描述】:

我需要确定 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

【问题讨论】:

    标签: java timezone dst java-time


    【解决方案1】:

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

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

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

    这将打印:

    过渡[重叠于 2018-11-04T02: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-04T02:00-04:00 到 -05:00 重叠]

    【讨论】:

    • 非常感谢!实际上我想选择 12 月 1 日,但是 ZonedDateTime 中的月份不再从 0 开始(就像在 java.util.Date 和 Calendar 中一样)。
    • 不幸的是,这仍然是一个常见的错误。我真的很讨厌这个从 0 开始的月份的事情......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-04
    • 2012-05-10
    • 2018-07-06
    • 2016-11-01
    • 1970-01-01
    • 2019-09-29
    • 2015-08-15
    相关资源
    最近更新 更多