在 Java 中计算两个日期之间的天数,有多种方法,适用于不同的 Java 版本和场景,下面我将介绍几种最常用和推荐的方法。

使用 Java 8 的 java.time 包 (推荐)
这是目前最现代、最推荐的方法。java.time API 自 Java 8 引入,它设计优秀,线程安全,并且功能强大。
我们将使用 LocalDate 类来表示一个日期(不包含时间),然后使用 ChronoUnit 来计算它们之间的天数差。
计算两个日期之间的完整天数
这个方法会计算从 date1 到 date2 之间完整的天数,从 2025-10-26 00:00 到 2025-10-27 00:00 是 1 天。
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
public class DaysBetweenJava8 {
public static void main(String[] args) {
// 定义两个日期
LocalDate date1 = LocalDate.of(2025, 10, 26);
LocalDate date2 = LocalDate.of(2025, 11, 15);
// 使用 ChronoUnit.DAYS.between() 计算天数差
// 结果是一个 long 类型的整数
long daysBetween = ChronoUnit.DAYS.between(date1, date2);
System.out.println("日期 1: " + date1);
System.out.println("日期 2: " + date2);
System.out.println("两个日期之间的天数差: " + daysBetween); // 输出: 20
}
}
计算两个日期之间的“日历”天数
有时候我们关心的是“跨越了多少天”,而不是完整的天数,从 2025-10-26 到 2025-10-27,无论几点,都算作 1 天,这种情况下,我们可以使用 until 方法。

import java.time.LocalDate;
public class CalendarDaysBetween {
public static void main(String[] args) {
LocalDate date1 = LocalDate.of(2025, 10, 26);
LocalDate date2 = LocalDate.of(2025, 11, 15);
// 使用 until 方法计算日历天数
// date1.until(date2) 返回一个 Period 对象
// 然后调用 getDays() 获取天数
long calendarDays = date1.until(date2).getDays();
System.out.println("日期 1: " + date1);
System.out.println("日期 2: " + date2);
System.out.println("日历天数差: " + calendarDays); // 输出: 20
// 另一种写法,效果相同
long calendarDays2 = date2.until(date1).getDays(); // 会得到负数
System.out.println("日历天数差 (反向): " + calendarDays2); // 输出: -20
}
}
注意:ChronoUnit.DAYS.between() 和 LocalDate.until().getDays() 在处理纯日期(LocalDate)时,结果通常是相同的。ChronoUnit 的方法更通用,可以用于计算其他时间单位(如小时、分钟)。
使用 java.util.Date 和 java.util.Calendar (旧方法)
在 Java 8 之前,我们通常使用 Date 和 Calendar 类,这种方法比较繁琐,Date 类本身有很多设计缺陷(例如它同时包含日期和时间,并且不是线程安全的),不推荐在新代码中使用,但了解它有助于维护旧项目。
import java.util.Calendar;
import java.util.Date;
public class DaysBetweenLegacy {
public static void main(String[] args) {
// 1. 创建 Calendar 实例
Calendar calendar1 = Calendar.getInstance();
Calendar calendar2 = Calendar.getInstance();
// 2. 设置日期 (注意:月份是从0开始的,0代表一月)
calendar1.set(2025, Calendar.OCTOBER, 26);
calendar2.set(2025, Calendar.NOVEMBER, 15);
// 3. 清除时间部分,只保留日期,否则会影响天数计算
calendar1.set(Calendar.HOUR_OF_DAY, 0);
calendar1.set(Calendar.MINUTE, 0);
calendar1.set(Calendar.SECOND, 0);
calendar1.set(Calendar.MILLISECOND, 0);
calendar2.set(Calendar.HOUR_OF_DAY, 0);
calendar2.set(Calendar.MINUTE, 0);
calendar2.set(Calendar.SECOND, 0);
calendar2.set(Calendar.MILLISECOND, 0);
// 4. 获取 Date 对象并计算毫秒差
Date date1 = calendar1.getTime();
Date date2 = calendar2.getTime();
long diffInMillis = date2.getTime() - date1.getTime();
// 5. 将毫秒转换为天数
long daysBetween = diffInMillis / (1000 * 60 * 60 * 24);
System.out.println("日期 1: " + date1);
System.out.println("日期 2: " + date2);
System.out.println("两个日期之间的天数差: " + daysBetween); // 输出: 20
}
}
缺点:
- 代码冗长,需要手动处理月份和时间的清零。
Date类的设计已过时,容易出错。Calendar不是线程安全的。
使用 Joda-Time 库 (第三方库)
在 Java 8 之前,Joda-Time 是事实上的标准日期时间库,它比 java.util.Date 和 java.util.Calendar 好用得多,如果你不能升级到 Java 8,或者在使用遗留项目,Joda-Time 仍然是一个不错的选择。

import org.joda.time.LocalDate;
import org.joda.time.Days;
public class DaysBetweenJoda {
public static void main(String[] args) {
// Joda-Time 的 LocalDate 和 Java 8 的同名类类似
LocalDate date1 = new LocalDate(2025, 10, 26);
LocalDate date2 = new LocalDate(2025, 11, 15);
// 使用 Days 类直接计算
int daysBetween = Days.daysBetween(date1, date2).getDays();
System.out.println("日期 1: " + date1);
System.out.println("日期 2: " + date2);
System.out.println("两个日期之间的天数差: " + daysBetween); // 输出: 20
}
}
注意:使用 Joda-Time 需要添加 Maven 或 Gradle 依赖。
<!-- Maven 依赖 -->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.12.5</version> <!-- 使用最新版本 -->
</dependency>
总结与对比
| 方法 | 优点 | 缺点 | 推荐场景 |
|---|---|---|---|
java.time (Java 8+) |
现代、API优雅、线程安全、功能强大 | 需要 Java 8 或更高版本 | 所有新项目 |
java.util.Date/Calendar |
无需额外库 | 过时、API繁琐、易出错、非线程安全 | 维护旧的 Java 7 或更早版本的项目 |
| Joda-Time | API优秀,比旧版Java好很多 | 是第三方库,需要额外依赖 | 不能升级到 Java 8 的旧项目 |
最终建议:
对于任何新的 Java 开发,请毫不犹豫地使用 Java 8 的 java.time 包,它是业界标准,也是最安全、最简洁的选择。
