推荐使用java.time包的localdate配合chronounit.days.between()计算日期天数差,自动处理闰年和大小月,结果可正可负;带时间的数据需先转为localdate以忽略时分秒,注意时区和解析安全性。

Java 中计算两个日期之间相差的天数,推荐使用 java.time 包(Java 8+),它简洁、线程安全、不易出错。核心思路是将两个日期转为 LocalDate,再用 ChronoUnit.DAYS.between() 直接获取天数差。
用 LocalDate + ChronoUnit 计算纯日期差(推荐)
适用于只关心年月日,忽略时分秒的场景(例如:生日间隔、项目周期天数):
- 确保两个日期都是
LocalDate类型;若原始是String或Instant,需先解析或转换 -
ChronoUnit.DAYS.between(start, end)返回的是从 start 到 end 的**完整天数差**,结果可正可负(end 在 start 后为正) - 自动处理闰年、大小月,无需手动计算
示例:
LocalDate start = LocalDate.of(2023, 1, 15);LocalDate end = LocalDate.of(2023, 3, 10);
long days = ChronoUnit.DAYS.between(start, end); // 结果:54
处理带时间的 Instant 或 LocalDateTime
如果原始数据含具体时刻(如数据库的 Timestamp 或 API 返回的 ISO 时间字符串),需先截取日期部分或按需求取整:
- 若只想要“日期级”差(忽略时间),统一转成
LocalDate:
Instant instant1 = Instant.parse("2023-01-15T09:30:00Z");
Instant instant2 = Instant.parse("2023-03-10T17:45:00Z");
LocalDate d1 = instant1.atZone(ZoneId.systemDefault()).toLocalDate();
LocalDate d2 = instant2.atZone(ZoneId.systemDefault()).toLocalDate();
long days = ChronoUnit.DAYS.between(d1, d2); - 若需考虑时间(比如精确到小时的天数),可用
Duration或Period,但注意Duration按 24 小时算,可能跨时区偏差
兼容旧代码:用 Calendar(不推荐,仅作了解)
Java 7 及以前常用 Calendar,但易出错(如月份从 0 开始、毫秒计算易溢出):
- 把两个
Date转为毫秒,相减后除以24 * 60 * 60 * 1000 - 必须注意时区和夏令时影响,且结果是
double,需Math.round()或floor/ceil处理 - 不建议新项目使用,维护成本高、逻辑不清晰
常见注意事项
- 顺序很重要:
between(a, b)是 b − a,不是绝对值;如需绝对天数,加Math.abs() - 时区敏感:解析字符串或处理
Instant时,务必明确时区(如ZoneId.of("Asia/Shanghai")) - 不要用
SimpleDateFormat解析日期字符串——它是非线程安全的,应改用DateTimeFormatter
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











