Java 8 日期时间 : get start of day from ZonedDateTime

标签 java datetime java-8 java-time

这些有什么区别吗:

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,那么您选择午夜。根据javadoc truncate() 方法最终转换回新的 ZonedDateTime 并将时间向前移动间隔的大小(1 小时)。

首先将 zdt 转换为 LocalDate(切断时间部分),然后在给定时区中查找其 ZonedDateTime-部分对于这种情况实际上是相同的。

但是,对于从夏令时切换回冬令时的相反情况,有一个异常(exception)(非常感谢@Austin 提供了一个反例)。问题是在重叠期间何时决定使用哪个偏移量。通常类 ZonedDateTime 被设计/指定为使用前一个偏移量,另见 Javadoc 的摘录:

For Overlaps, the general strategy is that if the local date-time falls in the middle of an Overlap, then the previous offset will be retained. If there is no previous offset, or the previous offset is invalid, then the earlier offset is used, typically "summer" time.

如果类 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();

关于Java 8 日期时间 : get start of day from ZonedDateTime,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29143910/

相关文章:

java - 服务器中的 RMI UnmarshalException

java - 我们可以在 Dao 中重新抛出 SQLException 和 ClassNotFound 异常,而不是重新抛出用户定义的异常吗?

python - 多索引 pandas 系列中的 set_codes

java - 基于注释参数创建切入点

java - 当光标位于子组件上时,JPanel 不会生成 MouseEvents

java - 如何从 Java 调用 tabula (JAR)?

Linq 到实体参数化构造函数 Datetime

vb.net - 在sqlite中如何从日期时间中选择?

java - 如何将 Stream<Map<Integer, String>> 转换为映射 java 8

Java IntStream iterate vs generated 何时使用什么?