夏令时 - Java

Daylight Saving Time - Java

我有以下时区 "2021-06-06T06:00+01:00[Europe/London]"

当我在那个时区调用 toInstant() 时,我得到“2021-06-06T05:00”。时钟向前走,为什么它会在早上 5 点返回?我想早上 7 点而不是早上 5 点。

最小可重现示例:

    ZonedDateTime zoned = ZonedDateTime.of(
            2021, 6, 6, 6, 0, 0, 0, ZoneId.of("Europe/London"));
    System.out.println(zoned);
    System.out.println(zoned.toInstant());

预期输出:2021-06-06T07:00

观察到的输出:

2021-06-06T06:00+01:00[Europe/London]
2021-06-06T05:00:00Z

2021-06-06T06:00+01:00 =
2021-06-06T05:00+00:00

这就是时区偏移量的定义方式,例如检查 Wikipedia

+01:00 的时区指示符表示给定时间在 UTC 前 1 小时的时区,这意味着 UTC 中的同一时间是给定时间减 1 小时。

因此 2021-06-06T06:00+01:002021-06-06T05:00+00:00 是同一时刻,如果没有夏令时,当天会早 1 小时。

ZonedDateTime
.parse( "2021-06-06T06:00+01:00[Europe/London]" )
.toInstant()
.toString()

看到这个code run live at IdeOne.com

2021-06-06T05:00:00Z

代码 1

ZoneId tzLondon = ZoneId.of("Europe/London");
ZonedDateTime zonedDateTime = ZonedDateTime.of(2021, 6, 6, 6, 0, 0, 0, tzLondon);
Instant instant = zonedDateTime.toInstant();
System.out.println("  zoned: " + zonedDateTime);
System.out.println("instant: " + instant);

输出 1

  zoned: 2021-06-06T06:00+01:00[Europe/London]
instant: 2021-06-06T05:00:00Z

分区输出是基于时区Europe/London,在夏令时(DST)期间是GMT+1,这就是为什么它似乎在即时输出后1小时( 05:00 + 1 小时 = 06:00)。但是两个输出代表相同的时间点,只是格式不同。

通常在 Java 中,您不会直接处理 DST 计算,因为 Java 会为您完成。当您从上面获取 ZonedDateTime 并添加几个月时,您可以看到这一点。

代码 2

ZonedDateTime zonedDateTimeAFewMonthsLater = zonedDateTime.plusMonths(5);
Instant instantAFewMonthsLater = zonedDateTimeAFewMonthsLater.toInstant();
System.out.println("A few months later   (zoned): " + zonedDateTimeAFewMonthsLater);
System.out.println("A few months later (instant): " + instantAFewMonthsLater);

输出 2

A few months later   (zoned): 2021-11-06T06:00Z[Europe/London]
A few months later (instant): 2021-11-06T06:00:00Z

但是,如果您真的很想将 ZonedDateTime 从 06:00 修补到 07:00,这取决于它的 DST 属性,您可以这样做。但是很脏。

代码 3

Duration dstDuration = zonedDateTime.getZone().getRules().getDaylightSavings(instant);
ZonedDateTime dstPatchedZonedDateTime = zonedDateTime.plus(dstDuration);
System.out.println("DST patched: " + dstPatchedZonedDateTime);

输出 3

DST patched: 2021-06-06T07:00+01:00[Europe/London]