DateTimeImmutable
Коли час змінюється, а обʼєкти ні
- Додано у версії: PHP 5.5
- Що дає: клас, який поводиться як
DateTime, але не змінюється при модифікації, а повертає клонований обʼєкт.
В чому суть
У PHP якщо ми зробимо зміни часу у обʼєкта DateTime, він змінився всюди, де передавався, бо обʼєкти в PHP завжди передаються по посиланню, і така поведінка може призвести до неочікуваної поведінки.
DateTimeImmutable вирішує цю проблему — будь-яка дія над датою повертає новий екземпляр, а не мутує старий.
Коли це справді має сенс
- у DTO / Value Object — щоб час гарантовано не змінювався після передачі;
- у планувальниках, розкладах, звітах — коли ти рахуєш багато дат від базової;
- у бізнес-логіці — коли з однієї дати обчислюється інша (початок/кінець періоду, дедлайн, акція, тощо).
Проблема, яку можна не помітити
У продакшн-коді DateTime часто передають між сервісами, DTO або кешують у контейнерах.
І тут трапляється типова історія:
class Campaign {
public function __construct(
public string $name,
public DateTime $startsAt,
public DateTime $endsAt,
) {}
}
$base = new DateTime('2025-10-01');
$campaign = new Campaign(
name: 'Autumn Sale',
startsAt: $base,
endsAt: $base->modify('+7 days')
);
echo $campaign->startsAt->format('Y-m-d'); // 2025-10-08 ❌
echo $campaign->endsAt->format('Y-m-d'); // 2025-10-08
Ми очікували, що початок буде 1 жовтня, але $base мутував під час modify, як наслідок — початок і кінець однакові.
Той самий код, але з DateTimeImmutable працює коректно:
$base = new DateTimeImmutable('2025-10-01');
$campaign = new Campaign(
name: 'Autumn Sale',
startsAt: $base,
endsAt: $base->modify('+7 days')
);
echo $campaign->startsAt->format('Y-m-d'); // 2025-10-01 ✅
echo $campaign->endsAt->format('Y-m-d'); // 2025-10-08
Додатковий приклад
class Period {
public function __construct(
public DateTimeImmutable $from,
public DateTimeImmutable $to
) {}
public function days(): int {
return $this->to->diff($this->from)->days;
}
}
$period = new Period(
from: $from = new DateTimeImmutable('2025-06-01'),
to: $from->modify('+10 days'),
);
echo $period->days(); // 10
Жодних несподіваних мутацій — об’єкт можна безпечно кешувати чи передавати далі.
Висновок
DateTimeImmutable — це безпечний вибір для роботи з логікою часу. Він виключає випадкові зміни дат, коли одна змінна призводить до неочікуваних результатів.
Якщо твоя дата здатна змінитись — вона рано чи пізно зламає щось у звіті, логіці або фінансах. Immutable цього не дозволить.
← Попередня: Генератори · Уся серія · Наступна: Іменовані аргументи →
Вперше опубліковано в Telegram-каналі «Створений щоб помирати» 21.10.2025.