Як пояснили інші, там спостерігається розрив часу. Є два можливих зміщення часових поясів для 1927-12-31 23:54:08
на Asia/Shanghai
, але тільки один зсув 1927-12-31 23:54:07
. Отже, залежно від того, який зсув використовується, є різниця в одній секунді або різниця в 5 хвилин та 53 секунди.
Ця незначна зміна компенсацій замість звичної одногодинної економії дня (літній час), до якої ми звикли, трохи затьмарює проблему.
Зауважте, що оновлення бази даних часових поясів у 2013 році перенесло цю розрив на кілька секунд раніше, але ефект все-таки буде помітний.
Новий java.time
пакет на Java 8 дозволяє зрозуміти це більш чітко та надавати інструменти для його роботи. Подано:
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());
Потім durationAtEarlierOffset
буде одна секунда, тоді як durationAtLaterOffset
буде п’ять хвилин і 53 секунди.
Також ці два компенсації однакові:
// Both have offsets +08:05:52
ZoneOffset zo3Earlier = zdt3.withEarlierOffsetAtOverlap().getOffset();
ZoneOffset zo3Later = zdt3.withLaterOffsetAtOverlap().getOffset();
Але ці два різні:
// +08:05:52
ZoneOffset zo4Earlier = zdt4.withEarlierOffsetAtOverlap().getOffset();
// +08:00
ZoneOffset zo4Later = zdt4.withLaterOffsetAtOverlap().getOffset();
Ви можете побачити ту саму проблему, що і в порівнянні 1927-12-31 23:59:59
з цим 1928-01-01 00:00:00
, хоча в цьому випадку більш раннє розмежування призводить до більш раннього зміщення, і більш ранньої дати є два можливі компенсації.
Ще один спосіб підійти до цього - перевірити, чи відбувається перехід. Ми можемо зробити це так:
// Null
ZoneOffsetTransition zot3 = shanghai.getRules().getTransition(ld3.toLocalDateTime);
// An overlap transition
ZoneOffsetTransition zot4 = shanghai.getRules().getTransition(ld3.toLocalDateTime);
Ви можете перевірити, чи є перехід збігом, коли існує більше одного дійсного зміщення на цю дату / час, або проміжок, коли ця дата / час не є дійсним для цього ідентифікатора зони - за допомогою isOverlap()
та isGap()
методів на zot4
.
Я сподіваюся, що це допомагає людям вирішувати подібні проблеми, коли Java 8 стає широкодоступною, або тим, хто використовує Java 7, який приймає репортер JSR 310.