I have two arbitrary date ranges, for example:
2019-01-01 - 2019-01-10 and 2019-01-06 - 2019-01-20
How do I find out in PHP, by how many days these date ranges overlap? (In the example above it’s 5 days)
Advertisement
Answer
Here’s a solution using DateTime
and DateInterval
objects:
$range1 = '2019-01-01 - 2019-01-10'; $range2 = '2019-01-06 - 2019-01-20'; list($start, $end) = explode(' - ', $range1); $start1 = new DateTime($start); $end1 = new DateTime($end); list($start, $end) = explode(' - ', $range2); $start2 = new DateTime($start); $end2 = new DateTime($end); if ($end1 > $start1) { $overlap = $end1->diff(min($start2, $end2)); } else { $overlap = $start1->diff(min($start2, $end2)); } echo "overlap is " . ($overlap->format('%a') + 1) . " days";
Output
overlap is 5 days
Update
Here is a more robust version of the code that allows for arbitrary overlapping of the ranges (including one being contained entirely in the other):
function range_overlap($range1, $range2) { list($start, $end) = explode(' - ', $range1); $start = new DateTime($start); $end = new DateTime($end); $start1 = min($start, $end); $end1 = max($start, $end); list($start, $end) = explode(' - ', $range2); $start = new DateTime($start); $end = new DateTime($end); $start2 = min($start, $end); $end2 = max($start, $end); // check for special cases if ($start1 >= $start2 && $end1 <= $end2) { // range1 completely contained inside range2 $overlap = $start1->diff($end1); } elseif ($start2 >= $start1 && $end2 <= $end1) { // range2 completely contained inside range1 $overlap = $start2->diff($end2); } elseif ($end2 > $end1) { // range1 ends first $overlap = $start2->diff($end1); } else { // range2 ends first $overlap = $start1->diff($end2); } // if overlap is < 0 then there is no overlap $overlap_days = $overlap->invert ? 0 : ($overlap->format('%a') + 1); echo "overlap is $overlap_days daysn"; }
It can be called like this:
range_overlap('2019-01-01 - 2019-01-10', '2019-01-06 - 2019-01-20'); // 5 days range_overlap('2019-01-01 - 2019-03-20', '2019-05-06 - 2019-04-20'); // no overlap range_overlap('2019-01-10 - 2019-05-20', '2019-01-01 - 2019-05-20'); // 131 days range_overlap('2019-01-06 - 2019-01-20', '2019-01-10 - 2019-01-01'); // 5 days range_overlap('2019-01-30 - 2019-01-10', '2019-01-12 - 2019-01-15'); // 4 days range_overlap('2019-02-01 - 2019-03-20', '2019-01-10 - 2019-02-28'); // 28 days