Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

jericopulvera's avatar

How do I combine overlapping date range the easy way?

Data to combine

array:6 [▼
  0 => array:3 [▼
    "StartDate" => "2017-07-18"
    "EndDate" => "2017-07-29"
  ]
  1 => array:3 [▼
    "StartDate" => "2017-08-02"
    "EndDate" => "2017-08-08"
  ]
  2 => array:3 [▼
    "StartDate" => "2017-08-12"
    "EndDate" => "2017-08-26"  // Overlaps with the next StartDate
  ]
  3 => array:3 [▼
    "StartDate" => "2017-08-26" // Overlaps with the last EndDate
    "EndDate" => "2017-09-02"
  ]
  4 => array:3 [▼
    "StartDate" => "2017-12-10"
    "EndDate" => "2018-01-10"
  ]
  5 => array:3 [▼
    "StartDate" => "2018-12-10"
    "EndDate" => "2019-01-05"
  ]
]

Output should be

array:6 [▼
  0 => array:3 [▼
    "StartDate" => "2017-07-18"
    "EndDate" => "2017-07-29"
  ]
  1 => array:3 [▼
    "StartDate" => "2017-08-02"
    "EndDate" => "2017-08-08"
  ]
  2 => array:3 [▼
    "StartDate" => "2017-08-12"
   "EndDate" => "2017-09-02"
  ]
  3 => array:3 [▼
    "StartDate" => "2017-12-10"
    "EndDate" => "2018-01-10"
  ]
  4 => array:3 [▼
    "StartDate" => "2018-12-10"
    "EndDate" => "2019-01-05"
  ]
]
0 likes
1 reply
jericopulvera's avatar
jericopulvera
OP
Best Answer
Level 7

Found the answer

function mergeDateRanges($ranges)
{
    $retVal = [];
    //sort date ranges by begin time
    usort($ranges, function ($a, $b) {
        return strcmp($a['StartDate'], $b['StartDate']);
    });

    $currentRange = [];
    foreach ($ranges as $range) {
        // bypass invalid value
        if ($range['StartDate'] >= $range['EndDate']) {
            continue;
        }
        //fill in the first element
        if (empty($currentRange)) {
            $currentRange = $range;
            continue;
        }

        if ($currentRange['EndDate'] < $range['StartDate']) {
            $retVal[] = $currentRange;
            $currentRange = $range;
        } elseif ($currentRange['EndDate'] < $range['EndDate']) {
            $currentRange ['EndDate'] = $range['EndDate'];
        }
    }

    if ($currentRange) {
        $retVal[] = $currentRange;
    }

    return $retVal;
}

Please or to participate in this conversation.