简体   繁体   English

从日期/时间范围数组中排除重叠的日期/时间范围

[英]Exclude date/time ranges from an array of date/time ranges with overlapping

Hope you are doing great!! 希望你过得很好!!

I'm kind of stuck with this, what I've done only work when there are not overlapping and anyway am not sure it's the correct approach. 我有点坚持,我所做的只是在没有重叠的情况下才起作用,而且无论如何都不确定这是正确的方法。

So my current implementation is to merge all times (start_time and end_time as different entry in that array), sort them and remove duplicates if any. 因此,我当前的实现是合并所有时间(start_time和end_time作为该数组中的不同条目),对其进行排序并删除重复项(如果有)。

Then I loop into that list and check for each if they are within $times ranges and not within restrictions ranges. 然后,我进入该列表,并检查它们是否在$ times范围内,而不在限制范围内。

All those which pass these condition are added to another list. 所有通过这些条件的对象都将添加到另一个列表中。 Then finally i'll loop through that list '2 item at a time' and build the final array of time ranges. 最后,我将遍历该列表“一次2个项目”,并构建最终的时间范围数组。

Codes: https://3v4l.org/2elDs (Laravel, using Collection and Carbon, so won't run there) 代码: https ://3v4l.org/2elDs(Laravel,使用Collection和Carbon,所以不会在那里运行)

Sample without date/time overlapping: 没有日期/时间重叠的样本:

$times = [
        [
            'start_time' => '2017-06-26 00:00:00',
            'end_time' => '2017-06-26 05:00:00',
        ],
        [
            'start_time' => '2017-06-26 13:00:00',
            'end_time' => '2017-06-26 18:00:00',
        ]
    ];

$timesToExclude= [
        [
            'start_time' => '2017-06-26 04:00:00',
            'end_time' => '2017-06-26 04:30:00',
        ],
        [
            'start_time' => '2017-06-26 07:00:00',
            'end_time' => '2017-06-26 10:00:00',
        ],
        [
            'start_time' => '2017-06-26 15:00:00',
            'end_time' => '2017-06-26 16:00:00',
        ]
    ];

Result to: 结果为:

    $result = [
        [
            "start_time" => "2017-06-26 00:00:00",
            "end_time"   => "2017-06-26 04:00:00"
        ], [
            "start_time" => "2017-06-26 04:30:00",
            "end_time"   => "2017-06-26 05:00:00"
        ],
        [
            "start_time" => "2017-06-26 13:00:00",
            "end_time"   => "2017-06-26 15:00:00"
        ],
        [
            "start_time" => "2017-06-26 16:00:00",
            "end_time"   => "2017-06-26 18:00:00"
        ]
    ]

Sample with date/time overlapping 日期/时间重叠的样本

    $times = [
        [
            'start_time' => '2017-06-26 00:00:00',
            'end_time'   => '2017-06-26 10:00:00',
        ],
        [
            'start_time' => '2017-06-26 05:00:00',
            'end_time'   => '2017-06-26 20:00:00',
        ]
    ];

    $timesToExclude= [
        [
            'start_time' => '2017-06-26 04:00:00',
            'end_time'   => '2017-06-26 04:30:00',
        ],
        [
            'start_time' => '2017-06-26 07:00:00',
            'end_time'   => '2017-06-26 09:00:00',
        ],
        [
            'start_time' => '2017-06-26 15:00:00',
            'end_time'   => '2017-06-26 16:00:00',
        ]
    ];

Should result to: 结果应为:

$result = [
        [
            "start_time" => "2017-06-26 00:00:00",
            "end_time"   => "2017-06-26 04:00:00"
        ], [
            "start_time" => "2017-06-26 04:30:00",
            "end_time"   => "2017-06-26 05:00:00"
        ],
        [
            "start_time" => "2017-06-26 05:00:00",
            "end_time"   => "2017-06-26 07:00:00"
        ],
        [
            "start_time" => "2017-06-26 09:00:00",
            "end_time"   => "2017-06-26 10:00:00"
        ],
        [
            "start_time" => "2017-06-26 10:00:00",
            "end_time"   => "2017-06-26 15:00:00"
        ],
        [
            "start_time" => "2017-06-26 16:00:00",
            "end_time"   => "2017-06-26 20:00:00"
        ]
    ]

Anyone knows the correct algo/pseudo to deal with that? 任何人都知道正确的算法/伪来处理吗?

Create common list of pairs {time; flag} 建立共用的配对清单{time; flag} {time; flag} , where flag is time_start, time_end, restriction_start or restriction_end . {time; flag} ,其中标记是time_start, time_end, restriction_start or restriction_end

Sort this list by time. 按时间对该列表进行排序。 In case of tie use flag as secondary key (for example, restr_start should go after time_end ). 如果是平局, restr_start标志用作辅助键(例如, restr_start应该在time_end之后)。

Make $Active=0 , $Exclude=0 使$Active=0$Exclude=0

Walk through sorted list. 遍历排序列表。

When you meet time_start , increment value of $Active {1} 当您遇到time_start$Active {1}的增量值

When you meet time_end , decrement value of $Active {2} 当您遇到time_end ,递减值$Active {2}

When you meet restriction_start , increment value of $Exclude {3} 当您遇到restriction_start$Exclude {3}的增量值

When you meet restriction_end , decrement value of $Exclude {4} 当您达到restriction_end ,递减值$Exclude {4}

Open output interval in the next cases: 在以下情况下打开输出间隔:
{1}: $Active becomes 1 and $Exclude = 0 {1}: $Active变为1, $Exclude = 0
{4}: $Exclude becomes 0 and $Active is non-zero {4}: $Exclude becomes 0$Active不为零

Close output interval in the next cases: 在以下情况下关闭输出间隔:
{2} $Active becomes 0 and $Exclude = 0 {2} $Active变为0, $Exclude = 0
{3} $Exclude becomes 1 and $Active is non-zero {3} $Exclude becomes 1$Active则为非零

example: (don't know exact php syntax for complex conditions) 示例:(不知道复杂条件的确切php语法)

 case $TimeStart:
            $active = $active + 1;
            if ($active=1) and ($exclude=0)
                 $range['start_time'] = $mergedTime['time'];
            break;
 ....
  case $RestrictionEnd:
            $exclude = $exclude - 1;
            if ($exclude=0) and ($active > 0)
                 $range['start_time'] = $mergedTime['time'];
            break;
function excludeOverlaping($disponibilities,$plages) {

        if(count($disponibilities) == 0)
            return $disponibilities;
        if(count($plages) == 0)
            return $disponibilities;

                usort($disponibilities, function($a, $b)
                {
                    return strtotime($a->startDate) - strtotime($b->startDate);
                });
                usort($plages, function($a, $b)
                {
                    return strtotime($a->startDate) - strtotime($b->startDate);
                });

                for($i = 0; $i < count($disponibilities); $i++){
                    for($j=0;$j<count($plages);$j++){
                        $dispo = $disponibilities[$i];
                        if(isset($dispo->exclude)){
                            break;
                        }
                        $plage = $plages[$j]; 
                        if(strtotime($dispo->startDate)>=strtotime($plage->startDate) && strtotime($dispo->endDate)<=strtotime($plage->endDate)){
                                $disponibilities[$i]->exclude = true;

                        }else if( strtotime($dispo->startDate)<strtotime($plage->startDate) && strtotime($dispo->endDate) <= strtotime($plage->endDate) && strtotime($dispo->endDate) > strtotime($plage->startDate)){
                                 $disponibilities[$i]->endDate = $plage->startDate;
                        }else if( strtotime($dispo->startDate)>=strtotime($plage->startDate)  && strtotime($dispo->startDate)<=strtotime($plage->endDate) && strtotime($dispo->endDate) > strtotime($plage->endDate)){
                                 $disponibilities[$i]->startDate = $plage->endDate;
                        }else if( strtotime($dispo->startDate)<strtotime($plage->startDate) &&  strtotime($dispo->endDate) > strtotime($plage->endDate) ){
                              echo "[[[4]]]\n";
                                $tmp = new stdClass();
                                $tmp->startDate = $dispo->startDate;
                                $tmp->endDate = $plage->startDate;
                                $tmp2 = new stdClass();
                                $tmp2->startDate = $plage->endDate;
                                $tmp2->endDate = $dispo->endDate;
                                $disponibilities[$i]->exclude = true;
                                array_push($disponibilities,$tmp);
                                array_push($disponibilities,$tmp2);

                        } 
                    }
                }
                for($i=0;$i<count($disponibilities);$i++){
                    if(isset($disponibilities[$i]->exclude)){
                       array_splice($disponibilities,$i,1);
                       $i--;
                    }
                }
                var_dump($disponibilities);

    }

    $times = array();
    $restrictions = array();
    $obj = new stdClass();
    $obj->startDate = '2017-06-26 00:00:00';
    $obj->endDate =  '2017-06-26 07:00:00';
    array_push($times,$obj);
    $obj = new stdClass();
    $obj->startDate = '2017-06-26 00:00:00';
    $obj->endDate = '2017-06-26 24:00:00';
    array_push($times,$obj);


    $obj = new stdClass();
    $obj->startDate =  '2017-06-26 04:00:00';
    $obj->endDate = '2017-06-26 06:00:00';
    array_push($restrictions,$obj);


    $obj = new stdClass();
    $obj->startDate = '2017-06-26 00:00:00' ;
    $obj->endDate = '2017-06-26 01:00:00';
    array_push($restrictions,$obj);


    excludeOverlaping($times,$restrictions);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM