如何获得一段时间的开始和结束时间?

时间:2016-06-22 17:45:47

标签: date datetime time java-8 period

我的枚举TimeFrame的值类似于:YesterdayLastWeekNextMonth等。

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

我查看了新的Java 8 Period类,它可以占用开始时间和结束时间,但似乎没有任何干净的方法可以在之后检索这些值。

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

2 个答案:

答案 0 :(得分:9)

不,Period不记录开始/结束 - 它只是表示它们之间的时间量,在时间意义上(而不是{{1表示的“精确时间量”) }})。

听起来基本上你应该创建一个有开始日期和结束日期的类。您仍然可以使用Duration来实现该功能,但您需要PeriodgetStartDate()返回getEndDate()值。您不需要自己做任何繁重的日期/时间算法 - 只需计算出开始日期并添加适当的时间段或结束日期,然后根据时间范围减去适当的时间段。

答案 1 :(得分:2)

时间在

上进行

小心传递“昨天”,“明天”等的枚举值。这引发了一些问题,时区和午夜。

日期和星期几只在时区的背景下有意义。对于任何特定时刻,日期在全球范围内变化。例如,在巴黎午夜过后几分钟,蒙特利尔仍然是“昨天”。因此,当您打算“昨天”等时,也要始终指定所需/预期的时区。

每个非atomic命令和代码行都与前一个分开执行。每次执行都需要一段时间,无论多么简短。在指定时区午夜的任何一个时刻,可能会滚动到新的一天。在午夜的那一刻,你的相对时间旗帜如“昨天”突然呈现出一种全新的含义。由于条件(日期)在代码开始时是不同的,因此早期代码意图的含义可能不同。

因此,传递Instant个对象,或者OffsetDateTimeZonedDateTime个对象更有意义。这些日期时间值被冻结,表示时间线上的特定时刻。您之前的原始代码可以验证该值的含义,检查日期确实是Friday或其他类似的。经过这样的验证,该值可以传递给其他代码。现在你不必担心在午夜发生奇怪的偶然错误。

java.time

你真的不需要建立一个类或枚举来表达你的相对时间的意图,如“昨天”。 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时间轴上的时刻。您可以通过调用toInstantInstant中提取ZonedDateTime

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

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

ZonedDateTime zdt = ZonedDateTime( instant , zoneId );

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

提示:搜索“半开”以了解跟踪包含时开始的时间跨度的做法,而结尾是独占