php 51 lines · 7 steps

Counting business days in PHP

A small class that counts weekdays between two dates while skipping weekends and holidays.

Explained by highlit
1<?php
2 
3declare(strict_types=1);
4 
5namespace App\Support;
6 
7use DateInterval;
8use DatePeriod;
9use DateTimeImmutable;
10use DateTimeInterface;
11 
12final class BusinessDayCalculator
13{
14 private array $holidays;
15 
16 public function __construct(array $holidays = [])
17 {
18 $this->holidays = array_flip(array_map(
19 static fn (string $date): string => (new DateTimeImmutable($date))->format('Y-m-d'),
20 $holidays
21 ));
22 }
23 
24 public function between(DateTimeInterface $start, DateTimeInterface $end): int
25 {
26 $from = DateTimeImmutable::createFromInterface($start)->setTime(0, 0);
27 $to = DateTimeImmutable::createFromInterface($end)->setTime(0, 0);
28 
29 if ($to < $from) {
30 [$from, $to] = [$to, $from];
31 }
32 
33 $period = new DatePeriod($from, new DateInterval('P1D'), $to->modify('+1 day'));
34 
35 $count = 0;
36 foreach ($period as $day) {
37 if ($this->isBusinessDay($day)) {
38 $count++;
39 }
40 }
41 
42 return $count;
43 }
44 
45 private function isBusinessDay(DateTimeInterface $day): bool
46 {
47 $weekday = (int) $day->format('N');
48 
49 return $weekday < 6 && !isset($this->holidays[$day->format('Y-m-d')]);
50 }
51}
01 / 01
STEP 01

Walkthrough

Space play ←→ step click any line
Three takeaways
  1. 1Flipping an array into keys turns repeated membership checks into O(1) lookups.
  2. 2Normalizing dates to midnight avoids time-of-day bugs when comparing or iterating days.
  3. 3DatePeriod lets you iterate a date range declaratively instead of manual date arithmetic.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Counting business days in PHP — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code