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