给定两个日期范围,确定两个日期是否重叠的最简单或最有效的方法是什么?
例如,假设我们有由DateTime变量StartDate1到EndDate1和StartDate2到EndDate2表示的范围。
给定两个日期范围,确定两个日期是否重叠的最简单或最有效的方法是什么?
例如,假设我们有由DateTime变量StartDate1到EndDate1和StartDate2到EndDate2表示的范围。
当前回答
本文《.NET时间段库》通过枚举PeriodRelation描述了两个时间段之间的关系:
// ------------------------------------------------------------------------
public enum PeriodRelation
{
After,
StartTouching,
StartInside,
InsideStartTouching,
EnclosingStartTouching,
Enclosing,
EnclosingEndTouching,
ExactMatch,
Inside,
InsideEndTouching,
EndInside,
EndTouching,
Before,
} // enum PeriodRelation
其他回答
这是我使用moment.js的javascript解决方案:
// Current row dates
var dateStart = moment("2014-08-01", "YYYY-MM-DD");
var dateEnd = moment("2014-08-30", "YYYY-MM-DD");
// Check with dates above
var rangeUsedStart = moment("2014-08-02", "YYYY-MM-DD");
var rangeUsedEnd = moment("2014-08-015", "YYYY-MM-DD");
// Range covers other ?
if((dateStart <= rangeUsedStart) && (rangeUsedEnd <= dateEnd)) {
return false;
}
// Range intersects with other start ?
if((dateStart <= rangeUsedStart) && (rangeUsedStart <= dateEnd)) {
return false;
}
// Range intersects with other end ?
if((dateStart <= rangeUsedEnd) && (rangeUsedEnd <= dateEnd)) {
return false;
}
// All good
return true;
适合我的紧凑公式
class ValidityRuleRange {
private final Date from;
private final Date to;
...
private boolean isOverlap(ValidityRuleRange vrr) {
int c1 = from.compareTo(vrr.getTo());
int c2 = to.compareTo(vrr.getFrom());
return c1 == 0 || c2 == 0 || c1 + c2 == 0;
}
我认为,在以下情况下,两个范围重叠就足够了:
(StartDate1 <= EndDate2) and (StartDate2 <= EndDate1)
这里是我的简化。假设时间间隔
| |
| |
不要重叠,xa<xb和ya<yb可以简化处理。上述条件可以简单检查。然后你会得到
ya yb
|--------|
xa |--|xb
|----|
|----|
ya > xa => return ya - xa < xb - xa
else => return xa < yb
正如您可能注意到的,第二个间隔仅在xa>=ya的情况下相关。
为了涵盖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的范围之间。
其余部分完全重叠,如其他答案所述。