Java 8 timezone API get next transition not returning DST change in Moscow 1991

Viewed 278

java.time.zone.ZoneRules#nextTransition is not return the DST change of Europe/Moscow 1991, that I cannot get the DST boundary of Europe/Moscow 1991. Europe/Moscow entered daylight saving on 1991-03-31 02:00 but also changed their standard offset, so the offset (+03:00) keep unchanged while no Java API can be used to get such a boundary of DST start.

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)));
    }
}

It returns below

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

where you can see isDST was changed unexpectedly before the transition.

1 Answers

Your observations are correct.

One way to confirm the change in March 1991 is: on the Time Zone and Clock Changes page of timeanddate.com (see the link at the bottom), select 1990 - 1999 from the dropdown. I quote:

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 zone rules are modeled with transitions that are either gaps (clock hands turned forward) or overlaps (clocks turned backward). Since neither happened in Moscow in March 1991, the zone rules cannot really model the transition, so apparently it has been chosen to leave it out. Maybe we might have imagined a gap and an overlap on top of each other and balancing each other out, but I don’t think that would have worked either.

Java does know about the change, though. Try for example

    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));

This prints:

+03:00
false
+02:00
true

You are also correct, though, that there is no way to query the ZoneRules object directly about when this change happened. If you need to do that, a binary search would narrow it down to 1991-03-30T23:00:00Z, the same as 1991-03-31T02:00:00+03:00.

I didn’t really see a clear question in your Question and am unsure what you more precisely had expected from an answer.

Link

Related