LocalDate.plus Неверный ответ - PullRequest
18 голосов
/ 10 мая 2019

Java LocalDate API, кажется, дает неправильный ответ при вызове plus(...) с длинным Period, где я получаю отключение одной ошибкой.Я что-то здесь не так делаю?

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
    }
}

Ответы [ 2 ]

21 голосов
/ 10 мая 2019

A Period состоит из нескольких лет, месяцев и дней.В вашем случае Period.between(birthA, eventA) - это 26 лет, 7 месяцев и 12 дней.

Если вы добавите это к birthA, вы получите:

  • 1965 + 26 лет ->1991
  • сентябрь 1991 + 7 месяцев -> апрель 1991
  • 27 апреля 1991 + 12 дней -> 9 мая 1992

Что работает, как ожидалось.

Если вы примените тот же расчет, начиная с 9 мая 1992 года, вы получите 21 декабря 2018.

Если вы хотите добавить определенное количество дней, вы не можете просто добавитьпериод (так как годы и месяцы не всегда имеют одинаковую длину).Один из вариантов - использовать ChonoUnit.DAYS.between вместо:

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

Возвращает 2018-12-20, что, я думаю, соответствует вашим ожиданиям.

7 голосов
/ 10 мая 2019

В дополнение к ответу ассилий, вот упрощенный пример, чтобы показать, почему это происходит:

    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
    }
...