我怎样才能得到一个时期的开始和结束时间?

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

我有一个枚举 TimeFrame,其值如下:YesterdayLastWeekNextMonth

我正在尝试编写一个接受 TimeFrame 和 return 那个时间段的开始和结束日期的方法。

我查看了新的 Java 8 Period class ,它可能需要开始时间和结束时间,但之后似乎没有任何干净的方法来检索这些值.

如何在不使用 List(似乎是错误的数据结构)或一些丑陋的日期时间算法的情况下,立即 return 干净地return 开始和结束日期?

不,Period 不记录 start/end - 它只是代表它们之间的时间量,在日历意义上(而不是 "precise amount of time" 代表Duration).

听起来基本上您应该创建自己的 class,它具有开始日期和结束日期。您仍然可以使用 Period 来实现它,但是您需要 getStartDate()getEndDate() 返回 LocalDate 值。您不需要自己做任何繁重的 date/time 运算 - 只需算出开始日期并添加适当的时间段,或结束日期并减去适当的时间段,具体取决于时间范围。

时光荏苒

传递“昨天”、“明天”等枚举值时要小心。这就提出了几个问题,时区和午夜。

日期和星期几仅在时区上下文中有意义。对于任何给定时刻,日期在全球范围内各不相同。例如,巴黎的午夜过后几分钟在蒙特利尔仍然是“昨天”。因此,当您打算使用“昨天”之类的内容时,请始终指定 desired/expected 时区。

每个非atomic命令和代码行都与前一个分开执行。每次执行都需要一点时间,无论多么短暂。在任何这些时刻,指定时区的午夜都可能会转入新的一天。在午夜的那一刻,你的相对时间标志,比如“昨天”,突然有了一个全新的含义。鉴于该代码开始时条件(日期)不同,该含义可能与早期代码的意图不同。

所以我觉得传递 Instant objects, or perhaps OffsetDateTime or ZonedDateTime 对象更有意义。这些日期时间值被冻结,代表时间轴上的特定时刻。您之前的原始代码可以验证该值的含义,检查日期是否确实是 Friday 或类似的日期。经过这样的验证后,该值可以传递给其他代码。现在您不必担心半夜偶尔会出现奇怪的错误。

java.time

你真的不需要构建一个 class 或枚举来表达你的相对时间的意图,比如“昨天”。 java.time classes 内置于 Java 8 及更高版本中,具有用于添加和减去天、周、月的简单阅读方法。这些基本上是一行,所以直接调用这些 plus…minus… 方法即可。

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

该代码隐式应用了 JVM 当前的默认时区。最好指定。

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

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

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

您可能想获得当天的第一时间。不总是 00:00:00.0.

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

如果要表示由一对日期时间值定义的时间跨度,请查看 Interval class found in the ThreeTen-Extra project that extends the java.time framework. This class tracks a pair of Instant objects which are moments on the timeline in UTC. You can extract an Instant from your ZonedDateTime by calling toInstant

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

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

ZonedDateTime zdt = ZonedDateTime( instant , zoneId );

对于仅限日期的间隔,您需要构建自己的 class 来存储一对 LocalDate 对象。我会称之为 DateRange.

提示:搜索 "Half-Open" 了解跟踪时间跨度的做法,其中开始于 包含 而结束为 包含 [=66] =].