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