【问题标题】:Determining if two time ranges overlap at any point [duplicate]确定两个时间范围是否在任何点重叠[重复]
【发布时间】:2012-11-03 11:03:27
【问题描述】:

可能重复:
Determine Whether Two Date Ranges Overlap

我正在尝试确定 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 时间戳有关,与显示的实际时间不匹配。我感谢那些与我一起工作的人,并帮助我发现问题所在。我希望我能同时接受 Andrey 和 Jason 的回答。

【问题讨论】:

  • 在你的例子中 red.start is 低于 orange.end 而 red.end is 优于 orange.start...
  • +1,有兴趣看看有 200 多票赞成的答案是否有 错误
  • 从来没有说过它有错误,它的答案是正确的。我对答案的使用是问题所在。查看下面的答案进一步巩固了这一点,我现在正在尝试。
  • 你的逻辑应该起作用。你能发布$red$orange 的值吗?
  • @Michael Irigoyen:您作为示例提供的范围不重叠。橙色以1352907000 结束,而红色以1352923200 开始,后者更晚。没有冲突。所以比较失败了,因为它应该。

标签: php algorithm


【解决方案1】:
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

}

【讨论】:

  • 不需要额外的逻辑。
【解决方案2】:

The logic 是正确的。您为$red(晚上8-8:50)和$orange(下午1:30-3:30)提供的时间戳不重叠

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

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';
}

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

【讨论】:

  • 我开始认为你是对的。我现在更仔细地查看时间戳,虽然时间显示正确,但 UNIX 时间戳不正确,因此看起来班次没有重叠,而实际上确实如此。
  • 你是如何进行时间戳转换的? strtotime()?
  • 一项已经包含在 UNIX 时间戳中(来自日历框架)。另一项来自日期时间对象,然后是strtotime'd。那里的某个地方发生了不一致。我相信我能找到它。
【解决方案3】:

如果您有两个范围 [b1, e1][b2, e2](已经确定 b1 &lt; e1b2 &lt; 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. 您在编辑中提供的样本范围不重叠,并且您的比较正确地将其识别为无冲突情况。 IE。一切正常。您认为问题在哪里?

【讨论】:

    【解决方案4】:

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

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

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

    【讨论】:

    • 这太可悲了。最重要的是,如果您使用形式逻辑的规则简化这种冗余检查,您将得到 OP 在他的版本中的确切内容
    • 是的,您是对的,您的答案得到了更好的解释并且完美运行。无论如何都不需要悲惨地使用这个词并批评你自己的所有其他答案:)
    • 不需要额外的逻辑。
    猜你喜欢
    • 2017-06-28
    • 2016-02-14
    • 2011-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-30
    • 2021-12-27
    • 1970-01-01
    相关资源
    最近更新 更多