DateTime змінюється на місці: modify(), add(), setTime() змінюють сам об'єкт і повертають його ж.
DateTimeImmutable ніколи не змінюється: ті самі методи повертають новий об'єкт, а оригінал лишається без змін.
Класичний баг з DateTime:
$start = new DateTime('2026-10-01');
$end = $start->modify('+7 days');
echo $start->format('Y-m-d'); // 2026-10-08 - початок теж зсунувся!
$start і $end - той самий об'єкт. Особливо підступно, коли дату передали у функцію чи вона - властивість моделі: виклик modify() усередині методу непомітно змінює стан десь в іншому місці.
З DateTimeImmutable:
$start = new DateTimeImmutable('2026-10-01');
$end = $start->modify('+7 days'); // $start лишився 2026-10-01
Що ще варто знати про дати в PHP:
- Часовий пояс - явно:
new DateTimeImmutable('now', new DateTimeZone('Europe/Kyiv')). Без нього беретьсяdate.timezone, яке на різних серверах різне. - Зберігати в UTC, показувати в поясі користувача -
->setTimezone(...)при виведенні. modify('+1 month')31 січня дає 3 березня (переповнення дня). Для «наступного місяця» -modify('last day of next month')чиfirst day of next month.- Порівняння - звичайними операторами:
$a < $bпрацює для дат. - Для інтервалів -
diff()повертаєDateInterval, для ітерації -DatePeriod.
У Laravel Carbon (на основі DateTime) змінюваний, а CarbonImmutable - ні. Laravel дозволяє зробити immutable за замовчуванням: Date::use(CarbonImmutable::class) у сервіс-провайдері - тоді now() і дати моделей стають незмінними.