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

如何在C#中判断两个班次是否重叠?

C# 判断跨天班次是否重叠的实现方案

处理跨午夜的班次重叠判断,核心难点在于跨天班次的时间区间是循环的(比如22:00到次日7:00),直接比较起止小时会失效。以下是两种可靠的实现方案:

方案1:拆分为正常区间逐一比较

将跨天班次拆分为两个不跨天的区间(比如22-7拆为22-24和0-7),然后检查所有区间对是否存在交集。这种方法逻辑直观,易于维护。

代码实现

public class ShiftType
{
    public string Id { get; set; }
    public int StartHour { get; set; }
    public int EndHour { get; set; }
}

public static class ShiftOverlapChecker
{
    /// <summary>
    /// 判断两个班次是否重叠
    /// </summary>
    /// <param name="shift1">第一个班次</param>
    /// <param name="shift2">第二个班次</param>
    /// <returns>重叠返回true,否则返回false</returns>
    public static bool ShiftsOverlap(ShiftType shift1, ShiftType shift2)
    {
        // 检查两个左闭右开区间是否有交集
        bool IntervalsOverlap(int start1, int end1, int start2, int end2)
        {
            // 左闭右开区间交集条件:区间A的起始小于区间B的结束,且区间B的起始小于区间A的结束
            return start1 < end2 && start2 < end1;
        }

        // 将班次拆分为一个或多个不跨天的区间(确保start < end)
        List<(int Start, int End)> GetShiftIntervals(ShiftType shift)
        {
            var intervals = new List<(int, int)>();
            if (shift.StartHour < shift.EndHour)
            {
                intervals.Add((shift.StartHour, shift.EndHour));
            }
            else
            {
                // 跨天班次拆分为两段:当日Start到24点,0点到次日End
                intervals.Add((shift.StartHour, 24));
                intervals.Add((0, shift.EndHour));
            }
            return intervals;
        }

        var intervals1 = GetShiftIntervals(shift1);
        var intervals2 = GetShiftIntervals(shift2);

        // 遍历所有区间对,只要有一对交集则班次重叠
        foreach (var interval1 in intervals1)
        {
            foreach (var interval2 in intervals2)
            {
                if (IntervalsOverlap(interval1.Start, interval1.End, interval2.Start, interval2.End))
                {
                    return true;
                }
            }
        }

        return false;
    }
}

测试验证

以下是几个典型场景的测试结果:

  • 班次A(6-14)与班次B(14-22):无重叠,返回false
  • 班次C(22-7)与班次A(6-14):重叠(0-7与6-14有交集),返回true
  • 班次C(22-7)与班次D(8-16):无重叠,返回false
  • 班次E(22-7)与班次F(23-8):重叠(22-24与23-24有交集),返回true

方案2:反向判断不重叠场景

通过先判断两个班次完全不重叠的所有情况,再取反得到重叠结果。这种方法不需要拆分区间,适合追求性能的场景。

代码实现

public static class ShiftOverlapChecker
{
    public static bool ShiftsOverlap(ShiftType shift1, ShiftType shift2)
    {
        bool isNonOverlapping = false;

        if (shift1.StartHour < shift1.EndHour && shift2.StartHour < shift2.EndHour)
        {
            // 两者都不跨天:一个完全在另一个结束之后
            isNonOverlapping = shift1.EndHour <= shift2.StartHour || shift2.EndHour <= shift1.StartHour;
        }
        else if (shift1.StartHour < shift1.EndHour && shift2.StartHour > shift2.EndHour)
        {
            // shift1不跨天,shift2跨天:shift1完全在shift2的空白区间(End到Start)
            isNonOverlapping = shift1.StartHour >= shift2.EndHour && shift1.EndHour <= shift2.StartHour;
        }
        else if (shift1.StartHour > shift1.EndHour && shift2.StartHour < shift2.EndHour)
        {
            // shift1跨天,shift2不跨天:shift2完全在shift1的空白区间(End到Start)
            isNonOverlapping = shift2.StartHour >= shift1.EndHour && shift2.EndHour <= shift1.StartHour;
        }
        else
        {
            // 两者都跨天:必然重叠(都覆盖午夜时段,至少有部分交集)
            isNonOverlapping = false;
        }

        return !isNonOverlapping;
    }
}

逻辑说明

完全不重叠的场景仅存在三种情况:

  1. 两个非跨天班次完全错开(一个结束时间 ≤ 另一个开始时间)
  2. 非跨天班次完全落在跨天班次的空白时段(跨天班次的End到Start之间)
  3. 跨天班次的空白时段完全包含另一个非跨天班次

内容的提问来源于stack exchange,提问作者Gergő Sillye

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 18:45:53