[英]Check date ranges (start and end date) for overlap
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));
The following is what I was attempting to check intersection of date ranges. 以下是我试图检查日期范围的交集。 In the array "ranges1" this example has overlapping dates.
在数组“ ranges1”中,此示例具有重叠的日期。 It should return the dates.
它应该返回日期。 In array $ranges2, this should pass as no intersecting dates.
在数组$ ranges2中,这应该作为没有相交的日期通过。
Now the weird thing is the start and end date can be the exact same, so you could make an entry for just a single day. 现在很奇怪的是,开始日期和结束日期可以完全相同,因此您可以输入一天的时间。 I've tried many things, and I'm stumped.
我尝试了很多事情,但感到很困惑。
I believe there needs to be another for loop, but regardless I am not getting success. 我相信还需要另一个for循环,但是不管我没有获得成功。
Here was another go I had: 这是我的另一项尝试:
<?php
// pass your ranges to this method and if there is a common intersecion it will // return it or false //将范围传递给此方法,如果存在普通的相交,它将//返回它,否则返回false
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 "<pre>";
var_dump(checkDateOverlap($ranges));
echo "</pre>";
Any advice greatly appreciated. 任何建议,不胜感激。
$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}\n";
}
}
}
}
checkDates($ranges);
I've attached my working code sample to hopefully help someone else in the future looking for the same solution. 我已经附上了我的工作代码示例,希望将来可以帮助其他人寻找相同的解决方案。 This will print the arrays that intersect.
这将打印相交的数组。
If you use usort to first sort the dates, the work gets a lot easier. 如果您使用usort首先对日期进行排序,则工作会容易得多。 The following can be optimized a lot, but it is done step-by-step make it easier to understand.
以下内容可以进行很多优化,但是分步完成使它更易于理解。
//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);
It works for your example. 它适用于您的示例。 If you have other rules that must be used, hopefully you can adjust this code.
如果您还有其他必须使用的规则,则希望可以调整此代码。
Here are some remarks: 以下是一些注意事项:
- You do not check the validity of the date formed by 'start' and 'end'. -您不检查“开始”和“结束”形成的日期的有效性。
- Why do you not convert the dates to timestamp ? -为什么不将日期转换为时间戳?
-> It's more easier and faster to compare integer value instead of string ? ->比较整数值而不是字符串更容易,更快。
Why do you not use PHP DateTime and DateInterval Objects ? 为什么不使用PHP DateTime和DateInterval对象?
http://php.net/manual/en/book.datetime.php http://php.net/manual/en/book.datetime.php
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.