PHP combine two seperate conflicting date ranges into unique pairs

后端 未结 3 435
陌清茗
陌清茗 2021-01-20 16:05

Set one:

  1. 2014-04-05 To 2014-06-27
  2. 2014-06-28 To 2014-10-19

Set two:

  1. 2014-04-05 To 2014-05-02
  2. 2014-05-03 To 2014
3条回答
  •  天命终不由人
    2021-01-20 16:53

    Preparing

    $arr1 = array(
      array('start'=>'2014-04-05', 'end'=> '2014-06-27'),
      array('start'=>'2014-06-28', 'end'=> '2014-10-19'),
    );
    
    $arr2 = array(
      array('start'=>'2014-04-05', 'end'=> '2014-05-02'),
      array('start'=>'2014-05-03', 'end'=> '2014-05-31'),
      array('start'=>'2014-06-01', 'end'=> '2014-10-21')
    );
    
    // merge arrays
    $all = array_merge($arr1,$arr2);
    
    // divide start-dates and end-dates into two arrays
    $starts = array();
    $ends = array();
    foreach($all as $date){
        $starts[] = $date['start'];
        $ends[] = $date['end'];
    }
    
    // Remove duplicates and "sort ASC"
    $starts = array_unique($starts);
    natsort($starts);
    
    $ends = array_unique($ends);
    natsort($ends);
    
    echo '
    ';
    var_dump($starts,$ends);
    echo '
    ';

    output

    array(4) {
        [0]=>
      string(10) "2014-04-05"
        [3]=>
      string(10) "2014-05-03"
        [4]=>
      string(10) "2014-06-01"
        [1]=>
      string(10) "2014-06-28"
    }
    array(5) {
        [2]=>
      string(10) "2014-05-02"
        [3]=>
      string(10) "2014-05-31"
        [0]=>
      string(10) "2014-06-27"
        [1]=>
      string(10) "2014-10-19"
        [4]=>
      string(10) "2014-10-21"
    }
    

    Ok. Now we need loop array $starts: for each start find closest end that more then start. Do it:

    $ranges = array();
    
    foreach($starts as $start){
        $start_time = strtotime($start);
    
        foreach($ends as $end){
            $end_time = strtotime($end);
            if ($start_time>$end_time) continue;
            else{
                $ranges[$end] = $start;
                break;
            }
        }
    }
    
    // "combine" 
    $result = array();    
    foreach($ranges as $end=>$start) {
        $result[] = array('start' => $start, 'end' => $end);
    }
    
    // print final result
    foreach($result as $item){
        echo $item['start'].'  To  '.$item['end'].'
    '; }

    output:

    2014-04-05 To 2014-05-02
    2014-05-03 To 2014-05-31
    2014-06-01 To 2014-06-27
    2014-06-28 To 2014-10-19
    

    What you need.

    Note About this line in loops:

     $ranges[$end] = $start;
    

    We can have this situation:

    2014-04-03 To 2014-05-02
    2014-04-04 To 2014-05-02
    2014-04-05 To 2014-05-02
    

    But it's wrong. Need only last range 2014-04-05 To 2014-05-02. And line:

     $ranges[$end] = $start;
    

    override value with same key=> finally will be set proper 2014-04-05 to key 2014-05-02.

提交回复
热议问题