period.between() 计算两个 localdate 间按日历规则对齐的年、月、日差值,非总天数或毫秒数;它逐级对齐(先年、再月、后日),结果为人类可读的 period 对象。
period.between() 是 java 8 引入的用于计算两个 localdate 之间“日历意义”差值的工具,但它返回的是一个 period 对象,**不是总天数,也不是精确到毫秒的时长**,而是按年、月、日分别对齐日历规则(如闰年、大小月)后得出的“人类可读”的差值。
理解 Period.between() 的计算逻辑
它采用“从大到小逐级对齐”的方式:先算完整年数,再在剩余日期中算完整月数,最后算剩余天数。例如:
-
Period.between(LocalDate.of(2022, 1, 15), LocalDate.of(2024, 3, 20))→P2Y2M5D(2年2个月5天) - 不是简单用总天数 ÷ 365 或 ÷ 30,而是考虑:2022-01-15 到 2024-01-15 是整 2 年;2024-01-15 到 2024-03-15 是整 2 个月;2024-03-15 到 2024-03-20 是 5 天
正确获取年、月、日分量
直接调用 Period 实例的 getter 方法即可,无需转换或推算:
LocalDate start = LocalDate.of(2020, 5, 10); LocalDate end = LocalDate.of(2023, 9, 25); Period period = Period.between(start, end); <p>int years = period.getYears(); // 3 int months = period.getMonths(); // 4 int days = period.getDays(); // 15 </p>
⚠️ 注意:getYears() 等方法返回的是该字段的**净值**,可能为负(当 end 早于 start 时),且不会自动归一化(比如不会把 15 个月转成 1 年 3 个月)。
常见误区与注意事项
-
不适用于跨时区或含时间的场景:它只处理
LocalDate,忽略时间与时区。若需带时分秒,请用Duration或ChronoUnit计算总毫秒/天数 -
结果依赖起止日期顺序:若 end 在 start 前,所有字段均为负值(如
Period.between(2023-01-01, 2022-01-01)得P-1Y) - 无法表示“365天 = 1年”这类平均换算:它严格按日历滚动,例如 2023-02-28 到 2024-02-28 是 1 年,但 2023-02-28 到 2024-02-29(闰年)也是 1 年 —— 它不关心中间是否经过 366 天
-
不能直接用于加减运算验证:虽然
start.plus(period).equals(end)在大多数情况下成立,但遇到月末边界可能有例外(如 2023-01-31 + P1M = 2023-02-28,再 + P1M = 2023-03-28,而非 3 月 31 日)
如果需要总天数,该用什么?
若目标是知道“一共多少天”,请改用:
-
ChronoUnit.DAYS.between(start, end)—— 返回 long 类型的总天数差(支持负值) - 或
end.toEpochDay() - start.toEpochDay()—— 效果相同,更底层
这两个方法给出的是纯粹的日期序数差,和 Period 的日历语义完全不同。










