I have an array that have start_date, end_date and price Eg.
/* date formate 'yyyy-mm-dd' */
$existingRanges = [
['start_date' => '2023-11-22', 'end_date' => '2023-11-30', 'price' => 200],
['start_date' => '2023-12-10', 'end_date' => '2023-12-14', 'price' => 100],
['start_date' => '2023-12-15', 'end_date' => '2023-12-20', 'price' => 100],
['start_date' => '2023-12-21', 'end_date' => '2023-12-27', 'price' => 100],
['start_date' => '2024-01-05', 'end_date' => '2024-01-05', 'price' => 600],
['start_date' => '2024-01-06', 'end_date' => '2024-01-07', 'price' => 700],
['start_date' => '2024-01-08', 'end_date' => '2024-01-20', 'price' => 700],
['start_date' => '2024-01-21', 'end_date' => '2024-01-31', 'price' => 100],
];
I want here to merge all the dates which are next to each other but have the same prices ie 2024-01-06 to 2024-01-07 and 2024-01-08 to 2024-01-20 these two date ranges are next to each other and their prices are the same so it should be 2024-01-06 to 2024-01-20 and price 700.
Array example of my results.
$results = [
['start_date' => '2023-11-22', 'end_date' => '2023-11-30', 'price' => 200],
['start_date' => '2023-12-10', 'end_date' => '2023-12-27', 'price' => 100],
['start_date' => '2024-01-05', 'end_date' => '2024-01-05', 'price' => 600],
['start_date' => '2024-01-06', 'end_date' => '2024-01-20', 'price' => 700],
['start_date' => '2024-01-21', 'end_date' => '2024-01-31', 'price' => 100],
];
The code/logic I tried with
function mergeDateRanges($p_arrDateranges) {
// sort by start date
/* usort($p_arrDateranges, function($a1, $a2) {
return $a1['start_date'] === $a2['start_date'] ? 0 : ($a1['start_date'] < $a2['start_date'] ? -1 : 1);
}); */
$finalArray = [];
$arrMerged = array();
$arrLastDR = null;
foreach ($p_arrDateranges as $arrDR) {
if ($arrLastDR === null) {
$arrLastDR = $arrDR;
continue;
}
if(!$arrMerged) {
array_push($arrMerged, $arrLastDR);
}
$endDate = DateTime::createFromFormat('Y-m-d', $arrLastDR['end_date']);
$sLastDateE_1 = $endDate->modify('+1 day')->format('Y-m-d');
if (strtotime($arrDR['start_date']) < strtotime($sLastDateE_1) && $arrDR['price'] == $arrLastDR['price']) {
array_push($finalArray, [
'start_date' => $arrDR['start_date'],
'end_date' => $arrLastDR['end_date'],
'price' => 0
]);
} else {
array_push($finalArray, $arrDR);
}
$arrLastDR = $arrDR;
array_push($arrMerged, $arrLastDR);
//print_r($arrLastDR);
}
return $finalArray;
}
mergeDateRanges($existingRanges);
This is returning different results So please help me to solve this issue.
2
Answers
If the time comparison of the previous end date equals current start date, along with the price check, then only update the end date of
$arrLastDR
to the current one’s end date(we can call this merging).If they don’t match, this merge segment was only valid till this index. So, add that to
$finalArray
and start a new$arrLastDR
with the current one.So change the below
to
Live Demo
Note: No need of any explicit sorting since you already confirmed that the input is in a sorted manner.
Here is an alternate solution:
Yields: