Theo giải thích của những người khác, có một sự gián đoạn thời gian ở đó. Có hai độ lệch múi giờ có thể có 1927-12-31 23:54:08
tại Asia/Shanghai
, nhưng chỉ có một độ lệch cho 1927-12-31 23:54:07
. Vì vậy, tùy thuộc vào mức bù nào được sử dụng, sẽ có chênh lệch một giây hoặc chênh lệch 5 phút và 53 giây.
Sự thay đổi nhỏ này của sự bù đắp, thay vì tiết kiệm ánh sáng ban ngày một giờ (thời gian mùa hè) thông thường mà chúng ta đã quen, che khuất vấn đề một chút.
Lưu ý rằng bản cập nhật 2013a của cơ sở dữ liệu múi giờ đã di chuyển sự gián đoạn này vài giây trước đó, nhưng hiệu quả vẫn có thể quan sát được.
java.time
Gói mới trên Java 8 cho phép sử dụng thấy rõ hơn điều này và cung cấp các công cụ để xử lý nó. Được:
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());
Sau đó durationAtEarlierOffset
sẽ là một giây, trong khi durationAtLaterOffset
sẽ là năm phút và 53 giây.
Ngoài ra, hai offset này giống nhau:
// Both have offsets +08:05:52
ZoneOffset zo3Earlier = zdt3.withEarlierOffsetAtOverlap().getOffset();
ZoneOffset zo3Later = zdt3.withLaterOffsetAtOverlap().getOffset();
Nhưng hai cái này thì khác:
// +08:05:52
ZoneOffset zo4Earlier = zdt4.withEarlierOffsetAtOverlap().getOffset();
// +08:00
ZoneOffset zo4Later = zdt4.withLaterOffsetAtOverlap().getOffset();
Tuy nhiên, trong trường hợp này, bạn có thể thấy cùng một vấn đề so 1927-12-31 23:59:59
với 1928-01-01 00:00:00
, trong trường hợp này, chính phần bù trước đó tạo ra sự phân kỳ dài hơn và đó là ngày sớm hơn có hai lần bù trừ có thể xảy ra.
Một cách khác để tiếp cận điều này là kiểm tra xem liệu có sự chuyển đổi đang diễn ra hay không. Chúng ta có thể làm điều này như thế này:
// Null
ZoneOffsetTransition zot3 = shanghai.getRules().getTransition(ld3.toLocalDateTime);
// An overlap transition
ZoneOffsetTransition zot4 = shanghai.getRules().getTransition(ld3.toLocalDateTime);
Bạn có thể kiểm tra xem quá trình chuyển đổi có trùng lặp hay không khi có nhiều hơn một khoảng bù hợp lệ cho ngày / giờ đó hoặc khoảng cách trong đó ngày / giờ đó không hợp lệ cho id vùng đó - bằng cách sử dụng isOverlap()
và isGap()
phương thức trên zot4
.
Tôi hy vọng điều này sẽ giúp mọi người xử lý loại vấn đề này một khi Java 8 trở nên phổ biến rộng rãi hoặc cho những người sử dụng Java 7 sử dụng backport JSR 310.