Date Arithmetic

DateInterval, DatePeriod and Date Arithmetic

A DateInterval is a duration in calendar units, built from an ISO 8601 string: P, then Y, M, W or D, then T and H, M, S, so P1Y2M10DT2H is a year, two months, ten days and two hours. createFromDateString() accepts English. add() and sub() apply one, diff() returns one (%a is total days), and a DatePeriod iterates from a start by an interval.

Adding intervals, measuring a difference and iterating periods (interval.php)PHP
<?php
date_default_timezone_set('UTC');
$order = new DateTimeImmutable('2026-01-15 09:30');
$diff = $order->diff(new DateTimeImmutable('2026-09-23 17:45'));
echo $order->add(new DateInterval('P1Y2M10DT2H'))->format('Y-m-d H:i'), ' | ',    // ISO 8601
    $order->sub(DateInterval::createFromDateString('90 minutes'))->format('H:i'), ' | ',
    $diff->format('%y y %m m %d d %h h %i min = %a days'), "\n";
$p = new DatePeriod(new DateTimeImmutable('2026-10-06'), new DateInterval('P2W'),
    new DateTimeImmutable('2026-10-31'));                          // every other Tuesday
$sept = new DatePeriod(new DateTimeImmutable('2026-09-01'), new DateInterval('P1D'),
    new DateTimeImmutable('2026-09-30'), DatePeriod::INCLUDE_END_DATE);
$monthly = DatePeriod::createFromISO8601String('R2/2026-12-31T00:00:00Z/P1M');
$fmt = fn(DatePeriod $period) => implode(', ',
    array_map(fn($d) => $d->format('D j M'), iterator_to_array($period)));
$workdays = count(array_filter(iterator_to_array($sept), fn($d) => $d->format('N') < 6));
echo $fmt($p), " | $workdays | ", $fmt($monthly), "\n";
Output
2027-03-25 11:30 | 08:00 | 0 y 8 m 8 d 8 h 15 min = 251 days
Tue 6 Oct, Tue 20 Oct | 22 | Thu 31 Dec, Sun 31 Jan, Wed 3 Mar

The end date is excluded unless you pass INCLUDE_END_DATE (PHP 8.2), which lets the September count reach the 30th: 22 working days. createFromISO8601String() (8.3) replaces the deprecated ISO-string constructor; R2 means the start plus two recurrences. It shows month arithmetic's trap once more: 31 December plus two months is "31 February", so 3 March. Age is $birth->diff($today)->y.