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(如 DateCalendar),容易引发时区、线程等问题

示例代码已整理至 GitHub:https://github.com/baeldung/core-java-modules/tree/master/core-java-9

📌 扩展阅读:

  • LocalDateTimeZonedDateTime 等类型的处理方式类似
  • 若涉及周期性任务调度,可结合 java.time.temporal.ChronoUnit 使用

保持代码简洁,远离时间处理的坑。⏱️


原始标题:Iterate Through a Range of Dates in Java | Baeldung