Legacy Date Functions
Also Known As
date()
strtotime()
mktime()
legacy date
TL;DR
Using date(), mktime(), strtotime(), and date_create() instead of DateTimeImmutable — the legacy functions are mutable, timezone-unsafe, and cannot be easily mocked.
Explanation
PHP's procedural date functions (date(), mktime(), strtotime()) operate on Unix timestamps and use the default timezone set by date_default_timezone_set(). They are mutable, cannot be mocked in tests, and lead to timezone bugs. DateTimeImmutable (PHP 5.5+) provides an immutable, object-oriented API: timezone-aware, chainable, testable (Carbon extends it), and compatible with DateTimeInterface. date() and strtotime() are acceptable for quick scripts but not for application date logic.
Common Misconception
✗ strtotime() reliably parses any date string — strtotime() is locale-dependent, ambiguous with formats like '01/02/03' (day/month/year or month/day/year?), and silently returns false for unparseable strings.
Why It Matters
Tests that depend on date() return the real current time — untestable. Code using the default timezone breaks when the server timezone is changed. DateTimeImmutable fixes both.
Common Mistakes
- date('Y-m-d') in tests — untestable; use DateTimeImmutable and mock the clock.
- strtotime('+1 month') — silently fails on some date strings; use modify('+1 month').
- Not checking strtotime() for false — invalid input silently becomes timestamp 0 (1970).
- DateTime (mutable) instead of DateTimeImmutable — shared DateTime references can be modified unexpectedly.
Code Examples
✗ Vulnerable
// Procedural, untestable, timezone-fragile:
$expiry = date('Y-m-d', strtotime('+30 days'));
$timestamp = mktime(0, 0, 0, 12, 25, 2026);
$age = (time() - strtotime($user->birthdate)) / (365.25 * 86400);
// Mutable DateTime — shared reference bug:
$start = new DateTime('2026-01-01');
$end = $start->modify('+1 month'); // $start also modified!
✓ Fixed
// DateTimeImmutable — immutable, testable, timezone-aware:
$expiry = (new DateTimeImmutable())->modify('+30 days')->format('Y-m-d');
$xmas = new DateTimeImmutable('2026-12-25', new DateTimeZone('UTC'));
$birth = new DateTimeImmutable($user->birthdate);
$age = (new DateTimeImmutable())->diff($birth)->y;
// Immutable — original unchanged:
$start = new DateTimeImmutable('2026-01-01');
$end = $start->modify('+1 month'); // $start unchanged
Tags
🤝 Adopt this term
£79/year · your link shown here
Added
16 Mar 2026
Edited
22 Mar 2026
Views
23
🤖 AI Guestbook educational data only
|
|
Last 30 days
Agents 0
No pings yet today
Amazonbot 7
Perplexity 5
Unknown AI 3
Google 2
Ahrefs 2
ChatGPT 2
Majestic 1
How they use it
crawler 19
crawler_json 2
pre-tracking 1
⚡
DEV INTEL
Tools & Severity
🟡 Medium
⚙ Fix effort: Low
⚡ Quick Fix
Replace date() and mktime() with DateTimeImmutable — date() uses the server timezone silently; DateTimeImmutable forces you to be explicit about timezone from construction
📦 Applies To
PHP 5.0+
web
cli
🔗 Prerequisites
🔍 Detection Hints
date() mktime() strtotime() without explicit timezone; mixing timestamps and formatted strings; date_create() instead of DateTimeImmutable
Auto-detectable:
✓ Yes
phpstan
rector
php-cs-fixer
⚠ Related Problems
🤖 AI Agent
Confidence: High
False Positives: Low
✓ Auto-fixable
Fix: Low
Context: Line
Tests: Update