ChronoUnit 是 Java 8 提供的精确时间单位计算工具,支持 DAYS、WEEKS、MONTHS 等单位的整数差值计算,MONTHS/YEARS 基于日历逻辑而非固定毫秒,需注意类型一致性和参数顺序。

ChronoUnit 是 Java 8 引入的 java.time 包中用于精确计算时间单位间隔的核心工具,它不依赖日历系统细节,直接按“单位语义”做差值计算,比手动用毫秒除算更准确、更易读。
直接用 between() 计算天数、周数、月数
对 LocalDate、LocalDateTime、ZonedDateTime 等支持的时间类型,调用 ChronoUnit.XXX.between(start, end) 即可获得整数结果:
-
ChronoUnit.DAYS.between(d1, d2):返回两个日期之间的**完整天数**(含起始日不算,类似“日历差”,d2 > d1 时为正) -
ChronoUnit.WEEKS.between(d1, d2):等价于DAYS.between(...) / 7,向下取整(如 10 天 → 1 周) -
ChronoUnit.MONTHS.between(d1, d2):按“年月”对齐计算,只看年份和月份字段差,忽略具体日期(如 2023-01-31 到 2023-02-28 返回 1,尽管不足整月)
注意 MONTHS 和 YEARS 的“日历语义”特性
MONTHS 和 YEARS 不是固定毫秒长度,而是基于日历规则的逻辑差:
- 2023-01-15 到 2023-03-10 →
MONTHS.between = 1(1月→2月算1个月,3月还没到) - 2023-01-31 到 2023-02-28 →
MONTHS.between = 1(即使2月没31日,仍算跨过一个月份) - 若需“按实际天数折算月均值”,应先用
DAYS再除以 30.44,而非依赖MONTHS
搭配 TemporalAdjusters 或 plus() 实现反向推算
结合 between() 结果可做实用推导:
立即学习“Java免费学习笔记(深入)”;
- 已知起始日和天数,求结束日:
start.plusDays(ChronoUnit.DAYS.between(start, end))(看似冗余,实则可用于校验或链式计算) - 想得到“n个月后的同一天”,优先用
localDate.plusMonths(n),而非plus(…, ChronoUnit.MONTHS)(后者不支持) -
ChronoUnit本身不修改时间对象,仅计算;修改请用对应类型的plus/minus方法
避免常见误区
这些操作容易出错,需特别留意:
- 参数顺序不能颠倒:若
d1在d2后,结果为负数(如DAYS.between(2024-05-10, 2024-05-01) == -9) - 不能混用类型:不能对
LocalDateTime和ZonedDateTime直接调用between,需先统一为同类型(如都转成Instant再用ChronoUnit.SECONDS) -
HOURS/MINUTES对LocalDate抛UnsupportedTemporalTypeException(因为不含时间信息)



















