如何在PHP中检查多个日期范围之间的重叠?

如何在PHP中检查多个日期范围之间的重叠?,php,algorithm,date,overlap,overlapping,Php,Algorithm,Date,Overlap,Overlapping,有很多关于检查两个日期之间重叠的帖子。然而,我找不到任何关于如何在多个范围之间进行检查的内容 假设我有这个数组: $ranges = [ array('start'=>'2014-01-01' , 'end'=> '2014-01-05'), array('start'=>'2014-01-06' > , 'end'=> '2014-01-10'), array('start'=>'2014-01-04' > , 'end'=> '2014-01-

有很多关于检查两个日期之间重叠的帖子。然而,我找不到任何关于如何在多个范围之间进行检查的内容

假设我有这个数组:

$ranges = [
array('start'=>'2014-01-01' , 'end'=> '2014-01-05'),
array('start'=>'2014-01-06' > , 'end'=> '2014-01-10'),
array('start'=>'2014-01-04' > , 'end'=> '2014-01-07')]
人们可能会简单地认为,检查两个范围之间重叠的函数可以在所有范围之间使用循环,但这是错误的,因为所有范围可以相互重叠,但不能全部重叠


我希望有人能帮我找到一个好的解决方案……

基于Raeef Refai Response算法只检查彼此相邻的日期,而不是整个日期范围列表。这里是一个经过调整的版本。希望这有帮助

<?php

// pass your ranges to this method and if there is a common intersecion it will
// return it or false

function checkIfOverlapped($ranges)
{
    $res = $ranges[0];

    $countRanges = count($ranges);

    for ($i = 1; $i < $countRanges; $i++) {

        $r1s = $res['start'];
        $r1e = $res['end'];

        $r2s = $ranges[$i]['start'];
        $r2e = $ranges[$i]['end'];

        if ($r1s >= $r2s && $r1s <= $r2e || $r1e >= $r2s && $r1e <= $r2e || $r2s >= $r1s && $r2s <= $r1e || $r2e >= $r1s && $r2e <= $r1e) {

            $res = array(
                'start' => $r1s > $r2s ? $r1s : $r2s,
                'end' => $r1e < $r2e ? $r1e : $r2e
            );

        } else return false;

    }

    return $res;
}

// example
$ranges = array(
    array('start' => '2014-01-01', 'end' => '2014-01-05'),
    array('start' => '2014-01-05', 'end' => '2014-01-10'),
    array('start' => '2014-01-04', 'end' => '2014-01-07')
);

var_dump(checkIfOverlapped($ranges));
$ranges = [
    ['2014-01-01','2014-01-05'],
    ['2014-01-05','2014-01-10'],
    ['2014-01-04','2014-01-07']
];

foreach($ranges as $key => $range){

  $r1s = $range[0];
  $r1e = $range[1];

  foreach($ranges as $key2 => $range2){
    if($key != $key2){
      $r2s = $range2[0];
      $r2e = $range2[1];

      if ($r1s >= $r2s && $r1s <= $r2e || $r1e >= $r2s && $r1e <= $r2e || $r2s >= $r1s && $r2s <= $r1e || $r2e >= $r1s && $r2e <= $r1e) {

          $res = array(
              '0' => $r1s > $r2s ? $r1s : $r2s,
              '1' => $r1e < $r2e ? $r1e : $r2e
          );
          break;
      }
    }
  }
}
$ranges=[
['2014-01-01','2014-01-05'],
['2014-01-05','2014-01-10'],
['2014-01-04','2014-01-07']
];
foreach($key=>$range的范围){
$r1s=$range[0];
$r1e=$range[1];
foreach($key2=>$range2的范围){
如果($key!=$key2){
$r2s=$range2[0];
$r2e=$range2[1];
如果($r1s>=$r2s&&$r1s=$r2s&&$r1e=$r1s&&$r2s=$r1s&&&$r2e$r1s>$r2s?$r1s:$r2s,
“1”=>$r1e<$r2e?$r1e:$r2e
);
打破
}
}
}
}

上述解决方案都不适合我,我在这里使用Carbon API进行日期比较,但如果不使用Carbon API,则可以通过正常的PHP日期比较来实现

PS:如果有人能优化此代码,我会很高兴。

公共静态函数checkOverlapinDaterRanges($ranges){
$P=[];
对于($i=0;$ibetween($start,$end)| | \Carbon\Carbon::parse($ranges[$i]['end'])->between($start,$end)){
$overlapp[]=$ranges[$j];
打破
}
如果(\Carbon\Carbon::parse($ranges[$j]['start'])->介于($start\u first,$end\u first)| \Carbon\Carbon::parse($ranges[$j]['end'])->介于($start\u first,$end\u first))之间{
$overlapp[]=$ranges[$j];
打破
}
}
}
返回$P;
}

如果在循环的第一次迭代中没有重叠,函数将返回false,并且不会进行进一步的比较。此函数用于查找公共交点,因此如果前两个之间没有交点,则为false。感谢您的解释。我理解OP是想知道是否有重叠或是否全部重叠,但是重新阅读它,很难确定OP在寻找哪个场景。要用本机PHP代码替换“between”函数,可以使用
if($start_first=$start){//overlap}
public static function checkOverlapInDateRanges($ranges) {
    $overlapp = [];
    for($i = 0; $i < count($ranges); $i++){
        for($j= ($i + 1); $j < count($ranges); $j++){

            $start = \Carbon\Carbon::parse($ranges[$j]['start']);
            $end = \Carbon\Carbon::parse($ranges[$j]['end']);

            $start_first = \Carbon\Carbon::parse($ranges[$i]['start']);
            $end_first = \Carbon\Carbon::parse($ranges[$i]['end']);

            if(\Carbon\Carbon::parse($ranges[$i]['start'])->between($start, $end) || \Carbon\Carbon::parse($ranges[$i]['end'])->between($start, $end)){
                $overlapp[] = $ranges[$j];
                break;
            }
            if(\Carbon\Carbon::parse($ranges[$j]['start'])->between($start_first, $end_first) || \Carbon\Carbon::parse($ranges[$j]['end'])->between($start_first, $end_first)){
                $overlapp[] = $ranges[$j];
                break;
            }
        }
    }
    return $overlapp;
}