1. 概述
在本文中,我们将探讨如何在 Java 7、Java 8 和 Java 9+ 中,使用起止日期来遍历一个日期区间。内容简洁实用,适合日常开发参考。
不同 Java 版本提供了不同的工具类和 API,选择合适的方式不仅能提升代码可读性,还能避免踩坑。✅
2. Java 7:使用 Date 与 Calendar
在 Java 7 及更早版本中,我们通常使用 java.util.Date
存储日期,配合 java.util.Calendar
进行日期的增减操作。
⚠️ 注意:Date
类本身不支持直接加减天数,必须借助 Calendar
,这种方式略显繁琐且线程不安全,实际项目中容易出问题。
下面是一个典型的遍历实现:
void iterateBetweenDatesJava7(Date start, Date end) {
Date current = start;
while (current.before(end)) {
processDate(current);
Calendar calendar = Calendar.getInstance();
calendar.setTime(current);
calendar.add(Calendar.DATE, 1);
current = calendar.getTime();
}
}
📌 要点说明:
- 使用
while
循环判断当前日期是否早于结束日期 - 每次循环通过
Calendar.add(Calendar.DATE, 1)
实现 +1 天 processDate()
是自定义处理逻辑(如打印、入库等)
❌ 踩坑提醒:
不要复用同一个 Calendar
实例而不重置时间,容易导致死循环或逻辑错乱。每次最好重新实例化或谨慎 clear()。
3. Java 8:LocalDate + for 循环
Java 8 引入了全新的 java.time
包(JSR-310),带来了更现代、不可变、线程安全的时间 API。
我们可以使用 LocalDate
表示仅包含日期的部分,无需关心时间与时区。
遍历方式变得简单粗暴又清晰:
void iterateBetweenDatesJava8(LocalDate start, LocalDate end) {
for (LocalDate date = start; date.isBefore(end); date = date.plusDays(1)) {
processDate(date);
}
}
✅ 优势:
- 无需辅助类(告别 Calendar)
- 方法链清晰,语义明确
- 所有对象不可变,天然线程安全
plusDays(1)
直接返回新实例,无需担心状态污染
📌 小技巧:
如果你需要包含结束日期,可以把条件改为 !date.isAfter(end)
或 date.compareTo(end) <= 0
。
4. Java 9+:datesUntil + Stream API
Java 9 对 LocalDate
新增了一个非常实用的方法 —— datesUntil()
,它可以直接生成一个从起始日期到结束日期的 Stream<LocalDate>
。
这让我们可以用函数式风格优雅地处理日期序列:
void iterateBetweenDatesJava9(LocalDate start, LocalDate end) {
start.datesUntil(end).forEach(this::processDate);
}
✅ 更进一步,你还可以结合其他 Stream 操作:
List<String> formattedDates = start.datesUntil(end)
.map(date -> "Processed: " + date)
.collect(Collectors.toList());
📌 特性总结:
- ✅ 简洁:一行搞定遍历
- ✅ 函数式:支持 filter、map、collect 等操作
- ✅ 开箱即用:无需第三方库
- ⚠️ 注意:
datesUntil(end)
是左闭右开区间,即包含start
,不包含end
。若需包含 end,可使用重载方法:
start.datesUntil(end.plusDays(1)).forEach(this::processDate);
5. 总结
Java 版本 | 推荐方案 | 是否推荐 |
---|---|---|
≤ Java 7 | Date + Calendar |
❌ 仅维护老项目时使用 |
Java 8 | LocalDate + for |
✅ 日常推荐 |
≥ Java 9 | datesUntil() + Stream |
✅✅ 强烈推荐,代码最简洁 |
📌 核心建议:
- 新项目一律使用 Java 8+ 的
java.time
API - 能用
datesUntil()
就不用手写循环,更安全、更现代 - 避免混用旧 API(如
Date
和Calendar
),容易引发时区、线程等问题
示例代码已整理至 GitHub:https://github.com/baeldung/core-java-modules/tree/master/core-java-9
📌 扩展阅读:
- 对
LocalDateTime
、ZonedDateTime
等类型的处理方式类似 - 若涉及周期性任务调度,可结合
java.time.temporal.ChronoUnit
使用
保持代码简洁,远离时间处理的坑。⏱️