我要检测两个时间段是否重叠。 每个周期都有开始日期和结束日期。 我需要检测我的第一个时间段(A)是否与另一个时间段(B/C)重叠。 在我的例子中,如果B的起点等于A的终点,它们就不重叠(倒数也是) 我发现了以下几个案例:

实际上我是这样做的:

tStartA < tStartB && tStartB < tEndA //For case 1
OR
tStartA < tEndB && tEndB <= tEndA //For case 2
OR
tStartB < tStartA  && tEndB > tEndA //For case 3

(情况4在情况1或情况2的账户中被计入)

这是可行的,但似乎不是很有效。

首先,c#中有一个现有的类可以对这个(时间段)进行建模,类似于一个时间跨度,但是有一个固定的开始日期。

其次:是否已经有c#代码(如在DateTime类)可以处理这个问题?

第三:如果没有,你会用什么方法最快地进行比较?


当前回答

CodeProject上有一个很棒的库,评论也很好:http://www.codeproject.com/Articles/168662/Time-Period-Library-for-NET

这个库做了很多关于重叠、交叉等方面的工作。它太大了,不能全部复制/粘贴,但我会看看哪些具体的部分对你有用。

其他回答

自定义间隔树结构如何?您必须稍微调整一下,以定义在定义域中两个间隔“重叠”的含义。

这个问题可能会帮助你在c#中找到一个现成的间隔树实现。

这是我的解决方案:

public static bool OverlappingPeriods(DateTime aStart, DateTime aEnd,
                                      DateTime bStart, DateTime bEnd)
{
    if (aStart > aEnd)
        throw new ArgumentException("A start can not be after its end.");

    if(bStart > bEnd)
        throw new ArgumentException("B start can not be after its end.");

    return !((aEnd < bStart && aStart < bStart) ||
                (bEnd < aStart && bStart < aStart));
}

我进行了单元测试,覆盖率为100%。

这段代码检查两个间隔是否重叠。

---------|---|
---|---|                > FALSE
xxxxxxxxxxxxxxxxxxxxxxxxx
-------|---|
---|---|                > FALSE
xxxxxxxxxxxxxxxxxxxxxxxxx
------|---|
---|---|                > TRUE
xxxxxxxxxxxxxxxxxxxxxxxxx
---|---|
---|--|                 > TRUE
xxxxxxxxxxxxxxxxxxxxxxxxx
----|---|
---|-----|              > TRUE
xxxxxxxxxxxxxxxxxxxxxxxxx
---|---|
----|-|                 > TRUE
xxxxxxxxxxxxxxxxxxxxxxxxx
---|---|
----|--|                > TRUE
xxxxxxxxxxxxxxxxxxxxxxxxx
---|---|
---|---|                > TRUE
xxxxxxxxxxxxxxxxxxxxxxxxx
---|---|
----|---|               > TRUE
xxxxxxxxxxxxxxxxxxxxxxxxx
---|---|
-------|---|            > FALSE
xxxxxxxxxxxxxxxxxxxxxxxxx
---|---|
--------|---|           > FALSE

算法:

x1 < y2
and
x2 > y1

例如12:00 - 12:30和12:30 13:00不重叠

你可以创建一个可重用的Range模式类:

public class Range<T> where T : IComparable
{
    readonly T min;
    readonly T max;

    public Range(T min, T max)
    {
        this.min = min;
        this.max = max;
    }

    public bool IsOverlapped(Range<T> other)
    {
        return Min.CompareTo(other.Max) < 0 && other.Min.CompareTo(Max) < 0;
    }

    public T Min { get { return min; } }
    public T Max { get { return max; } }
}

你可以添加所有你需要的方法来合并范围,获得交集等等…

简单检查两个时间段是否重叠:

bool overlap = a.start < b.end && b.start < a.end;

或者在你的代码中:

bool overlap = tStartA < tEndB && tStartB < tEndA;

(如果你改变了主意,想说两个刚刚接触的周期重叠,可以用<=代替<。)