我的枚举TimeFrame
的值类似于:Yesterday
,LastWeek
,NextMonth
等。
我正在尝试编写一个接收TimeFrame
的方法,并返回该段时间的开始和结束日期。
我查看了新的Java 8 Period
类,它可以占用开始时间和结束时间,但似乎没有任何干净的方法可以在之后检索这些值。
如果不使用List
(似乎是错误的数据结构)或一些丑陋的日期时间算法,我怎么能干净地立即返回开始和结束日期?
答案 0 :(得分:9)
不,Period
不记录开始/结束 - 它只是表示它们之间的时间量,在时间意义上(而不是{{1表示的“精确时间量”) }})。
听起来基本上你应该创建一个有开始日期和结束日期的类。您仍然可以使用Duration
来实现该功能,但您需要Period
和getStartDate()
返回getEndDate()
值。您不需要自己做任何繁重的日期/时间算法 - 只需计算出开始日期并添加适当的时间段或结束日期,然后根据时间范围减去适当的时间段。
答案 1 :(得分:2)
小心传递“昨天”,“明天”等的枚举值。这引发了一些问题,时区和午夜。
日期和星期几只在时区的背景下有意义。对于任何特定时刻,日期在全球范围内变化。例如,在巴黎午夜过后几分钟,蒙特利尔仍然是“昨天”。因此,当您打算“昨天”等时,也要始终指定所需/预期的时区。
每个非atomic命令和代码行都与前一个分开执行。每次执行都需要一段时间,无论多么简短。在指定时区午夜的任何一个时刻,可能会滚动到新的一天。在午夜的那一刻,你的相对时间旗帜如“昨天”突然呈现出一种全新的含义。由于条件(日期)在代码开始时是不同的,因此早期代码意图的含义可能不同。
因此,传递Instant
个对象,或者OffsetDateTime
或ZonedDateTime
个对象更有意义。这些日期时间值被冻结,表示时间线上的特定时刻。您之前的原始代码可以验证该值的含义,检查日期确实是Friday
或其他类似的。经过这样的验证,该值可以传递给其他代码。现在你不必担心在午夜发生奇怪的偶然错误。
你真的不需要建立一个类或枚举来表达你的相对时间的意图,如“昨天”。 Java 8及更高版本中内置的java.time类具有用于添加和减去天,周,月的简单读取方法。这些基本上是单行的,因此请直接调用这些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 );
如果要表示由一对日期时间值定义的时间范围,请查看扩展java.time框架的Interval
项目中的ThreeTen-Extra类。此类跟踪一对Instant
个对象,这些对象是UTC时间轴上的时刻。您可以通过调用toInstant
从Instant
中提取ZonedDateTime
。
Interval intervalYesterday = Interval.of( yesterdayStart.toInstant() , yesterdayStart.plusDays( 1 ).toInstant() );
要从Instant
返回到分区日期时间,请应用ZoneId
。
ZonedDateTime zdt = ZonedDateTime( instant , zoneId );
对于仅限日期的间隔,您需要构建自己的类来存储一对LocalDate
对象。我会称之为DateRange
。
提示:搜索“半开”以了解跟踪包含时开始的时间跨度的做法,而结尾是独占。