php
51 lines · 8 steps
Merging overlapping busy time blocks in PHP
A service that normalizes calendar events and collapses overlapping intervals into clean busy blocks.
Explained by
highlit
1<?php
2
3namespace App\Services;
4
5use DateTimeImmutable;
6
7final class BusyBlockMerger
8{
9 public function merge(array $events): array
10 {
11 $ranges = [];
12
13 foreach ($events as $event) {
14 $start = $event['start'] instanceof DateTimeImmutable
15 ? $event['start']
16 : new DateTimeImmutable($event['start']);
17 $end = $event['end'] instanceof DateTimeImmutable
18 ? $event['end']
19 : new DateTimeImmutable($event['end']);
20
21 if ($end <= $start) {
22 continue;
23 }
24
25 $ranges[] = [$start, $end];
26 }
27
28 usort($ranges, fn (array $a, array $b) => $a[0] <=> $b[0]);
29
30 $merged = [];
31
32 foreach ($ranges as [$start, $end]) {
33 $last = array_key_last($merged);
34
35 if ($last !== null && $start <= $merged[$last]['end']) {
36 if ($end > $merged[$last]['end']) {
37 $merged[$last]['end'] = $end;
38 }
39 continue;
40 }
41
42 $merged[] = ['start' => $start, 'end' => $end];
43 }
44
45 return array_map(static fn (array $block) => [
46 'start' => $block['start']->format(DATE_ATOM),
47 'end' => $block['end']->format(DATE_ATOM),
48 'duration_minutes' => (int) (($block['end']->getTimestamp() - $block['start']->getTimestamp()) / 60),
49 ], $merged);
50 }
51}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Sorting intervals by start time turns overlap detection into a single linear pass.
- 2Normalizing inputs to a common type early lets the rest of the logic stay simple.
- 3Extending the last kept range in place is the whole trick to merging overlaps.
Related explainers
php
<?php class NameParser {
Parsing a full name into components in PHP
string-parsing
arrays
normalization
Intermediate
8 steps
php
<?php namespace App\Services\Checkout;
Validating coupons with Laravel's Pipeline
pipeline
chain of responsibility
transactions
Intermediate
7 steps
php
<?php namespace App\Services;
How a password strength validator works in PHP
validation
regular-expressions
data-driven
Intermediate
8 steps
php
<?php namespace App\Services;
Building a cached daily leaderboard in Laravel
caching
aggregation
eager-loading
Intermediate
9 steps
php
<?php final class RotatingFileLogger {
How a rotating file logger works in PHP
logging
file-rotation
io
Intermediate
9 steps
python
import re from functools import total_ordering from typing import Optional
Parsing and comparing semantic versions
regex
operator-overloading
sorting
Intermediate
7 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/merging-overlapping-busy-time-blocks-in-php-explained-php-2e9a/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.