gpt4 book ai didi

kotlin - 将 period 添加到 startDate 不会产生 endDate

转载 作者:行者123 更新时间:2023-12-02 04:06:10 24 4
gpt4 key购买 nike

我有两个 LocalDate 声明如下:

val startDate = LocalDate.of(2019, 10, 31)  // 2019-10-31
val endDate = LocalDate.of(2019, 9, 30) // 2019-09-30

然后我使用 Period. Between 函数计算它们之间的周期:

val period = Period.between(startDate, endDate) // P-1M-1D

此处的期间具有负数的月数和日数,这是预期的,因为 endDate 早于 startDate

但是,当我将 period 添加回 startDate 时,我得到的结果不是 endDate,而是日期前一天:

val endDate1 = startDate.plus(period)  // 2019-09-29

所以问题是,为什么不变式没有

startDate.plus(Period. Between(startDate, endDate)) == endDate

保留这两个日期吗?

Period. Between 返回了错误的句点,还是 LocalDate.plus 添加了错误的句点?

最佳答案

如果您了解 plus 是如何为 LocalDate 实现的

@Override
public LocalDate plus(TemporalAmount amountToAdd) {
if (amountToAdd instanceof Period) {
Period periodToAdd = (Period) amountToAdd;
return plusMonths(periodToAdd.toTotalMonths()).plusDays(periodToAdd.getDays());
}
...
}

您会在那里看到 plusMonths(...)plusDays(...)

plusMonths 处理一个月有 31 天、另一个月份有 30 天的情况。因此以下代码将打印 2019-09-30 而不是不存在的 2019-09-31

println(startDate.plusMonths(period.months.toLong()))

之后,减去一天的结果就是 2019-09-29。这是正确的结果,因为 2019-09-292019-10-31 相隔 1 个月 1 天

Period. Between 计算很奇怪,在本例中归结为

    LocalDate end = LocalDate.from(endDateExclusive);
long totalMonths = end.getProlepticMonth() - this.getProlepticMonth();
int days = end.day - this.day;
long years = totalMonths / 12;
int months = (int) (totalMonths % 12); // safe
return Period.of(Math.toIntExact(years), months, days);

其中 getProlepticMonth 是从 00-00-00 开始的总月数。在本例中,为 1 个月零 1 天。

据我了解,这是 Period. BetweenLocalDate#plus 负周期交互中的一个错误,因为以下代码具有相同的含义

val startDate = LocalDate.of(2019, 10, 31)
val endDate = LocalDate.of(2019, 9, 30)
val period = Period.between(endDate, startDate)

println(endDate.plus(period))

但它打印出正确的2019-10-31

问题在于 LocalDate#plusMonths 将日期规范化为始终“正确”。在以下代码中,您可以看到,从 2019-10-31 中减去 1 个月后,结果为 2019-09-31,然后标准化为 2019 -10-30

public LocalDate plusMonths(long monthsToAdd) {
...
return resolvePreviousValid(newYear, newMonth, day);
}

private static LocalDate resolvePreviousValid(int year, int month, int day) {
switch (month) {
...
case 9:
case 11:
day = Math.min(day, 30);
break;
}
return new LocalDate(year, month, day);
}

关于kotlin - 将 period 添加到 startDate 不会产生 endDate,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58573688/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com