给定两个日期范围,确定两个日期范围是否重叠的最简单或最有效的方法是什么?
例如,假设我们有 DateTime 变量StartDate1
到EndDate1
和 StartDate2
到EndDate2
表示的范围。
(StartA <= EndB)和(EndA> = StartB)
证明:
让 ConditionA 在 DateRange B 之后完全表示 DateRange A.
_ |---- DateRange A ------| |---Date Range B -----| _
(如果StartA > EndB
True)
设 ConditionB 表示 DateRange A 完全在 DateRange B 之前
|---- DateRange A -----| _ _ |---Date Range B ----|
(如果EndA < StartB
真)
如果 A Nor B 都不成立则存在重叠 -
(如果一个范围既不完全在另一个范围之后,
也不完全在另一个之前,那么它们必须重叠。)
Not (A Or B)
<=> Not A And Not B
转换为: (StartA <= EndB) and (EndA >= StartB)
注意:这包括边缘完全重叠的条件。如果你想排除它,
将>=
运算符更改为>
,并将<=
更改为<
笔记 2。感谢 @Baodad,请参阅此博客 ,实际重叠最少:
{ endA-startA
, endA - startB
, endB-startA
, endB - startB
}
(StartA <= EndB) and (EndA >= StartB)
(StartA <= EndB) and (StartB <= EndA)
注 3。感谢 @tomosius,更短版本的内容如下:
DateRangesOverlap = max(start1, start2) < min(end1, end2)
这实际上是更长实现的语法快捷方式,其中包括额外的检查以验证开始日期是在 endDates 之前还是之前。从上面得出这个:
如果开始日期和结束日期可能不正常,即,如果startA > endA
或startB > endB
,那么您还必须检查它们是否有序,这意味着您必须添加两个额外的有效性规则:
(StartA <= EndB) and (StartB <= EndA) and (StartA <= EndA) and (StartB <= EndB)
或:
(StartA <= EndB) and (StartA <= EndA) and (StartB <= EndA) and (StartB <= EndB)
或,
(StartA <= Min(EndA, EndB) and (StartB <= Min(EndA, EndB))
或:
(Max(StartA, StartB) <= Min(EndA, EndB)
但是要实现Min()
和Max()
,你必须编写代码,(使用 C 三元语言来表示简洁性):
(StartA > StartB? Start A: StartB) <= (EndA < EndB? EndA: EndB)
我认为,如果符合以下条件,两个范围重叠就足够了:
(StartDate1 <= EndDate2) and (StartDate2 <= EndDate1)
本文的Time Period Library for .NET通过枚举PeriodRelation描述了两个时间段的关系:
// ------------------------------------------------------------------------
public enum PeriodRelation
{
After,
StartTouching,
StartInside,
InsideStartTouching,
EnclosingStartTouching,
Enclosing,
EnclosingEndTouching,
ExactMatch,
Inside,
InsideEndTouching,
EndInside,
EndTouching,
Before,
} // enum PeriodRelation