确定两个时间范围是否在任何点重叠

时间:2012-11-14 21:17:56

标签: php algorithm

  

可能重复:
  Determine Whether Two Date Ranges Overlap

我想弄清楚如果PHP中的两个时间范围重叠。我最初的尝试一直指的是Determine Whether Two Date Ranges Overlap,然而,它并不匹配所有情况。如果时间范围嵌套在另一个时间范围的开始和结束时间之间,则它不匹配。如果它与班次的开始或结束重叠,或者如果班次完全匹配,则按预期工作。

查看我正在谈论的图像:

enter image description here

基本上,我试图隐藏任何橙色移位,如果它们在任何地方重叠任何红色移位。这是我试图用来实现这一目标的相关代码部分。

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 个答案:

答案 0 :(得分:8)

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

not (e2 < b1 or e1 < b2)

可以改写为

e2 >= b1 and e1 >= b2

在您的语法中

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

<强>即。你得到了正确的答案。为什么你声称​​“逻辑地处理数字,我理解为什么上面的陈述失败了。”对我来说并不清楚。究竟什么失败了? (而且我不知道为什么每个人都会提出荒谬的“过度工程”检查,并进行两次以上的比较。)

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

P.S。您在编辑中提供的示例范围不会重叠,您的比较会将其正确识别为无冲突情况。即一切都按预期工作。你在哪里看到这个问题?

答案 1 :(得分:6)

The logic是正确的。您为$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';
}

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

答案 2 :(得分:1)

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

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

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

答案 3 :(得分: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

}