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 namespace App\Models\Concerns;
Building soft deletes as an Eloquent trait in Laravel
traits
soft-delete
global-scope
Intermediate
10 steps
php
<?php namespace App\Services;
Idempotent role assignment in Laravel
many-to-many
pivot-data
idempotency
Intermediate
8 steps
php
<?php namespace App\Listeners;
How event subscribers group listeners in Laravel
event-driven
subscribers
queues
Intermediate
6 steps
php
<?php namespace App\Services;
How user impersonation works in Laravel
authentication
authorization
session
Intermediate
8 steps
rust
use std::time::Duration; #[derive(Debug, Clone, Copy)] pub struct LatencyStats {
Computing latency percentiles in Rust
percentiles
interpolation
closures
Intermediate
6 steps
php
class OrderReceiptController extends Controller { public function store(Request $request, Order $order) {
Handling receipt uploads in a Laravel controller
file-upload
validation
authorization
Intermediate
5 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.