Why the seconds between the parsed LocalDateTime variables of timestamp -923130000 and -923130001 is 3599?

110 views Asked by At

Java parse timestamp -923130000 and -923130001 as LocalDateTime failed. The seconds between the two result is 3599. It's too weired.

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;

public class TestLocalDateTime {

    public static void main(String[] args) {
        System.out.println("-923130000: " + toLocalDateTime(-923130000L));
        System.out.println("-923130001: " + toLocalDateTime(-923130001L));

        System.out.println(ChronoUnit.SECONDS.between(toLocalDateTime(-923130000L), toLocalDateTime(-923130001L)));
    }

    private static LocalDateTime toLocalDateTime(Long timestamp) {
        return LocalDateTime.ofInstant(Instant.ofEpochSecond(timestamp), ZoneId.systemDefault());
    }

}

output:

-923130000: 1940-09-30T23:00
-923130001: 1940-09-30T23:59:59
3599

Java version:

$ java -version
java version "1.8.0_191"
Java(TM) SE Runtime Environment (build 1.8.0_191-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, mixed mode)

The code is executed on macOS .

1

There are 1 answers

0
Anonymous On

Apparently a bug in the time zone data

Java 8 and 9 seem to believe that China time zone changed from offset +09:00 to +08:00 at midnight after September 30, 1940, so the second after 23:59:59 would again be 23:00. Time zones showing this include Asia/Chungking, Asia/Shanghai, Asia/Chongqing, PRC and Asia/Harbin.

It also seems that Java is wrong on this point. I checked Shanghai on dateandtime.com, and it knows of no time zone transition in this night. Also I cannot reproduce the same behaviour on Java 11.

One way to see this is using the following code snippet:

    ZoneId zone = ZoneId.of("Asia/Shanghai");
    System.out.println(Instant.ofEpochSecond(-923_130_001L).atZone(zone));
    System.out.println(Instant.ofEpochSecond(-923_130_000L).atZone(zone));

Output on Java 8 and 9:

1940-09-30T23:59:59+09:00[Asia/Shanghai]
1940-09-30T23:00+08:00[Asia/Shanghai]

Output on Java 11:

1940-09-30T23:59:59+09:00[Asia/Shanghai]
1940-10-01T00:00+09:00[Asia/Shanghai]

Assuming you don’t want to upgrade to java 10 or 11 or later immediately the best thing you can do is probably update the time zone database in your current Java 8 installation/s. See Timezone Updater Tool.

Tip of the day: Always prefer ZonedDateTime over LocalDateTime. A ZonedDateTime knows its own time zone and offset. In your situation just printing the ZonedDateTime objects or inspecting them in the debugger would reveal what’s happening. Having the time zone be part of the date-time object prevents many silly mistakes. A ZonedDateTime can be formatted in any way a LocalDateTime can (and more), so presentation to the user is unchanged.

Link: Time Changes in Shanghai Over the Years