← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

PHP Date/Timezone Pitfalls

php PHP 5.1+ Intermediate

Also Known As

PHP timezone DateTime timezone Carbon date_default_timezone_set

TL;DR

Common PHP date and timezone bugs — relying on date_default_timezone_set(), comparing DateTime objects across timezones, and strtotime() ambiguity.

Explanation

PHP date pitfalls: date_default_timezone_set() is process-wide — changing it affects all date operations globally. DateTime is mutable (use DateTimeImmutable). strtotime() is locale-dependent and silently returns false for invalid strings. Comparing DateTime across timezones: two DateTime objects representing the same instant but different timezones compare as unequal by value. Carbon wraps DateTimeImmutable with testing support (Carbon::setTestNow()). Always: store UTC, display in user's timezone, use DateTimeImmutable, validate date strings explicitly.

Common Misconception

date_default_timezone_set() is safe to call in library code — calling it in a library changes the timezone for the entire application, breaking any code that relies on the previous timezone setting.

Why It Matters

A PHP application without explicit timezone handling shows different times to users in different regions, stores ambiguous timestamps that cannot be reliably converted, and breaks during DST transitions.

Common Mistakes

  • Calling date_default_timezone_set() in library code — it is a global setting; libraries must never change it.
  • DateTime instead of DateTimeImmutable — mutation surprises when DateTime is passed to functions.
  • Comparing DateTime objects with == — compares string representation not the same instant.
  • strtotime() without checking for false — invalid strings return false which converts to timestamp 0 (1970).

Code Examples

✗ Vulnerable
// Mutable DateTime — surprise mutation:
$start = new DateTime('2026-01-01');
$end   = $start->modify('+1 month'); // $start is also modified!
echo $start->format('Y-m-d'); // 2026-02-01 — not 2026-01-01!

// Timezone comparison bug:
$utc = new DateTime('12:00', new DateTimeZone('UTC'));
$bst = new DateTime('13:00', new DateTimeZone('Europe/London')); // Same instant
var_dump($utc == $bst); // false — same instant, different representation
✓ Fixed
// DateTimeImmutable — safe:
$start = new DateTimeImmutable('2026-01-01');
$end   = $start->modify('+1 month'); // $start unchanged
echo $start->format('Y-m-d'); // 2026-01-01 — correct

// Correct comparison — convert to same timezone or compare timestamps:
$utc = new DateTimeImmutable('12:00', new DateTimeZone('UTC'));
$bst = new DateTimeImmutable('13:00', new DateTimeZone('Europe/London'));
var_dump($utc->getTimestamp() === $bst->getTimestamp()); // true

// Validate before using strtotime:
$ts = strtotime($userInput);
if ($ts === false) throw new InvalidArgumentException('Invalid date');

Tags


Added 16 Mar 2026
Edited 22 Mar 2026
Views 25
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 2 pings S 1 ping S 0 pings M 0 pings T 0 pings W 4 pings T 0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S
No pings yet today
No pings yesterday
Perplexity 7 Amazonbot 6 Google 3 ChatGPT 2 Ahrefs 1
crawler 16 crawler_json 3
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Low
⚡ Quick Fix
Set date.timezone = UTC in php.ini and always pass explicit DateTimeZone objects — relying on the system timezone causes bugs when servers are in different regions
📦 Applies To
PHP 5.1+ web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
date.timezone not set in php.ini; date_default_timezone_set() in application code; DateTimeImmutable without explicit timezone
Auto-detectable: ✓ Yes phpstan lynis phpinfo
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: Medium ✗ Manual fix Fix: Medium Context: File Tests: Update

✓ schema.org compliant