【问题标题】:LocalDate.plus Incorrect AnswerLocalDate.plus 错误答案
【发布时间】:2019-09-28 12:49:48
【问题描述】:

在使用长 Period 调用 plus(...) 时,Java 的 LocalDate API 似乎给出了不正确的答案,我在其中遇到了一个错误。我在这里做错了吗?

import java.time.LocalDate;
import java.time.Month;
import java.time.Period;
import java.time.temporal.ChronoUnit;

public class Main
{
    public static void main(String[] args)
    {
        // Long Period
        LocalDate birthA = LocalDate.of(1965, Month.SEPTEMBER, 27);
        LocalDate eventA = LocalDate.of(1992, Month.MAY, 9);
        LocalDate halfA = eventA.plus(Period.between(birthA, eventA));
        System.out.println(halfA); // 2018-12-21 ????
        System.out.println(ChronoUnit.DAYS.between(birthA, eventA)); // 9721
        System.out.println(ChronoUnit.DAYS.between(eventA, halfA)); // 9722 ????

        // Short Period
        LocalDate birthB = LocalDate.of(2012, Month.SEPTEMBER, 10);
        LocalDate eventB = LocalDate.of(2012, Month.SEPTEMBER, 12);
        LocalDate halfB = eventB.plus(Period.between(birthB, eventB));
        System.out.println(halfB); // 2018-09-14
        System.out.println(ChronoUnit.DAYS.between(birthB, eventB)); // 2
        System.out.println(ChronoUnit.DAYS.between(eventB, halfB)); // 2
    }
}

【问题讨论】:

    标签: java java-8 localdate off-by-one


    【解决方案1】:

    Period 由若干年、月和日组成。在您的情况下,Period.between(birthA, eventA) 是 26 年 7 个月零 12 天。

    如果你把它添加到birthA,你会得到:

    • 1965 + 26 年 -> 1991
    • 1991 年 9 月 + 7 个月 -> 1991 年 4 月
    • 1991 年 4 月 27 日 + 12 天 -> 1992 年 5 月 9 日

    按预期工作。

    如果您应用相同的计算,从 1992 年 5 月 9 日开始,您将得到 2018 年 12 月 21 日。

    如果您想添加特定天数,则不能简单地添加期间(因为年和月的长度并不总是相同)。一种选择是改用ChonoUnit.DAYS.between

    LocalDate halfA = eventA.plusDays(ChronoUnit.DAYS.between(birthA, eventA));
    

    这会返回 2018-12-20,我认为这是您所期望的。

    【讨论】:

    • 啊,这让我终于明白Period到底是什么了!
    【解决方案2】:

    为了补充 assylias 的回答,这里有一个简化的例子来说明为什么会发生这种情况:

        public static void main(String[] args)
        {
            LocalDate a = LocalDate.of(1992, Month.APRIL, 1);
            LocalDate b = LocalDate.of(1992, Month.MAY, 1);
            // Calculate the period. It will return "One month"
            Period period = Period.between(a, b);
            // Add one month to b. It will return June 1, 1992
            LocalDate c = b.plus(period);
            System.out.println(ChronoUnit.DAYS.between(a, b)); // 30 days as April has 30 days
            System.out.println(ChronoUnit.DAYS.between(b, c)); // 31 days as May has 31 days
        }
    

    【讨论】:

      猜你喜欢
      • 2020-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多