PHP 8: Modern PHP Development · Errors, Exceptions and Robust Code

Dates, Time Zones and Immutability

Work safely with DateTimeImmutable, time zones and intervals.

Use DateTimeImmutable (not DateTime) so operations return new objects instead of mutating shared instances. Store timestamps in UTC, convert to the user's time zone only for display, and set date.timezone explicitly. Use DateInterval/DatePeriod for ranges, and an injectable clock (PSR-20 ClockInterface) to make time-dependent code testable.

<?php
$utc = new DateTimeZone('UTC');
$createdAt = new DateTimeImmutable('now', $utc);
$expiresAt = $createdAt->modify('+30 minutes');       // new object

$local = $createdAt->setTimezone(new DateTimeZone('Europe/Berlin'));
echo $local->format('Y-m-d H:i T');

final class TokenService
{
    public function __construct(private Psr\Clock\ClockInterface $clock) {}

    public function isExpired(DateTimeImmutable $expiresAt): bool
    {
        return $expiresAt <= $this->clock->now();
    }
}

Common pitfalls

  • Mutating a shared DateTime passed into a function.
  • Storing local times without a time zone.
  • Adding '+1 month' to Jan 31 and expecting Feb 28 (it overflows into March).

Key points

  • Prefer DateTimeImmutable
  • Store UTC, display local
  • Inject a clock for testability

Further reading: PHP manual: DateTimeImmutable

Practice questions

Why prefer DateTimeImmutable over DateTime?

Answer

DateTime::modify() changes the object in place, so a date shared between functions can change unexpectedly. Immutable dates return new objects, avoiding such bugs.

How do you test code that depends on the current time?

Answer

Inject a clock (PSR-20 ClockInterface) and use a fixed/mock clock in tests instead of calling new DateTimeImmutable() directly.

Open in the app to mark lessons complete, take notes and track your progress.