给定两个日期范围,确定两个日期是否重叠的最简单或最有效的方法是什么?
例如,假设我们有由DateTime变量StartDate1到EndDate1和StartDate2到EndDate2表示的范围。
给定两个日期范围,确定两个日期是否重叠的最简单或最有效的方法是什么?
例如,假设我们有由DateTime变量StartDate1到EndDate1和StartDate2到EndDate2表示的范围。
当前回答
记住解决方案的一个简单方法是最小(结束)>最大(开始)
其他回答
将问题分为几个案例,然后处理每个案例。
“两个日期范围相交”的情况有两种情况:第一个日期范围从第二个开始,或者第二个日期范围在第一个开始。
如果重叠本身也需要计算,可以使用以下公式:
overlap = max(0, min(EndDate1, EndDate2) - max(StartDate1, StartDate2))
if (overlap > 0) {
...
}
我遇到过这样的情况,我们有日期而不是日期时间,并且日期只能在开始/结束时重叠。示例如下:
(绿色是当前间隔,蓝色块是有效间隔,红色块是重叠间隔)。
我将Ian Nelson的答案改编为以下解决方案:
(startB <= startA && endB > startA)
|| (startB >= startA && startB < endA)
这匹配所有重叠情况,但忽略允许的重叠情况。
由于对于不同的语言和环境有多种答案,这里有一个标准ANSISQL的答案。
在标准SQL中,它非常简单
(StartDate1, EndDate1) overlaps (StartDate2, EndDate2)
假设所有四列都是DATE或TIMESTAMP列。如果两个范围至少有一天相同(假设DATE值),则返回true
(但并非所有DBMS产品都支持此功能)
在PostgreSQL中,使用日期范围也很容易测试是否包含
daterange(StartDate1, EndDate1) @> daterange(StartDate2, EndDate2)
如果第二个范围完全包含在第一个范围中(与“重叠”不同),则上述值返回真
为了涵盖PHP/LaravelCarbon包中的所有重叠情况,您可以在Charles的答案中展开逻辑,如下所示。
if ( ($startTime1->between($startTime2, $endTime2, true) || $endTime1->between($startTime2, $endTime2, true)) || (($startTime1 <= $endTime2) && ($endTime2 <= $endTime1)) ){
//Complete Overlap, Partial Left Overlap, Partial Right Overlap.
}
这将检查StartTime1是否在(StartTime2-EndTime2)范围之间,或者EndTime1是否位于(StartTime2-EndTime2的范围之间。
其余部分完全重叠,如其他答案所述。