13

可能重复:
确定两个日期范围是否重叠

我正在尝试确定 PHP 中的两个时间范围是否重叠。在我最初的尝试中,我一直在参考确定两个日期范围是否重叠,但是,它并不匹配所有情况。如果一个时间范围嵌套在另一个时间范围的开始时间和结束时间之间,则不匹配。如果它与班次的开始或结束重叠,或者班次完全匹配,则它按预期工作。

看看我在说什么的这张图片:

在此处输入图像描述

基本上,如果橙色变化与任何地方的任何红色变化重叠,我会尝试隐藏它们。这是我试图用来实现这一点的代码的相关部分。

if(($red['start'] <= $orange['end']) && ($red['end'] >= $orange['start'])) {
    //Conflict handling
}

变量的值是 UNIX 时间戳。从逻辑上处理这些数字,我理解为什么上面的陈述失败了。显然,我可以做更多的逻辑来确定一个班次是否属于另一个班次(这是我可能需要做的),但我希望有一个更普遍的捕获。

编辑:添加每个块的开始和结束时间的值。我同意我所拥有的应该工作。事实上,它不是我的问题所在。我可能忽略了一些愚蠢的事情。

orange-start = 1352899800
orange-end = 1352907000

red-start = 1352923200
red-end = 1352926200

因此我的逻辑会说:

if((1352923200 <= 1352907000) && (1352926200 >= 1352899800))

因此,在此之后,第一次比较失败。

编辑 2:看起来我的逻辑是合理的(我认为是这种情况),我的问题与 UNIX 时间戳有关,与显示的实际时间不匹配。我感谢那些与我一起工作的人,并帮助我发现问题所在。我希望我能接受安德烈和杰森的回答。

4

4 回答 4

10

如果您有两个范围[b1, e1]and [b2, e2](已经确定b1 < e1and b2 < e2),则通过以下逻辑表达式检测重叠

not (e2 < b1 or e1 < b2)

可以重写为

e2 >= b1 and e1 >= b2

在你的语法中

if(($orange['end'] >= $red['start']) && ($red['end'] >= $orange['start'])) {
   //Conflict handling
}

即你得到了正确的。为什么您声称“从逻辑上处理数字,我明白为什么上面的陈述失败了。” 我不清楚。究竟是什么失败了?(而且我不知道为什么每个人都提出了可笑的“过度设计”检查,并进行了两次以上的比较。)

当然,您必须决定是否将接触范围视为重叠,并相应地调整比较的严格程度。

PS您在编辑中提供的样本范围不重叠,并且您的比较正确地将其识别为无冲突情况。即一切正常。你在哪里看到问题?

于 2012-11-14T21:42:57.527 回答
7

逻辑是正确的。您为$red(8-8:50pm) 和$orange(1:30-3:30pm)提供的时间戳不重叠

给定正确的值(反映您的屏幕截图),确实发现了重叠:

function show_date($value, $key) {
    echo $key, ': ', date('r', $value), PHP_EOL;
}

$red = array('start' => strtotime('today, 2pm'), 'end' => strtotime('today, 2:45pm'));
$orange = array('start' => strtotime('today, 1:30pm'), 'end' => strtotime('today, 4pm'));

array_walk($red, 'show_date');
array_walk($orange, 'show_date');

if (($red['start'] <= $orange['end']) && ($red['end'] >= $orange['start'])) {
    echo 'Conflict handling';
}

我的猜测是你有一个时区转换问题。

于 2012-11-14T22:00:43.837 回答
1

您需要检查您是否有一个“红色”任务,该任务在“橙色”任务的开始和结束之间开始或结束。像这样,您应该检测与“RED”任务重叠的每个“ORANGE”任务。

if((($red['start'] <= $orange['end']) && ($red['start'] >= $orange['start'])) ||
   (($red['end'] <= $orange['end']) && ($red['end'] >= $orange['start'])) ) {
    //Conflict handling
}

编辑:正如 AndreyT 所说,这有点矫枉过正,你可以用更少的检查做得更好

于 2012-11-14T21:26:16.230 回答
0
if ((($red['start'] <= $orange['end']) && ($red['start'] >= $orange['start']))
    || (($red['end'] <= $orange['end']) && ($red['end'] >= $orange['start']))
    || (($red['start'] >= $orange['start']) && ($red['end'] >= $orange['end']))
   ) {
 // conflict happens if Red starts sometime between Orange start and end
 //               or if Red ends sometime between Orange start and end
 //               or if Red starts before Orange starts and ends after Orange ends

}
于 2012-11-14T21:32:56.320 回答