使用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,表示两个日期之间的天数,包括开始日期和结束日期.我想要的是两个日期所代表的天数,实际上是4天(3月28日,3月29日,3月30日,3月31日).
我知道我可以加上从Period.between()返回的天数加1,但我想我很惊讶我找不到另一个电话来准确地返回我想要的东西.我错过了什么或者只添加1个解决方案吗?
始终通过半开放式方法定义您的时间跨度,其中:
开始是包容性的.
结束是独家的.
如果您想要四天March 28, March 29, March 30, March 31
,请从3月28日开始到4月1日结束.从第一个(3月28日)开始,直到(但不包括)最后一个(4月1日).
半开2016年3月28日/ 2016年4月1日
我错过了什么
您可能会错过对半开放式方法在定义时间跨度方面的有用性的理解.
通常,定义时间跨度的最佳实践是半开放方法.在半开放中,开始是包容性的,而结尾是独占的.
这种方法解决了处理小数秒的问题.直观地说,许多程序员将试图找到最后一个可能的时刻作为一段时间的结束.但最后一刻涉及到无限可分的最后一秒.你可能会想,"好吧,只需要三个小数位,毫秒,12:59.59.999,中午休息时间结束,因为这是我将需要的所有分辨率,这就是传统java的分辨率. util.Date类.".但是你会在你的数据库中找不到像Postgres这样的匹配,它们以微秒,12:59:59.999999的分辨率存储日期时间值.所以你决定使用小数的六位小数,x .999999.但是开始遇到与java.time类中的日期时间值不匹配的情况,并且您学习了对于小数秒的九位数x.999999999的分辨率为纳秒.
我相信你会发现在整个日期时间处理代码中一致使用半开放式方法(无论是否涉及小数秒)将:
使您的代码更易于阅读和理解.
总体上减轻认知负担.
知道你所有的时间跨度都有相同的定义消除歧义.
减少错误.
例子:
中午午餐时间从时钟到达中午(12:00:00)开始,一直到但不包括时钟敲响一刻的时刻.这意味着12:00:00至13:00:00.
一整天从一天的第一时刻开始(顺便说一下,并不总是00:00:00)并且一直运行到第二天的第一时刻,但不包括.
一周从星期一开始,一直运行到下一个星期一,但不包括在内.这意味着周一至周一的七天.
月份的第一个月开始,并且在下个月的第一天开始运行,但不包括.所以三月是三月一日到四月一日.
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
enum,一个实现TemporalUnit
.请参阅此问题以供讨论.
同样,java.time类使用半开放方法.所以
long daysBetween = ChronoUnit.DAYS.between( start, stop );
4
请参阅IdeOne.com上的此示例代码.