LocalDates之间的期间产生错误的结果

huangapple go评论70阅读模式
英文:

Period between LocalDates produces wrong results

问题

我看到java.time.Periodjava.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所记录的行为:

该方法将指定的月份数添加到年份字段中的三个步骤:

  1. 将输入的月份添加到年份字段中
  2. 检查结果日期是否无效
  3. 必要时将日期调整为最后一个有效日期

例如,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.

huangapple
  • 本文由 发表于 2023年3月9日 15:46:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/75681703.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定