关于日期:我如何获得一段时间的开始和结束时间?

How can I get the start and end time of a period?

我有一个枚举TimeFrame,它的值类似于:YesterdayLastWeekNextMonth等。

我正在尝试编写一个方法,它接收一个TimeFrame,并返回该时间段的开始和结束日期。

我研究了新的Java 8 EDCOX1×5类,它可以占用一个启动时间和结束时间,但是似乎没有任何干净的方法来检索这些值。

如果不使用List(似乎是错误的数据结构)或一些难看的日期时间算法,我如何能够立即干净地返回开始和结束日期?


不,Period不记录开始/结束时间——它只是用日历的方式表示它们之间的时间量(而不是由Duration表示的"精确时间量")。

听起来基本上你应该创建一个有开始日期和结束日期的类。您仍然可以使用Period来实现这一点,但您可以使用getStartDate()getEndDate()返回LocalDate值。您不需要自己做任何繁重的日期/时间算术-只需计算出开始日期并添加适当的期间,或结束日期并减去适当的期间,具体取决于时间框架。


时光流逝

小心传递"昨天"、"明天"等的枚举值。这引发了几个问题,时区和午夜。

日期和星期几仅在时区上下文中有意义。在任何特定的时刻,日期在全球各地都不尽相同。例如,巴黎午夜过后的几分钟仍然是蒙特利尔的"昨天"。因此,每当你打算"昨天"这样做时,也一定要指定所需/预期的时区。

每个非原子命令和代码行与前一个命令和代码行分别执行。每次执行都需要一段时间,无论时间多么短暂。在任何这些时刻,指定时区的午夜都可能转入新的一天。在午夜的那一刻,你的"昨天"等相对时间标志突然有了一个全新的含义。这一含义可能与早期代码所预期的不同,因为该代码开始时的条件(日期)不同。

所以对我来说,绕过Instant个物体,或者可能是OffsetDateTimeZonedDateTime个物体更为合理。这些日期时间值被冻结,表示时间线上的特定时刻。您以前的原始代码可以验证该值的含义,检查日期是否确实是Friday或某些类似的值。经过这种验证后,该值可以传递给其他代码。现在你不必担心午夜偶尔会发生奇怪的错误。

Java.时间

您不需要构建类或枚举来表示相对时间的意图,例如"昨天"。Java.Times类内置于Java 8和以后,具有用于添加和减去天、周、月的简单读取方法。这些基本上是一行程序,所以直接调用这些plus…minus…方法。

1
2
3
ZonedDateTime now = ZonedDateTime.now();
ZonedDateTime yesterday = now.minusDays( 1 );
ZonedDateTime weekLater = now.plusWeeks( 1 );

该代码隐式地应用了JVM的当前默认时区。最好具体说明。

1
2
ZoneId zoneId = ZoneId.of("America/Montreal" );
ZonedDateTime now = ZonedDateTime.now( zoneId );

您可能只需要没有时间和时区的日期。使用LocalDate

1
LocalDate weekPrior = now.toLocalDate().minusWeeks( 1 );

你可能想得到一天中的第一个时刻。不一定是江户十一〔十三〕年的时候。

1
ZonedDateTime yesterdayStart = now.minusDays( 1 ).toLocalDate().atStartOfDay( zoneId );

如果要表示由一对日期时间值定义的时间跨度,请查看扩展java.time框架的threeten extra项目中的Interval类。这个类跟踪一对Instant对象,这些对象是UTC时间线上的时刻。通过调用toInstant,可以从ZonedDateTime中提取Instant

1
Interval intervalYesterday = Interval.of( yesterdayStart.toInstant() , yesterdayStart.plusDays( 1 ).toInstant() );

要从Instant返回到分区日期时间,请应用ZoneId

1
ZonedDateTime zdt = ZonedDateTime( instant , zoneId );

对于仅限日期的间隔,您需要构建自己的类来存储一对LocalDate对象。我会把它叫做类似于DateRange的东西。

提示:搜索"半开放"以了解跟踪时间跨度的实践,其中从包含开始,而结束是独占的。