Seperti yang dijelaskan oleh orang lain, ada diskontinuitas waktu di sana. Ada dua kemungkinan zona waktu untuk 1927-12-31 23:54:08
at Asia/Shanghai
, tetapi hanya satu offset untuk 1927-12-31 23:54:07
. Jadi, tergantung pada offset mana yang digunakan, ada perbedaan satu detik atau 5 menit dan 53 detik.
Pergeseran sedikit offset ini, alih-alih penghematan siang hari satu jam (waktu musim panas) yang biasa kita gunakan, mengaburkan masalah sedikit.
Perhatikan bahwa pembaruan database zona waktu 2013a memindahkan diskontinuitas ini beberapa detik sebelumnya, tetapi efeknya masih dapat diamati.
java.time
Paket baru pada Java 8 memungkinkan penggunaan melihat ini lebih jelas, dan menyediakan alat untuk menanganinya. Diberikan:
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());
Maka durationAtEarlierOffset
akan menjadi satu detik, sedangkan durationAtLaterOffset
akan menjadi lima menit dan 53 detik.
Juga, kedua offset ini adalah sama:
// Both have offsets +08:05:52
ZoneOffset zo3Earlier = zdt3.withEarlierOffsetAtOverlap().getOffset();
ZoneOffset zo3Later = zdt3.withLaterOffsetAtOverlap().getOffset();
Tetapi keduanya berbeda:
// +08:05:52
ZoneOffset zo4Earlier = zdt4.withEarlierOffsetAtOverlap().getOffset();
// +08:00
ZoneOffset zo4Later = zdt4.withLaterOffsetAtOverlap().getOffset();
Anda dapat melihat masalah yang sama 1927-12-31 23:59:59
dengan membandingkan 1928-01-01 00:00:00
, meskipun, dalam kasus ini, offset sebelumnya yang menghasilkan divergensi yang lebih panjang, dan tanggal sebelumnya yang memiliki dua kemungkinan offset.
Cara lain untuk mendekati ini adalah untuk memeriksa apakah ada transisi yang sedang berlangsung. Kita bisa melakukan ini seperti ini:
// Null
ZoneOffsetTransition zot3 = shanghai.getRules().getTransition(ld3.toLocalDateTime);
// An overlap transition
ZoneOffsetTransition zot4 = shanghai.getRules().getTransition(ld3.toLocalDateTime);
Anda dapat memeriksa apakah transisi merupakan tumpang tindih di mana ada lebih dari satu offset yang valid untuk tanggal / waktu itu atau celah di mana tanggal / waktu itu tidak valid untuk id zona itu - dengan menggunakan isOverlap()
dan isGap()
metode pada zot4
.
Saya harap ini membantu orang menangani masalah ini begitu Java 8 tersedia secara luas, atau bagi mereka yang menggunakan Java 7 yang mengadopsi JSR 310 backport.