Unix Time and Time Zones
The same instant has the same Unix timestamp everywhere. Local input, display, and future schedules still need regional rules. Distinguish instants, local date/time, and elapsed duration.
Separate UTC Storage from Local Display
A UTC-based instant works well for a completed event. A recurring local appointment or a birthday cannot always be represented faithfully by one UTC number.
Key points
- Event occurrence: retain the instant, for example as epoch time, and convert to the user’s zone for display.
- Recurring 9 a.m. appointment: keep local time, an IANA ID such as America/New_York, and recurrence rules; compute each occurrence using its date.
- Treat a birthday or business date as a date when it does not denote an instant. Twenty-four elapsed hours can differ from the same local time tomorrow across a clock change.
Storage, APIs, and Logs
Decide where the time zone is applied and how you communicate it.
Database
- PostgreSQL timestamp with time zone retains an instant in UTC internally, not the original region name. Output follows the session TimeZone. Store an IANA ID separately when needed.
- timestamp without time zone is a local date/time without a zone. It can be part of a local schedule, but conversion to an instant requires a zone and an ambiguity policy.
APIs/messages
- For instant strings, choose a format such as RFC 3339 with an offset, for example 2024-02-29T12:00:00+09:00. An offset alone does not identify a region such as Asia/Tokyo.
- For epoch values, state the unit such as seconds or milliseconds. Also agree on parsing, fractions, and supported ranges.
Logs/monitoring
- Prefer UTC for analysis, or emit both UTC and local.
- Include a UTC offset such as Z or +09:00. Also retain the IANA ID separately if regional rules matter.
Conversion Examples
Explicit TZ settings reduce surprises from environment defaults.
Convert with a named region in Python
This uses zoneinfo in Python 3.9 or later. It needs system time-zone data or the Python tzdata package; provide that dependency on systems without zone data, such as many Windows environments.
from datetime import datetime, timezone
from zoneinfo import ZoneInfo
instant = datetime.fromtimestamp(1735689600, tz=timezone.utc)
print(instant.isoformat())
print(instant.astimezone(ZoneInfo("Asia/Tokyo")).isoformat())
# 2025-01-01T00:00:00+00:00
# 2025-01-01T09:00:00+09:00
In applications
- Respect an explicit input offset. For named-zone local input, define whether to reject or resolve nonexistent and repeated times rather than silently accepting library defaults.
- Choose the display zone from user settings or business requirements. OS, language runtime, and database connection settings may differ; inspect them explicitly.
Common Pitfalls
Default TZ mismatches, DST, and vague string parsing frequently bite teams.
Watch out for
- Zone-less strings may be treated as local, treated as UTC, or rejected, depending on the API. They do not universally use the environment’s default zone.
- Forward clock changes can create nonexistent local times; backward changes can repeat them. Changes are not always one hour.
- Different browser and server zones can display the same instant differently. Distinguish display differences from storing a different instant.
- Do not use a simple 86,400-second addition for the same local time tomorrow. Decide whether you need elapsed duration or a calendar appointment.
New York transition examples
These examples use America/New_York in 2026. The two November 01:30 times are different instants, distinguished by their offsets.
| UTC | Local date/time |
|---|---|
| 2026-03-08 06:59 | 2026-03-08 01:59 -05:00 |
| 2026-03-08 07:00 | 2026-03-08 03:00 -04:00 |
| 2026-11-01 05:30 | 2026-11-01 01:30 -04:00 |
| 2026-11-01 06:30 | 2026-11-01 01:30 -05:00 |
Testing and Operations
Run checks with different TZ settings to ensure consistent behavior.
Checklist
- Compare UTC and Asia/Tokyo conversions and verify a round trip to the original epoch value.
- Test missing and repeated local times, twenty-four hours later, and the same local time tomorrow separately.
- Check input offsets, seconds versus milliseconds, database connection zones, and time-zone data updates.
- See the time-zone list for regions and Unix time basics for units and conversions.
Specifications and sources
IANA Time Zone Database / tzdb theory / RFC 3339 / PostgreSQL date/time types / Python zoneinfo