且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Java 8日期时间:从ZonedDateTime获取一天的开始

更新时间:2021-11-04 01:53:44

为了更正而更新:

在大多数情况下是相同的,请参阅以下巴西从冬季到夏季切换时的示例:

In most cases yes the same, see following example for Brazil when switching from winter to summer time:

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() -method最终转换回新的 ZonedDateTime 并将时间转移到差距的大小(1小时)。

Truncating happens on the local timeline. If you choose DAYS then you opt for midnight. According to javadoc the truncate()-method finally converts back to the new ZonedDateTime and shifts the time forward by the size of the gap (1 hour).

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

Converting the zdt first to LocalDate (cutting off the time part) and then looking for its ZonedDateTime-part in given timezone is effectively the same for this situation.

但是,对于从夏季时间切换回冬季时间的相反情况,有一个例外(非常感谢@Austin提供了反例)。问题是在重叠期间何时决定使用哪个偏移量。通常设计/指定类 ZonedDateTime 以使用前一个偏移量,另请参阅 Javadoc

However, for the reverse case of switching back from summer time to winter time there is one exception (thanks very much to @Austin who gave a counter example). The problem is during overlap when to decide which offset to be used. Usually the class ZonedDateTime is designed/specified to use the previous offset, see also this excerpt from 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 因此遵循自己的规范,那么这两个程序仍然是等价的意思:

If the class ZonedDateTime would consequently follow its own specification then both procedures would still be equivalent meaning:

zdt.truncatedTo(ChronoUnit.DAYS);

应相当于

zdt.toLocalDate().atStartOfDay().atZone(zdt.getZone()).withEarlierOffsetAtOverlap();

但根据@Austin的例子,我在自己的测试中证实的真实行为是:

But the real behaviour according to the example of @Austin and confirmed by me in own testing is:

zdt.toLocalDate().atStartOfDay().atZone(zdt.getZone()).withLaterOffsetAtOverlap();

类似隐藏的不一致 ZonedDateTime ,温和地说。如果你问我哪种方法更受欢迎,那么我宁愿提倡第二种方法,尽管它更长,需要更多的击键。但它的最大优点是更加透明。更喜欢第二种方法的另一个原因是:

Looks like a hidden inconsistency in the class ZonedDateTime, mildly spoken. If you ask me which method to be preferred then I would rather advocate the second method although it is much longer and requires more keystrokes. But it has the big advantage to be more transparent about what it does. Another reason to prefer the second approach is:

它确实获得当地时间等于一天开始的第一个瞬间。否则,当使用第一种方法时,你必须写:

It really obtains the FIRST instant at which the local time is equal to the start of day. Otherwise, when using first method, you have to write:

zdt.truncatedTo(ChronoUnit.DAYS).withEarlierOffsetAtOverlap();