我想弄清楚如果PHP中的两个时间范围重叠。我最初的尝试一直指的是Determine Whether Two Date Ranges Overlap,然而,它并不匹配所有情况。如果时间范围嵌套在另一个时间范围的开始和结束时间之间,则它不匹配。如果它与班次的开始或结束重叠,或者如果班次完全匹配,则按预期工作。
查看我正在谈论的图像:
基本上,我试图隐藏任何橙色移位,如果它们在任何地方重叠任何红色移位。这是我试图用来实现这一目标的相关代码部分。
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时间戳不匹配的实际时间。我感谢那些和我一起工作过的人,并帮助我发现这个问题。我希望我能接受安德烈和杰森的答案。
答案 0 :(得分:8)
如果您有两个范围[b1, e1]
和[b2, e2]
(已经确定b1 < e1
和b2 < 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
}