1. 概述
Java 8 引入的全新时间 API 让日期时间处理不再依赖外部库。这篇短文将对比不同 Java 版本中获取两个日期之间所有日期的实现方式,看看它们是如何逐步简化的。
2. 使用 Java 7
在 Java 7 中,我们需要借助 Calendar
实现这个功能。核心思路是:
- 先获取去除时间信息的开始和结束日期
- 通过循环逐天递增,直到达到结束日期
以下是具体实现代码:
public static List getDatesBetweenUsingJava7(Date startDate, Date endDate) {
List datesInRange = new ArrayList<>();
Calendar calendar = getCalendarWithoutTime(startDate);
Calendar endCalendar = getCalendarWithoutTime(endDate);
while (calendar.before(endCalendar)) {
Date result = calendar.getTime();
datesInRange.add(result);
calendar.add(Calendar.DATE, 1);
}
return datesInRange;
}
private static Calendar getCalendarWithoutTime(Date date) {
Calendar calendar = new GregorianCalendar();
calendar.setTime(date);
calendar.set(Calendar.HOUR, 0);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
return calendar;
}
⚠️ 这种方式需要手动处理时间清零和循环控制,代码量较大且容易出错。
3. 使用 Java 8
Java 8 的 Stream API 让实现变得优雅许多:
- 先计算两个日期间的天数差
- 创建整数流并映射为日期对象
- 收集结果到列表
public static List<LocalDate> getDatesBetweenUsingJava8(
LocalDate startDate, LocalDate endDate) {
long numOfDaysBetween = ChronoUnit.DAYS.between(startDate, endDate);
return IntStream.iterate(0, i -> i + 1)
.limit(numOfDaysBetween)
.mapToObj(i -> startDate.plusDays(i))
.collect(Collectors.toList());
}
✅ 关键改进:
- 使用
ChronoUnit.DAYS.between()
精确计算天数 - 通过
IntStream
和mapToObj
实现函数式转换 - 避免了手动循环和状态管理
4. 使用 Java 9
Java 9 提供了终极解决方案——直接使用 datesUntil()
方法:
public static List<LocalDate> getDatesBetweenUsingJava9(
LocalDate startDate, LocalDate endDate) {
return startDate.datesUntil(endDate)
.collect(Collectors.toList());
}
✅ 核心优势:
- 单行代码完成核心逻辑
datesUntil()
直接返回有序日期流- 无需手动计算天数差或创建中间流
5. 总结
对比三个版本的实现,我们可以清晰看到 Java 时间 API 的演进:
- Java 7:需要手动处理
Calendar
和循环,代码冗长 - Java 8:通过 Stream API 实现函数式风格,显著简化
- Java 9:专用方法
datesUntil()
提供最简洁方案
对于新项目,强烈推荐使用 Java 9+ 的方案。如果仍在使用 Java 8,Stream 方式也是不错的选择。至于 Java 7 的实现方式,建议在升级时尽快替换。
完整代码示例可在 GitHub 查看。