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

Timezone Handling

i18n PHP 5.0+ Intermediate

Also Known As

UTC DST timezone conversion DateTimeImmutable

TL;DR

Storing dates as UTC and converting to local timezones only for display — prevents DST bugs, ambiguous times, and incorrect date arithmetic.

Explanation

Always store and compute in UTC; convert for display. PHP's DateTimeImmutable with DateTimeZone handles conversions. Database: use DATETIME with UTC application-level enforcement (MySQL), or TIMESTAMPTZ (PostgreSQL, which stores UTC and converts automatically). DST transitions create ambiguous times (1:30am exists twice) and gaps (2:30am may not exist). The IANA timezone database (America/New_York, not EST) handles DST rules correctly; three-letter abbreviations (EST, CET) are ambiguous.

Diagram

flowchart TD
    USER_INPUT[User enters: 2026-03-15 14:00] --> AMBIG{Which timezone?}
    AMBIG -->|assumed UTC| UTC_STORE[Store as UTC in DB<br/>2026-03-15T14:00:00Z]
    AMBIG -->|assumed local| WRONG[Wrong time stored!<br/>timezone lost forever]
    UTC_STORE --> DISPLAY[Display to user]
    DISPLAY --> CONVERT[Convert UTC to user timezone<br/>Europe/London = 14:00 BST]
    subgraph PHP_Best_Practice
        DI2[DateTimeImmutable with timezone]
        UTC2[Always store UTC]
        PREF[User timezone preference<br/>in profile settings]
        DI2 --> UTC2 --> PREF
    end
style WRONG fill:#f85149,color:#fff
style UTC_STORE fill:#238636,color:#fff
style UTC2 fill:#238636,color:#fff

Common Misconception

Using local server timezone for PHP and MySQL is fine — server timezone changes (DST, migration) silently change stored times; UTC is the only unambiguous storage format.

Why It Matters

Date bugs from incorrect timezone handling cause missed appointments, wrong billing periods, and doubled/skipped notifications during DST transitions — UTC storage prevents all of these.

Common Mistakes

  • Storing local timestamps in the database — server TZ changes silently shift all stored times.
  • Using date_default_timezone_set() to a non-UTC timezone for storage — always store UTC; convert only for display.
  • Three-letter timezone abbreviations (EST, IST) — ambiguous; IST is India Standard, Israel Standard, and Irish Standard Time.
  • Not using DateTimeImmutable — DateTime::modify() mutates the object; DateTimeImmutable always returns a new instance.

Code Examples

✗ Vulnerable
// Storing local time — breaks when server TZ changes:
date_default_timezone_set('America/New_York');
$created = date('Y-m-d H:i:s'); // Local time stored in DB
// Server moved to UTC: all existing times are now wrong

// Mutable DateTime — shared reference bug:
$start = new DateTime('2026-01-01');
$end = $start->modify('+30 days'); // $start is ALSO modified!
✓ Fixed
// UTC storage, local display:
date_default_timezone_set('UTC');
$created = (new DateTimeImmutable())->format('Y-m-d H:i:s'); // Stored as UTC

// Display in user's timezone:
$utc = new DateTimeImmutable('2026-01-01 12:00:00', new DateTimeZone('UTC'));
$local = $utc->setTimezone(new DateTimeZone('America/New_York'));
echo $local->format('Y-m-d H:i:s T'); // '2026-01-01 07:00:00 EST'

Added 15 Mar 2026
Edited 22 Mar 2026
Views 48
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 2 pings M 1 ping T 1 ping W 0 pings T 1 ping F 2 pings S 0 pings S 0 pings M 2 pings T 2 pings W 0 pings T 0 pings F 1 ping S
No pings yesterday
Amazonbot 16 Perplexity 10 Google 6 Unknown AI 3 ChatGPT 3 Ahrefs 2
crawler 39 pre-tracking 1
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Medium
⚡ Quick Fix
Store all timestamps in UTC, display in user's timezone — never store local time; use PHP's DateTimeImmutable with explicit timezones and Carbon for convenience
📦 Applies To
PHP 5.0+ web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
date() without explicit timezone; storing user-visible timestamps without UTC conversion; comparing timestamps from different timezones
Auto-detectable: ✓ Yes phpstan psalm carbonphp
⚠ Related Problems
🤖 AI Agent
Confidence: High False Positives: Medium ✗ Manual fix Fix: Medium Context: File Tests: Update

✓ schema.org compliant