Jak wyjaśniają inni, istnieje nieciągłość czasowa. Istnieją dwa możliwe przesunięcia strefy czasowej dla 1927-12-31 23:54:08
o Asia/Shanghai
, ale tylko jedno przesunięcie dla 1927-12-31 23:54:07
. Tak więc, w zależności od zastosowanego przesunięcia, występuje różnica jednej sekundy lub różnica 5 minut i 53 sekund.
Ta niewielka zmiana przesunięć, zamiast zwykłej jednogodzinnej oszczędności światła dziennego (czasu letniego), do której jesteśmy przyzwyczajeni, nieco zaciemnia problem.
Należy zauważyć, że aktualizacja bazy danych strefy czasowej 2013a przesunęła tę nieciągłość kilka sekund wcześniej, ale efekt byłby nadal widoczny.
Nowy java.time
pakiet w Javie 8 pozwala lepiej to zobaczyć i zapewnia narzędzia do obsługi. Dany:
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());
Następnie durationAtEarlierOffset
będzie jedną sekundę, natomiast durationAtLaterOffset
będzie pięć minut i 53 sekund.
Te dwa przesunięcia są takie same:
// Both have offsets +08:05:52
ZoneOffset zo3Earlier = zdt3.withEarlierOffsetAtOverlap().getOffset();
ZoneOffset zo3Later = zdt3.withLaterOffsetAtOverlap().getOffset();
Ale te dwa są różne:
// +08:05:52
ZoneOffset zo4Earlier = zdt4.withEarlierOffsetAtOverlap().getOffset();
// +08:00
ZoneOffset zo4Later = zdt4.withLaterOffsetAtOverlap().getOffset();
Możesz zobaczyć ten sam problem w porównaniu 1927-12-31 23:59:59
z tym 1928-01-01 00:00:00
, jednak w tym przypadku to wcześniejsze przesunięcie powoduje dłuższe rozbieżności i wcześniejsza data ma dwa możliwe przesunięcia.
Innym sposobem podejścia do tego jest sprawdzenie, czy zachodzi przejście. Możemy to zrobić w następujący sposób:
// Null
ZoneOffsetTransition zot3 = shanghai.getRules().getTransition(ld3.toLocalDateTime);
// An overlap transition
ZoneOffsetTransition zot4 = shanghai.getRules().getTransition(ld3.toLocalDateTime);
Możesz sprawdzić, czy przejście jest pokrywające się, gdy istnieje więcej niż jedno prawidłowe przesunięcie dla tej daty / godziny, czy przerwa, w której ta data / czas nie jest ważna dla tego identyfikatora strefy - przy użyciu metod isOverlap()
i .isGap()
zot4
Mam nadzieję, że pomoże to ludziom poradzić sobie z tego rodzaju problemami, gdy Java 8 stanie się powszechnie dostępna, lub osobom używającym Java 7, które przyjmą backport JSR 310.