DateTimeImmutable vs DateTime
Also Known As
DateTimeImmutable
DateTime immutable
PHP date immutable
DateTimeInterface
TL;DR
DateTimeImmutable returns a new object for every modification — the original is never changed. DateTime modifies in place. Prefer DateTimeImmutable in all new code to avoid subtle bugs where shared date objects are accidentally mutated.
Explanation
DateTime and DateTimeImmutable both implement DateTimeInterface and accept the same constructor arguments and format strings. The difference is mutation: DateTime::modify(), add(), sub(), and setDate() mutate the object and return $this. DateTimeImmutable::modify() returns a new object with the change applied — the original is unchanged. This matters when a date is passed to a function that calls modify() — with DateTime, the caller's date changes too; with DateTimeImmutable, it cannot. The DateTimeInterface type hint accepts both, so you can write functions that work with either while defaulting to the immutable variant.
Common Misconception
✗ DateTimeImmutable is slower because it creates new objects. The object creation overhead is negligible — a few microseconds per operation. The correctness benefit far outweighs the cost.
Why It Matters
Accidentally mutating a shared DateTime object is a classic PHP bug — a function that 'just reads' a date may call modify() internally, silently changing the caller's date. This is especially dangerous with dates passed through multiple layers of business logic. DateTimeImmutable makes it structurally impossible.
Common Mistakes
- Calling modify() on a DateTimeImmutable and ignoring the return value — the call does nothing visible because the original is unchanged and the new object is discarded.
- Type-hinting DateTime instead of DateTimeInterface — this rejects DateTimeImmutable instances; use DateTimeInterface to accept both.
- Using date_create() helper functions which return DateTime not DateTimeImmutable — use 'new DateTimeImmutable()' or DateTimeImmutable::createFromFormat().
- Storing mutable DateTime objects in value objects or entities — any code that holds the same reference can accidentally change the date.
Code Examples
✗ Vulnerable
<?php
// ❌ DateTime mutation bug — modify() changes the original
function addBusinessDays(DateTime $date, int $days): DateTime
{
for ($i = 0; $i < $days; $i++) {
$date->modify('+1 day'); // Mutates the caller's DateTime!
if ((int) $date->format('N') >= 6) {
$date->modify('+2 days');
}
}
return $date;
}
$orderDate = new DateTime('2026-01-10');
$dueDate = addBusinessDays($orderDate, 3);
// $orderDate is now '2026-01-15' — silently mutated!
✓ Fixed
<?php
// ✅ DateTimeImmutable — originals are never modified
function addBusinessDays(DateTimeImmutable $date, int $days): DateTimeImmutable
{
$current = $date;
for ($i = 0; $i < $days; $i++) {
$current = $current->modify('+1 day'); // Returns new object
if ((int) $current->format('N') >= 6) {
$current = $current->modify('+2 days');
}
}
return $current;
}
$orderDate = new DateTimeImmutable('2026-01-10');
$dueDate = addBusinessDays($orderDate, 3);
// $orderDate is still '2026-01-10' — unchanged
Tags
🤝 Adopt this term
£79/year · your link shown here
Added
23 Mar 2026
Views
18
🤖 AI Guestbook educational data only
|
|
Last 30 days
Agents 0
No pings yet today
No pings yesterday
Amazonbot 6
Perplexity 2
ChatGPT 1
Google 1
Ahrefs 1
Also referenced
How they use it
crawler 11
Related categories
⚡
DEV INTEL
Tools & Severity
⚙ Fix effort: Low
⚡ Quick Fix
Replace 'new DateTime()' with 'new DateTimeImmutable()' everywhere. Where you used '$date->modify('+1 day')' and expected mutation, capture the return value: '$nextDay = $date->modify('+1 day');'.
📦 Applies To
PHP 5.5+
web
cli