推荐使用java.time包计算日期差:ChronoUnit.DAYS.between()得天数(结果可为负),ChronoUnit.MONTHS.between()得整月数(忽略日),Period.between()得精确年月日组合;跨时区需先归一化为LocalDate。

Java 中计算两个日期之间相差的天数或月数,推荐使用 java.time 包(Java 8+),它比旧的 Date 和 Calendar 更简洁、线程安全且语义清晰。
计算两个日期之间的天数差
使用 ChronoUnit.DAYS.between() 是最直接的方式,注意:结果是「结束日期减开始日期」的天数,若结束日期更早,结果为负数。
- 确保两个日期都是
LocalDate类型(不带时间);如果原始是Instant或ZonedDateTime,需先按时区转换再截取日期部分 - 示例:LocalDate start = LocalDate.of(2023, 1, 15);
LocalDate end = LocalDate.of(2023, 2, 20);
long days = ChronoUnit.DAYS.between(start, end); // 结果为 36 - 如果需要绝对值,可手动调用
Math.abs(days)
计算两个日期之间的月数差
用 ChronoUnit.MONTHS.between() 可得整月数(忽略日部分),但要注意它只看年月,不考虑具体日期是否“满月”:
- 例如:
2023-01-31到2023-02-28的MONTHS.between()返回1(因为 1 月→2 月),尽管实际不足 30 天 - 如需更精确的“完整自然月”逻辑(比如 2023-01-15 → 2023-02-14 算 0 个月,2023-01-15 → 2023-02-15 才算 1 个月),应使用
Period.between()并检查period.getMonths() - Period period = Period.between(startDate, endDate);
int months = period.getMonths(); // 注意:仅返回月份数,不包含年或日
同时获取年、月、日的完整差异(推荐用于业务显示)
当需要类似“2年3个月15天”这种可读结果时,Period.between() 是最佳选择:
- 它会自动处理进位(如 14 个月 → 1 年 2 个月)
- 注意:输入必须是同类型日期对象(都为
LocalDate),否则抛异常 - 示例:Period p = Period.between(LocalDate.of(2021, 5, 10), LocalDate.of(2024, 8, 25));
// p.getYears()=3, p.getMonths()=3, p.getDays()=15
跨时区或含时间的场景要先归一化
如果原始数据是带时区的时间戳(如 ZonedDateTime 或 Instant),不能直接用 between() 计算月/日差,必须先统一到某个时区并提取 LocalDate:
- 错误做法:
ChronoUnit.DAYS.between(zdt1, zdt2)—— 单位是纳秒,不是日 - 正确做法:LocalDate d1 = zdt1.withZoneSameInstant(ZoneId.of("Asia/Shanghai")).toLocalDate();
LocalDate d2 = zdt2.withZoneSameInstant(ZoneId.of("Asia/Shanghai")).toLocalDate();
long days = ChronoUnit.DAYS.between(d1, d2); - 关键:明确业务所需的“日期”含义——是本地日历日?还是 UTC 日?选对时区再截取
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











