Как объяснили другие, там есть временной разрыв.Существует два возможных смещения часового пояса для 1927-12-31 23:54:08
при Asia/Shanghai
, но только одно смещение для 1927-12-31 23:54:07
.Таким образом, в зависимости от того, какое смещение используется, разница составляет либо одну секунду, либо разницу в 5 минут и 53 секунды.
Это небольшое смещение смещений вместо обычного перехода на летнее время в течение одного часа (летнее время).используются, чтобы скрыть проблему немного.
Обратите внимание, что обновление базы данных часовых поясов 2013a переместило этот разрыв на несколько секунд раньше, но эффект все равно будет заметен.
Новый *Пакет 1010 * на 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);
Вы можете проверить, является ли переход перекрытием - в этом случае существует более одного действительного смещения для этой даты / времени - или разрывом - в этом случае эта дата/ time недопустимо для этого идентификатора зоны - с помощью методов isOverlap()
и isGap()
для zot4
.
Я надеюсь, что это поможет людям справиться с такого рода проблемами, как только Java 8 станет широко доступной, илидля тех, кто использует Java 7 и использует обратный порт JSR 310.