Zeitzonenproblem-Debugging: Häufige Fehler und Korrekturen

The Most Common Timezone Bugs

After years of developer pain, certain timezone bugs appear again and again. Here are the most common ones with their fixes.

Bug 1: The Naive Datetime Trap (Python)

# Bug: comparing naive and aware datetimes
from datetime import datetime, timezone
deadline = datetime(2024, 3, 1, 0, 0)          # naive — no timezone!
now = datetime.now(timezone.utc)                 # aware UTC
print(now > deadline)    # TypeError: can't compare!

# Worse: storing naive datetimes in DB then comparing
created = datetime.now()    # naive — assumed local, but which server?

# Fix: always use timezone-aware datetimes
deadline = datetime(2024, 3, 1, 0, 0, tzinfo=timezone.utc)
now = datetime.now(timezone.utc)
print(now > deadline)    # Works correctly

Bug 2: DST Transition — The Missing or Doubled Hour

# Bug: scheduling something at "2:30 AM" when clocks spring forward
# On the second Sunday in March (US), 2:00 AM → 3:00 AM
# There is NO 2:30 AM — it doesn't exist!

import zoneinfo
from datetime import datetime
tz = zoneinfo.ZoneInfo("America/New_York")
# This datetime does not exist — zoneinfo handles it, but your intent is wrong
dt = datetime(2024, 3, 10, 2, 30, tzinfo=tz)

# Fix: always compute in UTC, convert for display
# Schedule at 7:30 AM UTC instead of "2:30 AM local"

Bug 3: JavaScript Date Parsing Inconsistency

// Bug: date-only strings parsed as UTC, but displayed as local time
const d = new Date("2024-03-01");
// Parsed as: 2024-03-01T00:00:00Z (midnight UTC)
// Displayed as: March 1 in UTC+9 = but 2024-02-29T15:00:00 in UTC-9!
console.log(d.toLocaleDateString());  // "2/29/2024" in US Western timezone!

// Fix: always include time and timezone in date strings
const d = new Date("2024-03-01T00:00:00Z");   // UTC
const d = new Date("2024-03-01T00:00:00+09:00"); // KST

Bug 4: Database Storing Local Time

-- Bug: MySQL TIMESTAMP stored in local time
-- Server timezone changes → all historical data is wrong!

-- Fix: use DATETIME with UTC-only writes
-- In Django:
USE_TZ = True  # ensures all datetimes go in as UTC

Bug 5: Hardcoded UTC Offset Instead of IANA Timezone

# Bug: hardcoding UTC+9 for Korea Standard Time
KST = timezone(timedelta(hours=9))
dt = datetime.now(KST)   # Will be wrong during DST (if KST ever had DST)

# Fix: use IANA timezone names
from zoneinfo import ZoneInfo
dt = datetime.now(ZoneInfo("Asia/Seoul"))  # Correct, handles any future changes

Debugging Techniques

  • Print UTC everywhere: When debugging, always log datetime.now(timezone.utc).isoformat()
  • Test in multiple timezones: Set TZ=America/New_York or TZ=Asia/Tokyo env var to test your code in a different timezone without changing your machine
  • Test around DST transitions: Use libfaketime (Linux) or freezegun (Python) to simulate specific times
  • Check database timezone: SHOW timezone; (PostgreSQL) and SELECT @@global.time_zone; (MySQL)
# Python: test code in different timezone without changing system
TZ=America/New_York python my_script.py

# pytest with freezegun
from freezegun import freeze_time

@freeze_time("2024-03-10 06:59:00", tz_offset=-5)
def test_dst_spring_forward():
    # Test behavior at DST transition
    result = schedule_task("America/New_York", hour=2, minute=30)
    assert result.hour != 2  # 2:30 AM doesn't exist, should handle gracefully

The Golden Checklist

  • All datetimes are timezone-aware (no naive datetimes in production)
  • Database stores UTC (not local time)
  • Server timezone is set to UTC
  • API responses include timezone offset in all timestamp fields
  • Cron jobs either use UTC or explicitly set CRON_TZ
  • IANA timezone names used everywhere (never raw UTC offsets like +09:00)
  • DST transitions tested in automated tests