As explained by others, there's a time discontinuity there.there are two possible timezone offsets for
1927-12-31 23:54:08 at
Asia/Shanghai, but only one offset for
1927-12-31 23:54:07.So, depending on which offset is used, there's either a one second difference or a 5 minutes and 53 seconds difference.
This slight shift of offsets, instead of the usual one-hour daylight savings (summer time) we are used to, obscures the problem a bit.
Note that the 2013 a update of the timezone database moved this discontinuity a few seconds earlier, but the effect would still be observable.
java.time package on Java 8 let use see this more clearly, and provide tools to handle it.Given :
DateTimeFormatterBuilder dtfb = new DateTimeFormatterBuilder();
DateTimeFormatter dtf = dtfb.toFormatter();
ZoneId shanghai = ZoneId.of("Asia/Shanghai");
String str3 ="1927-12-31 23:54:07";
String str4 ="1927-12-31 23:54:08";
ZonedDateTime zdt3 = LocalDateTime.parse(str3, dtf).atZone(shanghai);
ZonedDateTime zdt4 = LocalDateTime.parse(str4, dtf).atZone(shanghai);
Duration durationAtEarlierOffset = Duration.between(zdt3.withEarlierOffsetAtOverlap(), zdt4.withEarlierOffsetAtOverlap());
Duration durationAtLaterOffset = Duration.between(zdt3.withLaterOffsetAtOverlap(), zdt4.withLaterOffsetAtOverlap());
durationAtEarlierOffset will be one second, while
durationAtLaterOffset will be five minutes and 53 seconds.
Also, these two offsets are the same :
//Both have offsets +08:05:52
ZoneOffset zo3Earlier = zdt3.withEarlierOffsetAtOverlap().getOffset();
ZoneOffset zo3Later = zdt3.withLaterOffsetAtOverlap().getOffset();
But these two are different :
ZoneOffset zo4Earlier = zdt4.withEarlierOffsetAtOverlap().getOffset();
ZoneOffset zo4Later = zdt4.withLaterOffsetAtOverlap().getOffset();
You can see the same problem comparing
1927-12-31 23:59:59 with
1928-01-01 00:00:00, though, in this case, it is the earlier offset that produce the longer divergence, and it is the earlier date that has two possible offsets.
Another way to approach this is to check whether there's a transition going on.we can do this like this :
ZoneOffsetTransition zot3 = shanghai.getRules().getTransition(ld3.toLocalDateTime);
//An overlap transition
ZoneOffsetTransition zot4 = shanghai.getRules().getTransition(ld3.toLocalDateTime);
You can check whether the transition is an overlap - in which case there's more than one valid offset for that date/time - or a gap - in which case that date/time is not valid for that zone id - by using the
isGap() methods on
I hope this helps people handle this sort of issue once Java 8 becomes widely available, or to those using Java 7 who adopt the JSR 310 backport.