Check date ranges (start and end date) for overlap
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | function checkDateOverlap($ranges) { $res = $ranges[0]; $countRanges = count($ranges); for ($i = 0; $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 of returned dates that overlap $ranges = array( array('start' => '2014-01-01', 'end' => '2014-01-04'), array('start' => '2014-01-05', 'end' => '2014-01-10'), array('start' => '2014-01-04', 'end' => '2014-01-07') ); //example of failure $ranges2 = array( array('start' => '2014-01-01', 'end' => '2014-01-04'), array('start' => '2014-01-05', 'end' => '2014-01-10'), array('start' => '2014-01-11', 'end' => '2014-01-17') ); var_dump(checkDateOverlap($ranges)); |
以下是我试图检查日期范围的交集的内容。在数组" ranges1"中,此示例具有重叠的日期。它应该返回日期。在数组$ ranges2中,这应该作为没有相交的日期通过。
现在很奇怪的是,开始日期和结束日期可以完全相同,因此您可以输入一天的时间。我尝试了很多事情,但感到很困惑。
我相信还需要一个for循环,但是不管我没有获得成功。
这是我的另一项尝试:
1 | <?php |
//将您的范围传递给此方法,如果存在常见的相交,它将
//返回或为false
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | function checkDateOverlap($ranges){ $res = $ranges[0]; $countRanges = count($ranges); for ($i = 0; $i < count($countRanges); $i++) { for($j = $i+1; $j < count($countRanges); $j++) { $r1s = $res['start']; $r1e = $res['end']; $r2s = $ranges[$i]['start']; $r2e = $ranges[$i]['end']; if (($r1s >= $r2e && $r2s <= $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-04', 'end' => '2014-01-05'), array('start' => '2014-01-06', 'end' => '2014-01-10'), array('start' => '2014-01-11', 'end' => '2014-01-13') ); echo"[cc lang="php"]"; var_dump(checkDateOverlap($ranges)); echo" |
";
code> pre>
任何建议,我们将不胜感激。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | $ranges = array( array('start' => new DateTime('2014-01-01'), 'end' => new DateTime('2014-01-05')), array('start' => new DateTime('2014-01-06'), 'end' => new DateTime('2014-01-06')), array('start' => new DateTime('2014-01-07'), 'end' => new DateTime('2014-01-07')), ); function intersects($lhs, $rhs) { // Note that this function allows ranges that"touch", // eg. one pair starts at the exact same time that the other ends. // Adding less"or equal to" will allow same start date return !($lhs['start'] > $rhs['end'] || $lhs['end'] < $rhs['start']); } function checkDates($ranges) { // Comparison loop is of size n?log(n), not doing any redundant comparisons for($i = 0; $i < sizeof($ranges); $i++) { for($j = $i+1; $j < sizeof($ranges); $j++) { if(intersects($ranges[$i], $ranges[$j])) { echo"Date {$i} intersects with date {$j}\ "; } } } } checkDates($ranges); |
我已附上我的工作代码示例,希望将来可以帮助其他人寻找相同的解决方案。这将打印相交的数组。
以下是一些注意事项:
-您不检查由"开始"和"结束"形成的日期的有效性。
-为什么不将日期转换为时间戳?
->比较整数值而不是字符串更容易,更快捷?
为什么不使用PHP DateTime和DateInterval对象?
http://php.net/manual/zh/book.datetime.php
如果您使用usort首先对日期进行排序,则工作会容易得多。以下内容可以进行很多优化,但是它是分步完成的,因此更易于理解。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | //The date comparison function, sort on start and then on end function cmp($a, $b) { if($a['start']<$b['start']) return -1; if($a['start']>$b['start']) return 1; if($a['end']<$b['end']) return -1; if($a['end']>$b['end']) return 1; return 0; // start=start and end=end } $ranges = array( array('start' => '2014-01-01', 'end' => '2014-01-04'), array('start' => '2014-01-05', 'end' => '2014-01-10'), array('start' => '2014-01-04', 'end' => '2014-01-07') ); usort($ranges, 'cmp'); // Sort the dates $output = array(); for($i=0; $i<sizeof($ranges); $i++) { $endindex = $i; // The index containing the proper 'end' value for($j=$i+1; $j<sizeof($ranges); $j++) { if($ranges[$endindex]['start'] == $ranges[$j]['start']) // Overlap $endindex = $j; elseif($ranges[$endindex]['end']>=$ranges[$j]['start']) // Overlap $endindex = $j; } $output[] = array('start' => $ranges[$i]['start'], 'end' => $ranges[$endindex]['end']); // Break the rules by hard-setting $i from the for loop - it works great in this case $i = $endindex; } print_r($output); |
它适用于您的示例。如果必须使用其他规则,则希望可以调整此代码。