使用 Java 8 时间我只是想找出时间范围内表示的天数。考虑以下:
LocalDate start = LocalDate.of(2016, Month.MARCH, 28);
LocalDate end = LocalDate.of(2016, Month.MARCH, 31);
Period period = Period.between(start, end);
期间的天数为 3,表示 2 个日期之间的天数,包括开始和结束。我想要的是 2 个日期所代表的天数,实际上是 4(3 月 28 日、3 月 29 日、3 月 30 日、3 月 31 日)。
我知道我可以在从 Period.between() 返回的天数上加 1,但我想我很惊讶我找不到另一个调用来完全返回我想要的。我是否遗漏了什么或添加 1 是唯一的解决方案?
最佳答案
tl;博士
始终通过 半开 方法定义您的时间跨度,其中:
如果您想要
March 28, March 29, March 30, March 31
的四天,请从 3 月 28 日开始,在 4 月 1 日结束。从第一个(3 月 28 日)开始运行这些日期,直到但不包括最后一个(4 月 1 日)。2016-03-28/2016-04-01
半开
Am I missing something
您可能没有意识到半开放方法在定义时间跨度方面的有用性。
通常,定义时间跨度的最佳实践是半开放方法。在半开中,开始是包容的,而结束是独占的。
这种方法解决了处理 小数秒 的问题。直觉上,许多程序员会试图找到最后可能的时刻作为时间跨度的结束。但最后一刻涉及无限可分的最后一秒。您可能会想,“好吧,只需将毫秒数保留到小数点后三位,中午午休结束时间为 12:59.59.999,因为这就是我所需要的所有分辨率,这就是遗留 java.util.Date 的分辨率。 util.Date 类。”。但是您将无法在您的数据库中找到匹配项,例如 Postgres 以微秒的分辨率存储日期时间值,12:59:59.999999。因此您决定使用小数点后六位,x .999999. 但是开始遇到与 java.time 类中的日期时间值不匹配的情况,并且您会了解到为九位小数秒 x.999999999 提供了纳秒分辨率。您可以使用半开法,结局一直持续到下一整秒,但不包括在内。
我相信您会发现在整个日期时间处理代码中一致使用半开方法(无论是否涉及小数秒)将:
例子:
LocalDate
与其添加
1
以获得总天数,不如将您的时间跨度定义为半开放 :开始是包含的,结束是不包含的。如果您试图表示 3 月 28 日、29 日、30 日和 31 日这四个日期,那么我建议您定义一个从 3 月 28 日到 4 月 1 日的时间跨度。LocalDate start = LocalDate.of( 2016, Month.MARCH, 28 ) ; // inclusive
LocalDate stop = LocalDate.of( 2016, Month.APRIL, 1 ) ; // exclusive
Period
java.time 类明智地使用了半开放方法。因此
Period.between
方法将结尾视为排他性的,如问题中所述。我建议你在这里随波逐流,而不是与之抗争。搜索 Stack Overflow 以获取更多有关此方法如何工作的示例。Period p = Period.between( start , stop );
p.toString(): P4D
ChronoUnit
如果您想要总天数,例如一个半月的 45 天,请使用
ChronoUnit
枚举,这是 TemporalUnit
的实现。参见 this Question 进行讨论。同样,java.time 类使用半开放方法。所以
long daysBetween = ChronoUnit.DAYS.between( start, stop );
4
实时代码
请参阅此示例 code run live at IdeOne.com 。
关于date - 确定 Java 中时间范围表示的天数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41833781/