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

参考DateTime重叠算法,如何改用LocalDate实现日期区间天数计算?

用LocalDate计算两个日期区间的重叠天数

我之前在处理日期区间重叠计算时也踩过类似的坑,Java 8引入的LocalDate确实比旧的DateTime好用,但需要调整一下计算逻辑来避免负数问题。下面是我验证过的可行实现:

核心逻辑梳理

两个日期区间[A_start, A_end]和[B_start, B_end]的重叠天数计算,关键是先找到实际重叠的区间:

  • 重叠区间的起始日期是两个区间起始的最大值(max(A_start, B_start))
  • 重叠区间的结束日期是两个区间结束的最小值(min(A_end, B_end))

如果重叠起始日期 <= 重叠结束日期,说明存在重叠,再计算这个区间的天数;否则重叠天数为0。

具体代码实现

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;

public class DateOverlapCalculator {
    public static long calculateOverlapDays(LocalDate range1Start, LocalDate range1End,
                                           LocalDate range2Start, LocalDate range2End) {
        // 确定重叠区间的边界
        LocalDate overlapStart = LocalDate.max(range1Start, range2Start);
        LocalDate overlapEnd = LocalDate.min(range1End, range2End);

        // 计算重叠天数:因为ChronoUnit.DAYS.between是左闭右开,所以要把结束日期加1来包含当天
        long overlapDays = ChronoUnit.DAYS.between(overlapStart, overlapEnd.plusDays(1));
        
        // 如果没有重叠(overlapStart > overlapEnd),between会返回负数,取0即可
        return Math.max(overlapDays, 0);
    }

    public static void main(String[] args) {
        // 测试案例1:部分重叠
        LocalDate r1s1 = LocalDate.of(2024, 1, 1);
        LocalDate r1e1 = LocalDate.of(2024, 1, 10);
        LocalDate r2s1 = LocalDate.of(2024, 1, 5);
        LocalDate r2e1 = LocalDate.of(2024, 1, 15);
        System.out.println(calculateOverlapDays(r1s1, r1e1, r2s1, r2e1)); // 输出6(5号到10号共6天)

        // 测试案例2:完全不重叠
        LocalDate r1s2 = LocalDate.of(2024, 1, 1);
        LocalDate r1e2 = LocalDate.of(2024, 1, 5);
        LocalDate r2s2 = LocalDate.of(2024, 1, 6);
        LocalDate r2e2 = LocalDate.of(2024, 1, 10);
        System.out.println(calculateOverlapDays(r1s2, r1e2, r2s2, r2e2)); // 输出0

        // 测试案例3:一个区间完全包含另一个
        LocalDate r1s3 = LocalDate.of(2024, 1, 1);
        LocalDate r1e3 = LocalDate.of(2024, 1, 20);
        LocalDate r2s3 = LocalDate.of(2024, 1, 5);
        LocalDate r2e3 = LocalDate.of(2024, 1, 15);
        System.out.println(calculateOverlapDays(r1s3, r1e3, r2s3, r2e3)); // 输出11(5号到15号共11天)

        // 测试案例4:区间首尾相连(比如range1结束于10号,range2开始于10号)
        LocalDate r1s4 = LocalDate.of(2024, 1, 1);
        LocalDate r1e4 = LocalDate.of(2024, 1, 10);
        LocalDate r2s4 = LocalDate.of(2024, 1, 10);
        LocalDate r2e4 = LocalDate.of(2024, 1, 15);
        System.out.println(calculateOverlapDays(r1s4, r1e4, r2s4, r2e4)); // 输出1(包含10号)
    }
}

为什么之前的方法会失效?

你之前直接用ChronoUnit.DAYS.between(LD1, LD2.plusDays(1))没有先判断重叠区间的有效性,当两个区间完全不重叠时,计算出来的天数会是负数,而如果直接拿这个负数参与后续的“取最小数”逻辑,就会得到错误的结果。通过先确定重叠边界,再用Math.max(overlapDays, 0)把负数转为0,就能完美解决这个问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 14:02:46