You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Java集合中连续间隔1天的日期划分成时间段?

嗨,这个需求我之前做项目的时候碰到过,其实核心就是利用TreeSet的有序特性(LocalDate默认按自然日期排序),遍历的时候把连续的日期归为同一个时间段就行,我给你捋捋具体的实现思路和代码:

实现思路

  1. 先判断集合是否为空,为空直接返回空结果
  2. 初始化第一个时间段的开始和结束为集合的第一个日期
  3. 按顺序遍历集合中的每个日期:
    • 如果当前日期是上一个时间段结束日期的次日(间隔1天),就把当前日期设为时间段的新结束
    • 如果不连续,就把之前的时间段存入结果列表,然后以当前日期为起点开始新的时间段
  4. 遍历结束后,别忘了把最后一个时间段加入结果列表

具体代码实现

首先我们可以自定义一个简单的DateRange类来存储时间段的开始和结束日期:

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;

// 自定义时间段类,封装开始和结束日期
class DateRange {
    private final LocalDate start;
    private final LocalDate end;

    public DateRange(LocalDate start, LocalDate end) {
        this.start = start;
        this.end = end;
    }

    // 重写toString,方便输出:单日期直接显示日期,多日期显示"开始至结束"
    @Override
    public String toString() {
        return start.equals(end) ? start.toString() : start + " 至 " + end;
    }

    // 按需添加getter方法
    public LocalDate getStart() {
        return start;
    }

    public LocalDate getEnd() {
        return end;
    }
}

然后是核心的时间段划分方法:

public static List<DateRange> splitIntoContinuousRanges(TreeSet<LocalDate> dates) {
    List<DateRange> resultRanges = new ArrayList<>();
    if (dates.isEmpty()) {
        return resultRanges;
    }

    // 初始化第一个时间段的开始和结束
    LocalDate currentStart = dates.first();
    LocalDate currentEnd = currentStart;

    for (LocalDate date : dates) {
        // 跳过第一个元素,已经初始化过了
        if (date.equals(currentStart)) {
            continue;
        }

        // 检查当前日期是否和上一个结束日期连续(间隔1天)
        if (date.equals(currentEnd.plusDays(1))) {
            currentEnd = date;
        } else {
            // 不连续,把当前时间段存入结果,开始新的时间段
            resultRanges.add(new DateRange(currentStart, currentEnd));
            currentStart = date;
            currentEnd = date;
        }
    }

    // 把最后一个时间段加入结果
    resultRanges.add(new DateRange(currentStart, currentEnd));
    return resultRanges;
}

调用示例(结合你的代码)

public static void main(String[] args) {
    TreeSet<LocalDate> dates = getDaysBetween("2017-02-01","2017-03-31");
    dates.removeAll(getDaysBetween("2017-01-01","2017-02-01"));
    dates.removeAll(getDaysBetween("2017-03-01","2017-03-04"));
    dates.removeAll(getDaysBetween("2017-03-08","2017-03-08"));
    dates.removeAll(getDaysBetween("2017-03-10","2017-03-12"));
    // 假设还有其他removeAll操作...

    // 划分时间段并输出
    List<DateRange> continuousRanges = splitIntoContinuousRanges(dates);
    continuousRanges.forEach(System.out::println);
}

一些注意点

  • 因为TreeSet是有序集合,遍历的时候不需要额外排序,这也是这个方案高效的原因
  • 要注意removeAll的逻辑,比如你第一个removeAll操作会把2017-02-01从集合中移除,所以后续的时间段会从2017-02-02开始
  • 如果你的getDaysBetween方法包含起始和结束日期,那remove操作会准确移除这些日期,没问题

内容的提问来源于stack exchange,提问作者Carl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:19:23