确定两个日期范围是否重叠
给定两个日期范围,确定两个日期范围是否重叠的最简单或最有效的方法是什么?
Given two date ranges, what is the simplest or most efficient way to determine whether the two date ranges overlap?
举个例子,假设我们有由 DateTime 变量表示的范围 StartDate1
到 EndDate1
and StartDate2
到 EndDate2.
As an example, suppose we have ranges denoted by DateTime variables StartDate1
to EndDate1
and StartDate2
to EndDate2
.
(StartA
证明:
让 ConditionA 表示 DateRange A 完全在 DateRange B 之后
Proof:
Let ConditionA Mean that DateRange A Completely After DateRange B
_ |---- DateRange A ------|
|---Date Range B -----| _
(如果 StartA > EndB
为真)
令 ConditionB 表示 DateRange A 完全在 DateRange B 之前
Let ConditionB Mean that DateRange A is Completely Before DateRange B
|---- DateRange A -----| _
_ |---Date Range B ----|
(如果 EndA
如果 A 和 B 都不为真,则存在重叠 -
(如果一个范围既不完全在另一个范围之后,
也不完全在另一个之前,那么它们必须重叠.)
Then Overlap exists if Neither A Nor B is true -
(If one range is neither completely after the other,
nor completely before the other,
then they must overlap.)
现在德摩根定律之一说:
不是(A 或 B)
不是A也不是B
翻译成:(StartA <= EndB) and (EndA >= StartB)
注意:这包括边缘完全重叠的情况.如果你想排除那个,
将 >=
运算符更改为 >
,并将 更改为
<
NOTE: This includes conditions where the edges overlap exactly. If you wish to exclude that,
change the >=
operators to >
, and <=
to <
注意2.感谢@Baodad,见这篇博客,实际重叠的是最少的:
{ endA-startA
, endA - startB
, endB-startA
, endB - startB
}
NOTE2. Thanks to @Baodad, see this blog, the actual overlap is least of:
{ endA-startA
, endA - startB
, endB-startA
, endB - startB
}
(StartA = StartB)
(StartA
注意3.感谢@tomosius,一个更短的版本如下:DateRangesOverlap = max(start1, start2)
这实际上是更长实现的语法快捷方式,其中包括额外的检查以验证开始日期是否在 endDates 上或之前.从上面推导出来:
NOTE3. Thanks to @tomosius, a shorter version reads:DateRangesOverlap = max(start1, start2) < min(end1, end2)
This is actually a syntactical shortcut for what is a longer implementation, which includes extra checks to verify that the start dates are on or before the endDates. Deriving this from above:
如果开始和结束日期可能乱序,即,如果 startA >endA
或 startB >endB
,那么你还必须检查它们是否有序,这意味着你必须添加两个额外的有效性规则:(StartA 或:
(StartA 或者,
(StartA 或:
(Max(StartA, StartB)
If start and end dates can be out of order, i.e., if it is possible that startA > endA
or startB > endB
, then you also have to check that they are in order, so that means you have to add two additional validity rules:(StartA <= EndB) and (StartB <= EndA) and (StartA <= EndA) and (StartB <= EndB)
or:(StartA <= EndB) and (StartA <= EndA) and (StartB <= EndA) and (StartB <= EndB)
or,(StartA <= Min(EndA, EndB) and (StartB <= Min(EndA, EndB))
or:(Max(StartA, StartB) <= Min(EndA, EndB)
但是要实现Min()
和Max()
,你必须编码,(为了简洁,使用C三元),:(StartA > StartB? Start A: StartB)
But to implement Min()
and Max()
, you have to code, (using C ternary for terseness),:(StartA > StartB? Start A: StartB) <= (EndA < EndB? EndA: EndB)