Date / Time Functions
debt(d5/e3/b5/t7)
Closest to 'specialist tool catches' (d5). PHPStan and Rector (listed in detection_hints.tools) can catch DateTime vs DateTimeImmutable usage and flag mutable date objects, but timezone misconfigurations and strtotime() ambiguity often slip through static analysis and only surface at runtime or in code review.
Closest to 'simple parameterised fix' (e3). The quick_fix indicates replacing DateTime with DateTimeImmutable and using Carbon — this is a pattern replacement that may touch multiple files but follows a consistent, mechanical substitution. Fixing strtotime() calls to use createFromFormat() is similarly straightforward but requires identifying all call sites.
Closest to 'persistent productivity tax' (b5). Date handling applies across all PHP contexts (web, cli, queue-worker per applies_to) and the choice between mutable/immutable DateTime propagates throughout the codebase. Every developer touching date logic must understand which API is in use, and mixing them creates ongoing confusion, though it doesn't fully define the system's architecture.
Closest to 'serious trap' (t7). The misconception explicitly states developers assume strtotime() reliably parses any date string when it's actually locale-sensitive and ambiguous. This contradicts how similar parsing functions work in other languages (explicit format required). The DateTime mutability trap also catches developers who expect immutability from an object-oriented date class, as is standard in many modern languages.
Also Known As
TL;DR
Explanation
PHP's procedural date() and time() functions are timezone-sensitive and easy to misuse. The object-oriented DateTimeImmutable class is preferred: it creates a new instance on modification rather than mutating in place, preventing shared-state bugs. Always construct DateTime objects with an explicit DateTimeZone to avoid relying on the system default. DateInterval handles durations, DateTimeInterface is the type hint for both DateTime and DateTimeImmutable, and use Carbon for a richer developer-friendly API in complex applications.
Common Misconception
Why It Matters
Common Mistakes
- Using date() and time() without setting or checking the default timezone — output differs per server.
- Using DateTime instead of DateTimeImmutable — methods like modify() mutate the object, causing bugs when a reference is shared.
- Comparing DateTime objects with == — use < > operators or diff(); == compares value but does not account for timezone.
- Storing dates as formatted strings in the database instead of DATE/DATETIME columns — loses sort and range query ability.
Code Examples
// Mutable DateTime causes bug when shared:
$start = new DateTime('2026-01-01');
$end = $start->modify('+30 days'); // $start is ALSO modified — use DateTimeImmutable
echo $start->format('Y-m-d'); // 2026-01-31 — not what you expect
// Always use DateTimeImmutable — mutable DateTime causes subtle bugs
$now = new \DateTimeImmutable('now', new \DateTimeZone('UTC'));
$plus7 = $now->modify('+7 days'); // returns new object
$start = new \DateTimeImmutable('2024-01-01');
$diff = $now->diff($start)->days; // DateInterval
// Format
echo $now->format('Y-m-d H:i:s'); // 2024-03-01 14:30:00
// From timestamp
$dt = (new \DateTimeImmutable())->setTimestamp($timestamp);
// Date arithmetic with DateInterval
$oneMonth = new \DateInterval('P1M');
$nextMonth = $now->add($oneMonth);
// Carbon (popular library — wraps DateTimeImmutable)
$dt = \Carbon\Carbon::now()->addDays(7)->startOfDay();