简体   繁体   English

检查日期范围(开始和结束日期)是否有重叠

[英]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.

相关问题 MySQL / PHP查询-检查输入的开始/结束日期不与Db中的现有日期范围重叠 - MySQL / PHP Query - check that entered start/end dates don't overlap existing date ranges in Db 从日期范围列表中获取开始和结束日期 - Get start and end date from a list of date ranges mysql开始日期和结束日期 - mysql start date and end date 检查输入的开始日期和结束日期是否在数据库中已经开始的日期和结束日期之间 - Check if the start and end date entered is between the already start and end date in database 如何在codeigniter中使用开始时间和结束时间检查旅行开始日期和结束日期 - How to check trip start-date and end-date with start-time and end-time in codeigniter 检查日期是否在多个日期范围的范围内 - Check if date is in range of multiple date ranges 从MySql中抓取当前日期在开始日期和结束日期之间的行(检查当前日期是否在开始日期和结束日期之间) - Grabbing rows from MySql where current date is in between start date and end date (Check if current date lies between start date and end date) 找出两个日期范围在 PHP 中重叠的天数 - Find out by how many days two date ranges overlap in PHP 如何检查引导日期中的时间重叠 - How to check time overlap in bootstrap date 如果在范围内找到,如何找到 start_time 和 end_time 范围,然后检查 start_date 和 end_date - How to find the start_time and end_time range if found in the range then check start_date and end_date
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM