LocalDates 之间的时间段会产生错误的结果

Period between LocalDates produces wrong results

提问人:prom85 提问时间:3/9/2023 最后编辑:Anonymousprom85 更新时间:3/12/2023 访问量:125

问:

我看到大部分工作都是根据需要的,我可以用它来获取两个日期之间的持续时间(以年、月和日为单位),但我发现了一个不起作用的示例(不是我预期的),如下所示: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 天作为持续时间......对此有解释吗?

java java-time localdate period 日期 差异

评论


答:

1赞 Mark Rotteveel 3/9/2023 #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。

评论

1赞 prom85 3/9/2023
谢谢你的解释。我完全知道排除结束日期和工作原理(这是有道理的),但是在计算两个日期之间的逻辑时,我会认为另一个逻辑是正确的(我仍然觉得逻辑不正确) - 请检查我问题的最后一段,我添加了我认为的“自然”逻辑 => 我可以得到这个结果还是我需要自己写这个逻辑?LocalDate.plusMonthsPeriodPeriodjava.time
1赞 Mark Rotteveel 3/9/2023
@prom85我已经回滚了该编辑,因为这被称为“移动球门柱”。无论如何,我不知道有“标准”方法可以做到这一点。
0赞 prom85 3/9/2023
没关系。它只是不适合评论......感谢您的回答。
2赞 Anonymous 3/11/2023
在不均匀长度的月份中计算月份和日期的“正确”方法是一个永无止境的讨论。每个日期库通常都有自己的方式。我认为,没有任何办法可以被认为是正确和充分的,并且可以使所有人满意。
0赞 Anonymous 3/12/2023
手动编写一个方法,以您喜欢的方式计算它并将结果塞进 .Period