Java 8时区API获得下一个过渡,而莫斯科1991年未返回DST更改

时间:2019-06-28 01:38:28

标签: java timezone dst

java.time.zone.ZoneRules#nextTransition未返回欧洲/莫斯科1991年的夏令时更改,我无法获得欧洲/莫斯科1991年的夏令时边界。 欧洲/莫斯科entered daylight saving on 1991-03-31 02:00 but also changed their standard offset,因此偏移量(+03:00)保持不变,而没有Java API可用于获取DST开始的边界。

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.zone.ZoneOffsetTransition;

public class TimeUtilTest {
    public static void main(String[] args) {
        ZoneId tz = ZoneId.of("Europe/Moscow");
        ZonedDateTime yearBegin = ZonedDateTime.of(1991, 1, 1, 0, 0, 0, 0, tz);
        ZoneOffsetTransition nextTransition = tz.getRules().nextTransition(yearBegin.toInstant());
        System.out.println("year begin isDST=" + tz.getRules().isDaylightSavings(yearBegin.toInstant()));
        System.out.println("next transition before is " + nextTransition.getDateTimeBefore() + " isDST=" + tz.getRules()
                .isDaylightSavings(nextTransition.getInstant().minusNanos(1)));
        System.out.println("next transition after is " + nextTransition.getDateTimeAfter() + " isDST=" + tz.getRules()
                .isDaylightSavings(nextTransition.getInstant().plusNanos(1)));
    }
}

它在下面返回

year begin isDST=false
next transition before is 1991-09-29T03:00 isDST=true
next transition after is 1991-09-29T02:00 isDST=false

您可以在其中看到isDST在过渡之前发生了意外更改。

1 个答案:

答案 0 :(得分:2)

您的观察是正确的。

确认1991年3月更改的一种方法是:在timeanddate.com的“时区和时钟更改”页面上(请参阅底部的链接),从下拉列表中选择1990-1999。我引用:

Year    Date & Time             Abbreviation    Time Change                         Offset After
1991    søn 31. mar, kl. 02.00  MSK → EEST      No offset (DST start, TZ change)    UTC+3h

Java区域规则以过渡(间隙(时钟指针朝前)或重叠(时钟向后))建模。由于1991年3月在莫斯科均未发生过,区划规则无法真正模拟过渡,因此显然已选择将其忽略。也许我们可能想象彼此之间存在间隙和重叠并相互平衡,但是我也不认为这会起作用。

Java确实知道有关更改。尝试例如

    ZoneRules moscowRules = tz.getRules();
    Instant justBeforeChange = ZonedDateTime.of(1991, 3, 31, 1, 59, 59, 999_999_999, tz).toInstant();
    System.out.println(moscowRules.getStandardOffset(justBeforeChange));
    System.out.println(moscowRules.isDaylightSavings(justBeforeChange));
    Instant onChange = ZonedDateTime.of(1991, 3, 31, 2, 0, 0, 0, tz).toInstant();
    System.out.println(moscowRules.getStandardOffset(onChange));
    System.out.println(moscowRules.isDaylightSavings(onChange));

此打印:

+03:00
false
+02:00
true

不过,您也很正确,无法直接查询ZoneRules对象有关此更改何时发生的信息。如果需要这样做,二进制搜索会将其范围缩小到1991-03-30T23:00:00Z,与1991-03-31T02:00:00 + 03:00相同。

在您的问题中,我没有真正看到清晰的问题,也不确定您从答案中得出的确切结果。

链接