我目前正在查看日期在英国夏令时内外的ZonedDateTime行为。
英国夏令时从3月25日开始,增加一小时(+1)。
我创建了ZonedDateTime(UTC和欧洲/伦敦)的几个实例,然后我在1个月内添加了它们,以便它们落入ZonedDateTime。
// These dates will be outside British Summer Time
ZonedDateTime utcFirstMarch = ZonedDateTime.of(2018, 3, 1, 12, 0, 0, 0, ZoneId.of("UTC"));
ZonedDateTime londonFirstMarch = ZonedDateTime.of(2018, 3, 1, 12, 0, 0, 0, ZoneId.systemDefault());
// These dates will be inside British Summer Time
ZonedDateTime utcFirstMarchPlusMonth = ZonedDateTime.of(2018, 3, 1, 12, 0, 0, 0, ZoneId.of("UTC")).plusMonths(1);
ZonedDateTime londonFirstMarchPlusMonth = ZonedDateTime.of(2018, 3, 1, 12, 0, 0, 0, ZoneId.systemDefault()).plusMonths(1);
ZonedDateTime londonFirstMarchPlusMonthToUtc = ZonedDateTime.of(2018, 3, 1, 12, 0, 0, 0, ZoneId.systemDefault()).plusMonths(1).withZoneSameInstant(ZoneId.of("UTC"));
这是打印这些日期时的结果:
utcFirstMarch: 2018-03-01T12:00Z[UTC]
londonFirstMarch: 2018-03-01T12:00Z[Europe/London]
utcFirstMarchPlusMonth: 2018-04-01T12:00Z[UTC]
londonFirstMarchPlusMonth: 2018-04-01T12:00+01:00[Europe/London]
londonFirstMarchPlusMonthToUtc: 2018-04-01T11:00Z[UTC]
最后,我打印了每个日期的纪元秒:
utcFirstMarch: 1519905600
londonFirstMarch: 1519905600
utcFirstMarchPlusMonth: 1522584000
londonFirstMarchPlusMonth: 1522580400
londonFirstMarchPlusMonthToUtc: 1522580400
我知道ZonedDateTime是不可变的。这意味着当我添加一个月时,我实际上创建了一个月更改的新实例。能否请您告诉我对给定观察结果的假设是否正确:
添加一个月将创建ZonedDateTime的新实例。 ZonedDateTime上的小时将始终相同。新日期是否在BST中无关紧要。 (看看LondonFirstMarch和LondonFirstMarchPlusMonth)
因为在加入1个月后,londonFirstMarchPlusMonth落入BST以使其仍然是12:00,它实际上提取了一个小时。这意味着底层纪元秒将与utcFirstMarchPlusMonth不同。
最后,当我们将区域转换为UTC时,londonFirstMarchPlusMonthToUtc显示实际小时为11:00。
修改
也许我不够清楚 - 道歉。一个月是任意值,因此当添加到第一个日期时,产生第二个日期属于BST。
如上所述,也许一个月不是一个很好的例子,因为它取决于我们所处的月份,这意味着不同的事情。对我来说,“月份”将由24小时单位组成。 (正如Ole.v.v.所说)
我认为按UTC时间运行并可选择将其转换为欧洲/伦敦是“我的问题”的解决方案
答案 0 :(得分:2)
您的假设通常是正确的。一些评论。
对于1.,ZonedDateTime
将尝试保持小时相同。只有在不可能的情况下,它才会做其他事情。例如,可能希望以下内容打印时间01:30:
System.out.println(ZonedDateTime
.of(2018, 2, 25, 1, 30, 0, 0, ZoneId.of("Europe/London"))
.plusMonths(1));
打印
2018-03-25T02:30+01:00[Europe/London]
在过渡到夏令时时间从1点到凌晨2点向前移动,因此那天 没有时间是1:30。 ZonedDateTime
不会产生不存在的时间,因此在这种情况下它会选择02:30。
对于4,“恰好一个月”有点难以严格定义,因为一个月可能是28天,29天,30天或31天。但是如果你想要24小时的倍数,那么使用UTC会给你这个。
答案 1 :(得分:-3)
我建议您使用Period
个实例来表达DateFormat
的正确行为:
ZonedDateTime nZoneDateTime = utcFirstMarch.plus(Period.ofDays(30));