Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

java

timezone

dst

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.

like image 771
Lyx St Avatar asked Jun 28 '19 01:06

Lyx St


People also ask

How do I change the TimeZone in Java 8?

Typically, you get a TimeZone using getDefault which creates a TimeZone based on the time zone where the program is running. For example, for a program running in Japan, getDefault creates a TimeZone object based on Japanese Standard Time. Hours must be between 0 to 23 and Minutes must be between 00 to 59.

How does Java handle daylight savings code?

The right way to handle DST in Java is to instantiate a Timezone with a specific TZDB Timezone ID, eg. “Europe/Rome”. Then, we'll use this in conjunction with time-specific classes like java. util.

What is default TimeZone in Java?

By default, the JVM reads time zone information from the operating system. This information gets passed to the TimeZone class, which stores the time zone and calculates the daylight saving time. We can call the method getDefault, which will return the time zone where the program is running.

What is daylight saving in Java?

The observesDaylightTime() method of TimeZone class in Java is used to check and verify whether the given date is in daylight saving time or if any transition from Standard Time to Daylight Saving Time will occur at any future time. Syntax: public boolean observesDaylightTime()


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

  • Time Changes in Moscow Over the Years on timeanddate.com
like image 186
Ole V.V. Avatar answered Sep 28 '22 07:09

Ole V.V.