在计算两个日期之间的年份时,第二个日期是从第一个日期开始计算的(这是我正在处理的简化示例),LocalDate
和Period
似乎计算了一年略有不同。
例如,
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 :(得分:3)
这个问题具有哲学性质,并且几乎没有时间测量和日期格式约定等问题。
LocalDate
是ISO 8601日期交换标准的实现。
Java Doc明确声明此类不表示时间,但仅提供标准日期表示法。
API仅对符号本身提供简单操作,所有计算均通过递增年,月或日来完成。给定的日期。
换句话说,在调用LocalDate.plusYears()
时,您每个概念年都会增加365天,而不是一年内的确切时间。
这使日成为可以添加到LocalDate
表示的日期的最低时间单位。
在人类的理解中, date 不是一个时刻,而是一个时期。
从00h 00m 00s(...)开始,以23h 59m 59s(...)结束。
然而, LocalDate
避免了时间测量和人类时间单位模糊的问题(小时,天,月,以及年都可以有不同的长度)和模型日期符号只是作为一个元组:
(years, months within a year, days within a month )
从那个时代开始计算。
在此解释中, Day 是影响日期的最小单位。
以下为例:
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()
返回给定年份的天数,并且闰年将返回 366 。所以你可以这样做:
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
请注意,将日期 366 而非 365 天的时间从 11个月和30天增加到 1一年和一天(增加2天!)。