得到一天的开始有这些有什么区别:的Java 8日期时间:从ZonedDateTime
zonedDateTime.truncatedTo(ChronoUnit.DAYS);
zonedDateTime.toLocalDate().atStartOfDay(zonedDateTime.getZone());
任何理由,更喜欢一个对其他?
感谢
得到一天的开始有这些有什么区别:的Java 8日期时间:从ZonedDateTime
zonedDateTime.truncatedTo(ChronoUnit.DAYS);
zonedDateTime.toLocalDate().atStartOfDay(zonedDateTime.getZone());
任何理由,更喜欢一个对其他?
感谢
更新了校正的缘故:
在大多数情况下是相同的,看到冬天切换到夏天的时候,为巴西下面的例子:
ZonedDateTime zdt =
ZonedDateTime.of(2015, 10, 18, 0, 30, 0, 0,
ZoneId.of("America/Sao_Paulo")); // switch to summer time
ZonedDateTime zdt1 = zdt.truncatedTo(ChronoUnit.DAYS);
ZonedDateTime zdt2 = zdt.toLocalDate().atStartOfDay(zdt.getZone());
System.out.println(zdt); // 2015-10-18T01:30-02:00[America/Sao_Paulo]
System.out.println(zdt1); // 2015-10-18T01:00-02:00[America/Sao_Paulo]
System.out.println(zdt2); // 2015-10-18T01:00-02:00[America/Sao_Paulo]
期截断情况在当地的时间表上。如果你选择DAYS,那么你选择午夜。根据javadoctruncate()
- 方法最终转换回新的ZonedDateTime
并将时间向前移动差距的大小(1小时)。
首先将zdt转换为LocalDate
(切断时间部分),然后在给定时区中查找其ZonedDateTime
-部分对于这种情况实际上是相同的。
但是,对于从夏令时切换回冬令时的情况,有一个例外(非常感谢@奥斯汀谁反例)。问题出在重叠时决定使用哪个偏移量。通常情况下,类ZonedDateTime
设计/指定使用以前的偏移,也看到Javadoc此摘录:
对于重叠,一般的策略是,如果本地日期,时间 落在重叠的中间,那么之前的偏移量将保留为 。如果没有先前的偏移量,或者先前的偏移量为 无效,则使用较早的偏移量,通常为“夏季”时间。
如果该类ZonedDateTime
将因此走自己的规范,然后这两个过程将仍然是等价的含义:
zdt.truncatedTo(ChronoUnit.DAYS);
应相当于
zdt.toLocalDate().atStartOfDay().atZone(zdt.getZone()).withEarlierOffsetAtOverlap();
但根据实际行为@Austin的例子,并在我自己的测试中确认是:
zdt.toLocalDate().atStartOfDay().atZone(zdt.getZone()).withLaterOffsetAtOverlap();
看起来像是在类ZonedDateTime
中隐含的不一致,说话温和。如果你问我哪种方法是首选,那么我宁愿提倡第二种方法,尽管它要长得多,而且需要更多击键。但它对于它的功能更加透明有很大的好处。偏好第二种方法的另一个原因是:
它确实获得了当地时间等于一天的第一个时刻。否则,在使用第一种方法时,您必须编写:
zdt.truncatedTo(ChronoUnit.DAYS).withEarlierOffsetAtOverlap();
这并不总是正确的!看到我的答案为什么不。 – Austin 2017-01-13 00:54:15
@奥斯汀你的答案似乎是合理的。我会相应地调查并纠正我的答案。 – 2017-01-13 07:46:28
它们略有不同。根据javadocs,truncatedTo()
将尝试在重叠的情况下保留时区,但atStartOfDay()
将查找午夜的首次出现。
例如,古巴恢复夏令时凌晨1点,回落到上午12点。如果您从该转换后的某个时间开始,则atStartOfDay()
将返回上午12点的第一次出现,而truncatedTo()
将返回第二次出现。
ZonedDateTime zdt = ZonedDateTime.of(2016, 11, 6, 2, 0, 0, 0, ZoneId.of("America/Havana"));
ZonedDateTime zdt1 = zdt.truncatedTo(ChronoUnit.DAYS);
ZonedDateTime zdt2 = zdt.toLocalDate().atStartOfDay(zdt.getZone());
System.out.println(zdt); // 2016-11-06T02:00-05:00[America/Havana]
System.out.println(zdt1); // 2016-11-06T00:00-05:00[America/Havana]
System.out.println(zdt2); // 2016-11-06T00:00-04:00[America/Havana]
非常感谢您找到了反例。提高了你的意见并更新了我的答案。 – 2017-01-13 10:48:29
注意,也这样做的另一种方式:
zonedDateTime.with(LocalTime.MIN);
产生相同的结果truncatedTo
这不是一个真正的答案。 – shmosel 2017-10-23 05:41:32
难道他们不能只是把方法'atStartOfDay()'的'ZonedDataTime'类? – Przemek 2016-01-14 08:12:46