英文:
Period between LocalDates produces wrong results
问题
我看到java.time.Period
与java.time.LocalDates
在大多数情况下可以按预期工作,我可以使用它来获取两个日期之间的年、月和天的持续时间,但我发现一个不起作用的示例(不符合我的预期),如下所示:
val test1 = LocalDate.of(2023, 1, 31)
val test2 = LocalDate.of(2023, 1, 28)
val testToday = LocalDate.of(2023, 3, 9)
val period1 = Period.between(test1, testToday)
val period2 = Period.between(test2, testToday)
L.d { "test1 = $test1 | test2 = $test2 | today = $testToday" }
L.d { "period1 = $period1 | period2 = $period2" }
输出如下:
period1 = P1M9D | period2 = P1M9D
test1 = 2023-01-31 | test2 = 2023-01-28 | today = 2023-03-09
问题
上面的解决方案告诉我以下信息:
- 2023-01-31和2023-03-09之间的持续时间 => 1个月9天(P1M9D)
- 2023-01-28和2023-03-09之间的持续时间 => 1个月9天(P1M9D)
=> 但这是错误的,第二个应该显示比持续时间多3天... 是否有解释?
英文:
I see that java.time.Period
with java.time.LocalDates
works mostly as desired and I can use it to get the duration between two dates in years, months and days but I found an example that is not working (not as I expected it), like following:
val test1 = LocalDate.of(2023, 1, 31)
val test2 = LocalDate.of(2023, 1, 28)
val testToday = LocalDate.of(2023, 3, 9)
val period1 = Period.between(test1, testToday)
val period2 = Period.between(test2, testToday)
L.d { "test1 = $test1 | test2 = $test2 | today = $testToday" }
L.d { "period1 = $period1 | period2 = $period2" }
Output is following:
period1 = P1M9D | period2 = P1M9D
test1 = 2023-01-31 | test2 = 2023-01-28 | today = 2023-03-09
Problem
The solution above tells me following:
- Duration between 2023-01-31 and 2023-03-09 => 1 month and 9 days (P1M9D)
- Duration between 2023-01-28 and 2023-03-09 => 1 month and 9 days (P1M9D)
=> but this is wrong, the second one should show 3 days more as duration... Is there an explanation for this?
答案1
得分: 1
问题出在Period.between
的计算方式上:
起始日期包括在内,但结束日期不包括在内。周期的计算是通过删除完整的月份,然后计算剩下的天数,调整以确保两者具有相同的符号。然后根据12个月的年度将月数拆分为年份和月份。如果结束日期的月份日大于或等于起始日期的月份日,将考虑一个月。例如,从2010-01-15到2011-03-18是一年、两个月和三天。
这导致2023-01-28到2023-01-01被计为1个月1天(P1M1D),但2023-01-29、30和31也是如此。这是因为2023-01-31再加1个月是2023-02-31,这是无效的,因此它使用2023-02-28(对于29、30和当然28也是如此)。换句话说,有1个完整的月,截至于2023-02-28,然后还有9天,直到2023-03-09(不包括在内)。
这符合LocalDate.plusMonths
所记录的行为:
该方法将指定的月份数添加到年份字段中的三个步骤:
- 将输入的月份添加到年份字段中
- 检查结果日期是否无效
- 必要时将日期调整为最后一个有效日期
例如,2007-03-31再加一个月将导致无效日期2007-04-31。而不是返回无效结果,将选择该月的最后一个有效日期,即2007-04-30。
英文:
The "problem" is the way Period.between
performs its calculation:
> The start date is included, but the end date is not. The period is
> calculated by removing complete months, then calculating the remaining
> number of days, adjusting to ensure that both have the same sign. The
> number of months is then split into years and months based on a 12
> month year. A month is considered if the end day-of-month is greater
> than or equal to the start day-of-month. For example, from 2010-01-15
> to 2011-03-18 is one year, two months and three days.
This results in 2023-01-28 until 2023-01-01 counting as 1 month and 1 day (P1M1D), but so will 2023-01-29, 30, and 31. This is because 2023-01-31 plus 1 month is 2023-02-31, which is invalid, so it uses 2023-02-28 (and same for 29 and 30, and of course 28). In other words, there is 1 full month, which ends on 2023-02-28, and then there are 9 more days until 2023-03-09 (exclusive).
This conforms to the behaviour documented for LocalDate.plusMonths
:
> This method adds the specified amount to the months field in three
> steps:
>
> 1. Add the input months to the month-of-year field
> 2. Check if the resulting date would be invalid
> 3. Adjust the day-of-month to the last valid day if necessary
>
> For example, 2007-03-31 plus one month would result in the invalid
> date 2007-04-31. Instead of returning an invalid result, the last
> valid day of the month, 2007-04-30, is selected instead.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论