UTC dalam Pemrograman: Praktik Terbaik

The Golden Rule: Store UTC, Display Local

The most important rule in programming with time is simple: always store timestamps in UTC, and convert to the user's local timezone only when displaying. This single principle prevents the vast majority of timezone-related bugs in software.

Why UTC?

  • Unambiguous: UTC has no daylight saving time, no political changes, no offsets. A UTC timestamp always means the same moment in time.
  • Comparable: Two UTC timestamps can be compared and sorted without conversion.
  • Portable: Your database, your server logs, and your API all agree on UTC regardless of where they are deployed.
  • Future-proof: Governments change timezone rules. Storing UTC means your historical data remains correct even if a country shifts its offset.

Common Mistakes

# BAD: Storing local time
created_at = datetime.now()          # naive datetime — timezone unknown!

# GOOD: Storing UTC
from datetime import datetime, timezone
created_at = datetime.now(tz=timezone.utc)  # timezone-aware UTC

# BAD: Converting before storage
user_time = datetime(2024, 3, 1, 14, 0, tzinfo=some_local_tz)
db.save(user_time)  # storing local time — dangerous

# GOOD: Convert to UTC before storage
utc_time = user_time.astimezone(timezone.utc)
db.save(utc_time)

Database Configuration

Ensure your database server and application server are both set to UTC:

# PostgreSQL — set default timezone
SET timezone = 'UTC';
-- in postgresql.conf: timezone = 'UTC'

# MySQL
SET time_zone = '+00:00';

# Django settings
USE_TZ = True          # always True in modern Django
TIME_ZONE = 'UTC'      # server timezone

API Design: Always Include Timezone Information

When returning dates in APIs, always include timezone information in the response:

# BAD
{"created_at": "2024-03-01 14:00:00"}

# GOOD — ISO 8601 with UTC offset
{"created_at": "2024-03-01T14:00:00Z"}
{"created_at": "2024-03-01T14:00:00+00:00"}

Displaying Local Time to Users

Convert from UTC to local time as late as possible — ideally in the view layer or on the client side:

# Python — convert UTC to user's timezone for display
from zoneinfo import ZoneInfo
utc_dt = datetime(2024, 3, 1, 14, 0, tzinfo=timezone.utc)
seoul_dt = utc_dt.astimezone(ZoneInfo("Asia/Seoul"))
print(seoul_dt)  # 2024-03-01 23:00:00+09:00

# JavaScript — browser handles local conversion
new Date("2024-03-01T14:00:00Z").toLocaleString("ko-KR", {
  timeZone: "Asia/Seoul"
})

Logging

Always log in UTC. Mixing timezones in log files makes debugging across servers in different regions extremely difficult. Include the timezone indicator explicitly: 2024-03-01T14:00:00Z — the trailing Z means UTC.