基于 LocalDateTime 创建 ZonedDateTime 实例的问题
Issue creating ZonedDateTime instance based on LocalDateTime
我看到一些我无法解释的行为,希望有人能给我指出正确的方向。
我首先创建一个 LocalDateTime 实例,然后通过将 "Europe/London" 时区应用于 LocalDateTime 来获取 ZonedDateTime,然后使用 DateTimeFormatter 打印输出。我希望看到的时间与 LocalDateTime 实例中指定的时间完全相同,但在下面的示例中,zonedDateTimeBeforeDST_Original 的输出比我预期的晚了一个小时。
所以,简而言之:为什么我的 LocalDateTime 中的 01:55 变成 ZonedDateTime 中的 02:55?
仅供参考,在其他时区没有看到这种行为。伦敦的好像是个特例。
//init date pattern
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
final DateTimeFormatter formatterOut = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss XXX");
LocalDateTime localDateTimeBeforeDST = LocalDateTime.parse("2018-03-25 01:55:00", formatter); //testing with time 5 minutes before DST switch or after
System.out.println("LocalDateTime: " + localDateTimeBeforeDST.format(formatter));
System.out.println();
String originalZone = "Europe/London";
ZoneId originalZoneId = ZoneId.of(originalZone);
ZoneId utcZoneId = ZoneId.of("Etc/UTC");
ZoneId localZoneId = ZoneId.of("Europe/London");
ZoneId localZoneId_2 = ZoneId.of("Europe/Brussels");
ZonedDateTime zonedDateTimeBeforeDST_Original = localDateTimeBeforeDST.atZone(originalZoneId);
ZonedDateTime zonedDateTimeBeforeDST_UTC = zonedDateTimeBeforeDST_Original.withZoneSameInstant(utcZoneId);
ZonedDateTime zonedDateTimeBeforeDST_1 = zonedDateTimeBeforeDST_UTC.withZoneSameInstant(localZoneId);
ZonedDateTime zonedDateTimeBeforeDST_2 = zonedDateTimeBeforeDST_UTC.withZoneSameInstant(localZoneId_2);
System.out.println("Instant: " + zonedDateTimeBeforeDST_Original.toEpochSecond());
System.out.println();
System.out.println("ZonedDateTime (" + originalZone + "): " + zonedDateTimeBeforeDST_Original.format(formatterOut));
System.out.println("ZonedDateTime (Etc/UTC): " + zonedDateTimeBeforeDST_UTC.format(formatterOut));
System.out.println("ZonedDateTime (Europe/London): " + zonedDateTimeBeforeDST_1.format(formatterOut));
System.out.println("ZonedDateTime (Europe/Brussels): " + zonedDateTimeBeforeDST_2.format(formatterOut));
System.out.println();
zonedDateTimeBeforeDST_Original = zonedDateTimeBeforeDST_Original.plus(10, ChronoUnit.MINUTES);
zonedDateTimeBeforeDST_UTC = zonedDateTimeBeforeDST_Original.withZoneSameInstant(utcZoneId);
zonedDateTimeBeforeDST_1 = zonedDateTimeBeforeDST_UTC.withZoneSameInstant(localZoneId);
zonedDateTimeBeforeDST_2 = zonedDateTimeBeforeDST_UTC.withZoneSameInstant(localZoneId_2);
System.out.println("ZonedDateTime (DST) (" + originalZone + "): " + zonedDateTimeBeforeDST_Original.format(formatterOut));
System.out.println("ZonedDateTime (DST) (Etc/UTC): " + zonedDateTimeBeforeDST_UTC.format(formatterOut));
System.out.println("ZonedDateTime (DST) (Europe/London): " + zonedDateTimeBeforeDST_1.format(formatterOut));
System.out.println("ZonedDateTime (DST) (Europe/Brussels): " + zonedDateTimeBeforeDST_2.format(formatterOut));
输出:
LocalDateTime: 2018-03-25 01:55:00
Instant: 1521942900
ZonedDateTime (Europe/London): 2018-03-25 02:55:00 +01:00
ZonedDateTime (Etc/UTC): 2018-03-25 01:55:00 Z
ZonedDateTime (Europe/London): 2018-03-25 02:55:00 +01:00
ZonedDateTime (Europe/Brussels): 2018-03-25 03:55:00 +02:00
ZonedDateTime (DST) (Europe/London): 2018-03-25 03:05:00 +01:00
ZonedDateTime (DST) (Etc/UTC): 2018-03-25 02:05:00 Z
ZonedDateTime (DST) (Europe/London): 2018-03-25 03:05:00 +01:00
ZonedDateTime (DST) (Europe/Brussels): 2018-03-25 04:05:00 +02:00
这是夏令时 (DST) 问题。当英国开始夏令时,时钟从 1 拨到 2 时,没有 2018-03-25 01:55:00。 ZonedDateTime
不会给你一个不存在的时间,所以它选择了一个现有的时间。
具体选择哪个时间在the documentation of LocalDateTime.atZone
中指定:
In the case of a gap, where clocks jump forward, there is no valid
offset. Instead, the local date-time is adjusted to be later by the
length of the gap. For a typical one hour daylight savings change, the
local date-time will be moved one hour later into the offset typically
corresponding to "summer".
当然,在使用夏令时的其他时区也会发生同样的事情。只有每个时区都有自己的过渡时间,通常与 2018 年 3 月 25 日星期日 01:00.
不一致
我看到一些我无法解释的行为,希望有人能给我指出正确的方向。
我首先创建一个 LocalDateTime 实例,然后通过将 "Europe/London" 时区应用于 LocalDateTime 来获取 ZonedDateTime,然后使用 DateTimeFormatter 打印输出。我希望看到的时间与 LocalDateTime 实例中指定的时间完全相同,但在下面的示例中,zonedDateTimeBeforeDST_Original 的输出比我预期的晚了一个小时。
所以,简而言之:为什么我的 LocalDateTime 中的 01:55 变成 ZonedDateTime 中的 02:55?
仅供参考,在其他时区没有看到这种行为。伦敦的好像是个特例。
//init date pattern
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
final DateTimeFormatter formatterOut = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss XXX");
LocalDateTime localDateTimeBeforeDST = LocalDateTime.parse("2018-03-25 01:55:00", formatter); //testing with time 5 minutes before DST switch or after
System.out.println("LocalDateTime: " + localDateTimeBeforeDST.format(formatter));
System.out.println();
String originalZone = "Europe/London";
ZoneId originalZoneId = ZoneId.of(originalZone);
ZoneId utcZoneId = ZoneId.of("Etc/UTC");
ZoneId localZoneId = ZoneId.of("Europe/London");
ZoneId localZoneId_2 = ZoneId.of("Europe/Brussels");
ZonedDateTime zonedDateTimeBeforeDST_Original = localDateTimeBeforeDST.atZone(originalZoneId);
ZonedDateTime zonedDateTimeBeforeDST_UTC = zonedDateTimeBeforeDST_Original.withZoneSameInstant(utcZoneId);
ZonedDateTime zonedDateTimeBeforeDST_1 = zonedDateTimeBeforeDST_UTC.withZoneSameInstant(localZoneId);
ZonedDateTime zonedDateTimeBeforeDST_2 = zonedDateTimeBeforeDST_UTC.withZoneSameInstant(localZoneId_2);
System.out.println("Instant: " + zonedDateTimeBeforeDST_Original.toEpochSecond());
System.out.println();
System.out.println("ZonedDateTime (" + originalZone + "): " + zonedDateTimeBeforeDST_Original.format(formatterOut));
System.out.println("ZonedDateTime (Etc/UTC): " + zonedDateTimeBeforeDST_UTC.format(formatterOut));
System.out.println("ZonedDateTime (Europe/London): " + zonedDateTimeBeforeDST_1.format(formatterOut));
System.out.println("ZonedDateTime (Europe/Brussels): " + zonedDateTimeBeforeDST_2.format(formatterOut));
System.out.println();
zonedDateTimeBeforeDST_Original = zonedDateTimeBeforeDST_Original.plus(10, ChronoUnit.MINUTES);
zonedDateTimeBeforeDST_UTC = zonedDateTimeBeforeDST_Original.withZoneSameInstant(utcZoneId);
zonedDateTimeBeforeDST_1 = zonedDateTimeBeforeDST_UTC.withZoneSameInstant(localZoneId);
zonedDateTimeBeforeDST_2 = zonedDateTimeBeforeDST_UTC.withZoneSameInstant(localZoneId_2);
System.out.println("ZonedDateTime (DST) (" + originalZone + "): " + zonedDateTimeBeforeDST_Original.format(formatterOut));
System.out.println("ZonedDateTime (DST) (Etc/UTC): " + zonedDateTimeBeforeDST_UTC.format(formatterOut));
System.out.println("ZonedDateTime (DST) (Europe/London): " + zonedDateTimeBeforeDST_1.format(formatterOut));
System.out.println("ZonedDateTime (DST) (Europe/Brussels): " + zonedDateTimeBeforeDST_2.format(formatterOut));
输出:
LocalDateTime: 2018-03-25 01:55:00
Instant: 1521942900
ZonedDateTime (Europe/London): 2018-03-25 02:55:00 +01:00
ZonedDateTime (Etc/UTC): 2018-03-25 01:55:00 Z
ZonedDateTime (Europe/London): 2018-03-25 02:55:00 +01:00
ZonedDateTime (Europe/Brussels): 2018-03-25 03:55:00 +02:00
ZonedDateTime (DST) (Europe/London): 2018-03-25 03:05:00 +01:00
ZonedDateTime (DST) (Etc/UTC): 2018-03-25 02:05:00 Z
ZonedDateTime (DST) (Europe/London): 2018-03-25 03:05:00 +01:00
ZonedDateTime (DST) (Europe/Brussels): 2018-03-25 04:05:00 +02:00
这是夏令时 (DST) 问题。当英国开始夏令时,时钟从 1 拨到 2 时,没有 2018-03-25 01:55:00。 ZonedDateTime
不会给你一个不存在的时间,所以它选择了一个现有的时间。
具体选择哪个时间在the documentation of LocalDateTime.atZone
中指定:
In the case of a gap, where clocks jump forward, there is no valid offset. Instead, the local date-time is adjusted to be later by the length of the gap. For a typical one hour daylight savings change, the local date-time will be moved one hour later into the offset typically corresponding to "summer".
当然,在使用夏令时的其他时区也会发生同样的事情。只有每个时区都有自己的过渡时间,通常与 2018 年 3 月 25 日星期日 01:00.
不一致