如何在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;
}