Como explicaron otros, hay una discontinuidad de tiempo allí. Hay dos posibles compensaciones de zona horaria para 1927-12-31 23:54:08
at Asia/Shanghai
, pero solo una compensación para 1927-12-31 23:54:07
. Entonces, dependiendo de qué desplazamiento se use, hay una diferencia de un segundo o una diferencia de 5 minutos y 53 segundos.
Este ligero cambio de compensaciones, en lugar del habitual horario de verano de una hora (horario de verano), oscurece un poco el problema.
Tenga en cuenta que la actualización 2013a de la base de datos de zonas horarias movió esta discontinuidad unos segundos antes, pero el efecto aún sería observable.
El nuevo java.time
paquete en Java 8 permite ver esto más claramente y proporciona herramientas para manejarlo. Dado:
DateTimeFormatterBuilder dtfb = new DateTimeFormatterBuilder();
dtfb.append(DateTimeFormatter.ISO_LOCAL_DATE);
dtfb.appendLiteral(' ');
dtfb.append(DateTimeFormatter.ISO_LOCAL_TIME);
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());
Luego durationAtEarlierOffset
será un segundo, mientras durationAtLaterOffset
que serán cinco minutos y 53 segundos.
Además, estas dos compensaciones son las mismas:
// Both have offsets +08:05:52
ZoneOffset zo3Earlier = zdt3.withEarlierOffsetAtOverlap().getOffset();
ZoneOffset zo3Later = zdt3.withLaterOffsetAtOverlap().getOffset();
Pero estos dos son diferentes:
// +08:05:52
ZoneOffset zo4Earlier = zdt4.withEarlierOffsetAtOverlap().getOffset();
// +08:00
ZoneOffset zo4Later = zdt4.withLaterOffsetAtOverlap().getOffset();
Se puede ver el mismo problema comparando 1927-12-31 23:59:59
con 1928-01-01 00:00:00
, sin embargo, en este caso, es la compensación temprana que produce la divergencia más tiempo, y es la fecha más temprana que tiene dos posibles desplazamientos.
Otra forma de abordar esto es verificar si hay una transición en curso. Podemos hacer esto así:
// Null
ZoneOffsetTransition zot3 = shanghai.getRules().getTransition(ld3.toLocalDateTime);
// An overlap transition
ZoneOffsetTransition zot4 = shanghai.getRules().getTransition(ld3.toLocalDateTime);
Puede verificar si la transición es una superposición donde hay más de un desplazamiento válido para esa fecha / hora o una brecha donde esa fecha / hora no es válida para esa identificación de zona, utilizando los métodos isOverlap()
y isGap()
en zot4
.
Espero que esto ayude a las personas a manejar este tipo de problemas una vez que Java 8 esté ampliamente disponible, o para aquellos que usan Java 7 que adopten el backport JSR 310.