【问题标题】:LocalDate minus a Period get wrong resultLocalDate 减去 Period 得到错误的结果
【发布时间】:2017-09-14 05:39:24
【问题描述】:

LocalDate 减去Period(如“28 年 1 个月 27 天”),得到错误的结果。

但是减去Period(只有天单位,比如“10282”天)得到正确的结果。 有什么要注意的吗?

public static void main(String[] args) {
    printAgeAndBirthday(1989, 2, 22);

    printBirthdayFromPeriod(28, 1, 27);
}
  private static void printBirthdayFromPeriod(int years, int months, int days) {
    final Period period = Period.of(years, months, days);
    final LocalDate now = LocalDate.now();
    final LocalDate birthday = now.minus(28, ChronoUnit.YEARS)
            .minus(1, ChronoUnit.MONTHS)
            .minus(27, ChronoUnit.DAYS);

    System.out.println("your birthday is : "+ birthday);//1989-02-19
    System.out.println("your birthday is : "+ now.minusYears(28).minusMonths(1).minusDays(27));//1989-02-19
    System.out.println("your birthday is : "+ now.minus(period));//1989-02-19
    System.out.println("your birthday is : "+period.subtractFrom(now));//1989-02-19
    System.out.println("your birthday is : "+ now.minus(Period.ofDays(10282)));//1989-02-22
}

private static void printAgeAndBirthday(int year, int month, int dayOfMonth) {
    LocalDate today = LocalDate.now();
    LocalDate birthday = LocalDate.of(year, month, dayOfMonth);

    Period p = Period.between(birthday, today);
    long p2 = ChronoUnit.DAYS.between(birthday, today);
    System.out.printf("You are %d years, %d months, and %d days old. (%d days total)%n",
            p.getYears(), p.getMonths(), p.getDays(), p2);

    LocalDate nextBDay = birthday.withYear(today.getYear());

    //If your birthday has occurred this year already, add 1 to the year.
    if (nextBDay.isBefore(today) || nextBDay.isEqual(today)) {
        nextBDay = nextBDay.plusYears(1);
    }

    Period p_1 = Period.between(today, nextBDay);
    long p_2 = ChronoUnit.DAYS.between(today, nextBDay);
    System.out.printf("There are %d months, and %d days until your next birthday. (%d total)%n",
            p_1.getMonths(), p_1.getDays(), p_2);
}

控制台日志:

You are 28 years, 1 months, and 27 days old. (10282 days total)
There are 10 months, and 4 days until your next birthday. (310 total)
your birthday is : 1989-02-19
your birthday is : 1989-02-19
your birthday is : 1989-02-19
your birthday is : 1989-02-19
your birthday is : 1989-02-22

java 版本:jdk1.8.0_45

【问题讨论】:

  • 不要使用 Period 进行精确计算。请参阅此相关帖子:stackoverflow.com/questions/41945704/…
  • 如果我从今天减去一个月零 27 天,我得到 2 月 19 日。所以这是正确的。

标签: java java-8 period localdate


【解决方案1】:

您的案例可以简化为

LocalDate date1 = LocalDate.of(2017, 2, 22), date2 = LocalDate.of(2017, 4, 18);
Period p = Period.between(date1, date2);
System.out.println("date1 + p: "+date1.plus(p));
System.out.println("date2 - p: "+date2.minus(p));

将打印出来

date1 + p: 2017-04-18
date2 - p: 2017-02-19

换句话说,年数无关紧要(除非其中一个年份是闰年而另一个不是,但在这里,两者都不是)。下面说明了这个问题:

February                       March                                                                                        April
19 20 21 22 23 24 25 26 27 28  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18
 ↑        │                                                                                   ↑                                                                                ↑
 │        └──────────────────────────── plus one Month ───────────────────────────────────────┴───────────────────────── plus 27 days ─────────────────────────────────────────┤
 │                                                                                ↑                                                                                            ↓
 └───────────────────────── minus 27 days ────────────────────────────────────────┴─────────────────── minus one month ────────────────────────────────────────────────────────┘

这会改变,如果你改变方向:

Period p2 = Period.between(date2, date1);
System.out.println("date1 - p2: "+date1.minus(p2));
System.out.println("date2 + p2: "+date2.plus(p2));

将打印出来

date1 - p2: 2017-04-15
date2 + p2: 2017-02-22

因此,当您用年、月和日来表示一个时期时,方向就变得相关了。相比之下,两个日期之间的天数是不变的:

LocalDate date1 = LocalDate.of(2017, 2, 22), date2 = LocalDate.of(2017, 4, 18);
Period p = Period.ofDays((int)ChronoUnit.DAYS.between(date1, date2));
System.out.println("date1 + p: "+date1.plus(p));
System.out.println("date2 - p: "+date2.minus(p));
date1 + p: 2017-04-18
date2 - p: 2017-02-22

【讨论】:

  • 真诚感谢您的回答。我得到了它 。当我按期间减去 LocalDate 时,使用天数单位将是正确的。
  • 如果您在代码中使用以下日期:LocalDate date1 = LocalDate.of(1971, 1, 2), date2 = LocalDate.of(1972, 3, 1);您会对以下结果感到惊讶: date1 + p: 1972-03-01 date2 - p: 1971-01-04 date2 - p 应该等于 date1;但事实并非如此。显然,加号和减号函数不是反函数 - 是错误吗?
  • @Legna 这个答案已经解释了日期,加号和减号不是反函数,它也解释了原因。
猜你喜欢
  • 2017-06-16
  • 1970-01-01
  • 2017-07-12
  • 1970-01-01
  • 2020-03-01
  • 2023-02-11
  • 1970-01-01
  • 2021-02-21
  • 1970-01-01
相关资源
最近更新 更多