2015-10-05 114 views
9

当计算两个日期之间的年份时,第二个日期从第一个日期开始计算(这是我正在处理的简化示例),LocalDatePeriod似乎计算一年略有不同。计算闰年之间的年份

例如,

LocalDate date = LocalDate.of(1996, 2, 29); 
LocalDate plusYear = date.plusYears(1); 
System.out.println(Period.between(date, plusYear).getYears()); 

LocalDate date = LocalDate.of(1996, 3, 29); 
LocalDate plusYear = date.plusYears(1); 
System.out.println(Period.between(date, plusYear).getYears()); 

尽管有明确的一年加入,第一Period回报年0,而第二种情况返回1

有没有解决这个整齐的方法吗?

+0

我相信你的产品代码实际上并没有增加1年,并试图计算它刚添加的年数。你究竟在努力实现什么?给我们实际的投入和预期的产出。 – dotvav

+3

@dotvav:给出的例子似乎很清楚,我没有看到任何问题。 –

+0

如果你真的想要一年的差异而不是零,那么就简单地减去年份数字,而不考虑任何月份或月份的部分。 –

回答

3

这个问题有一个哲学本质的跨越,如时间测量和日期格式约定一些问题。

LocalDateISO 8601日交流标准的实现。 Java Doc Doc明确声明,此类不代表时间,但只提供标准日期符号。

API提供了对符号本身只是简单的操作和所有的计算都通过增加,或年完成月,或某一特定日期的日。

换句话说,调用LocalDate.plusYears()时要添加的每个365天概念里,而不是一年的时间内的确切数额。

这使得可以添加到由LocalDate表示的日期的最低时间单位。

在人类的认识中,的日期不是时刻,而是一个时期。

它从00H00米00秒(...),并用23小时59分59秒(...)结束。然而

LocalDate避免了实时测量与人类的时间单位的含糊不清的问题(小时日,都可以有不同的长度)和模型日期符号只是作为一个元组:

(years, months within a year, days within a month)

由于时代的开始计算。

在这个解释中,有意义的是是影响日期的最小单位。

作为一个例子如下:

LocalDate date = LocalDate.of(1996, 2, 29); 
LocalDate plusSecond = date.plus(1, ChronoUnit.SECONDS); 

返回

java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Seconds 

...这说明,在使用LocalDate和添加的秒数(或更小的单位来驱动精度),则无法克服您的问题中列出的限制。

看着你的执行过程,你会发现LocalDate.plusYears()加上年后,调用resolvePreviousValid()。然后,此方法检查闰年和修改在以下方式字段:

day = Math.min(day, IsoChronology.INSTANCE.isLeapYear((long)year)?29:28);

在它通过有效地扣除1天纠正它换句话说。

您可以使用Year.length(),它返回给定年份的天数,并返回闰年的。所以,你可以这样做:

LocalDate plusYear = date.plus(Year.of(date.getYear()).length(), ChronoUnit.DAYS); 

你仍然会碰到以下古怪(来电Year.length()与简洁天数代替):

LocalDate date = LocalDate.of(1996, 2, 29); 
LocalDate plusYear = date.plus(365, ChronoUnit.DAYS); 
System.out.println(plusYear); 
Period between = Period.between(date, plusYear); 
System.out.println(between.getYears() + "y " + 
        between.getMonths() + "m " + 
        between.getDays() + "d"); 

回报

1997-02-28 
0y 11m 30d 

然后

LocalDate date = LocalDate.of(1996, 3, 29); 
LocalDate plusYear = date.plus(365, ChronoUnit.DAYS); 
System.out.println(plusYear); 
Period between = Period.between(date, plusYear); 
System.out.println(between.getYears() + "y " + 
        between.getMonths() + "m " + 
        between.getDays() + "d"); 

回报

1997-03-29 
1y 0m 0d 

最后:

LocalDate date = LocalDate.of(1996, 2, 29); 
LocalDate plusYear = date.plus(366, ChronoUnit.DAYS); 
System.out.println(plusYear); 
Period between = Period.between(date, plusYear); 
System.out.println(between.getYears() + "y " + 
        between.getMonths() + "m " + 
        between.getDays() + "d"); 

回报:

1997-03-01 
1y 0m 1d 

请注意,,而不是天移动日期从上升周期11个月和30天1年和1天(增加2天!)。