# Timezone Handling Guide: Best Practices for Developers
Timezone handling is one of the hardest problems in software development. This guide provides practical strategies for managing timezones correctly. For converting timestamps across timezones, use our Timestamp Converter.
Understanding Timezones
What Is a Timezone?
A timezone is a region that observes a uniform standard time. Despite the name, timezones are defined by their offset from UTC, not by geographical boundaries.
Key Concepts
- UTC (Coordinated Universal Time): The reference time standard, with no timezone offset
- Offset: The difference from UTC (e.g., +08:00 for Shanghai)
- DST (Daylight Saving Time): Seasonal clock adjustment used in some regions
- Timezone identifier: IANA name like "America/New_York" or "Asia/Shanghai"
Common Timezone Identifiers
| Identifier | Location | UTC Offset (Standard) | UTC Offset (DST) |
| UTC | Universal | +00:00 | — |
| America/New_York | New York | -05:00 | -04:00 |
| America/Los_Angeles | Los Angeles | -08:00 | -07:00 |
| Europe/London | London | +00:00 | +01:00 |
| Europe/Paris | Paris | +01:00 | +02:00 |
| Asia/Shanghai | Shanghai | +08:00 | — |
| Asia/Tokyo | Tokyo | +09:00 | — |
| Australia/Sydney | Sydney | +10:00 | +11:00 |
The Golden Rule: Store UTC, Display Local
Why UTC?
UTC has no DST transitions, no seasonal changes, and no geopolitical complications. It's the same everywhere on Earth at any given moment.
Implementation Pattern
// Store in UTC
const storeTime = new Date().toISOString();
// "2024-07-08T10:00:00.000Z"
// Display in local timezone
const displayTime = new Date(storeTime).toLocaleString('en-US', {
timeZone: 'America/New_York'
});
// "7/8/2024, 6:00:00 AM"
// Convert timestamp for display
const ts = 1720425600;
const localDisplay = new Date(ts * 1000).toLocaleString('zh-CN', {
timeZone: 'Asia/Shanghai'
});
Common Timezone Strategies
Strategy 1: UTC Everywhere
Store, compute, and transmit in UTC. Convert to local time only at the presentation layer.
Pros: Simple, unambiguous, no conversion bugs Cons: Users see UTC times if the UI doesn't convertStrategy 2: Store with Timezone
Store both the UTC time and the user's timezone.
{
"event_time": "2024-07-08T10:00:00Z",
"user_timezone": "America/New_York"
}
Pros: Preserves the user's original context
Cons: More storage, need to handle timezone changes
Strategy 3: Store as Timestamp
Store as a Unix timestamp (always UTC) and track timezone separately.
{
"event_time": 1720425600,
"user_timezone": "Asia/Shanghai"
}
Pros: Compact, efficient, easy arithmetic
Cons: Not human-readable, needs conversion for display
Working with the IANA Timezone Database
What Is the IANA Database?
The IANA Time Zone Database (also called tzdata or zoneinfo) is the standard source for timezone information. It tracks:
- UTC offsets for every region
- DST transition rules
- Historical timezone changes
- Timezone abbreviations and names
Using IANA Timezones in Code
// JavaScript (modern browsers)
const date = new Date();
const shanghaiTime = date.toLocaleString('zh-CN', {
timeZone: 'Asia/Shanghai',
dateStyle: 'full',
timeStyle: 'long'
});
// Using Intl API
const formatter = new Intl.DateTimeFormat('en-US', {
timeZone: 'America/New_York',
year: 'numeric',
month: 'short',
day: 'numeric',
hour: '2-digit',
minute: '2-digit',
timeZoneName: 'short'
});
Using Timezone Libraries
For Node.js and older browsers, use a library:
// Using Luxon
const { DateTime } = require('luxon');
const dt = DateTime.now().setZone('Asia/Shanghai');
console.log(dt.toISO()); // 2024-07-08T18:00:00+08:00
// Using date-fns-tz
import { format, utcToZonedTime } from 'date-fns-tz';
const zonedTime = utcToZonedTime(new Date(), 'Asia/Shanghai');
console.log(format(zonedTime, 'yyyy-MM-dd HH:mm:ss', { timeZone: 'Asia/Shanghai' }));
Handling DST Transitions
Spring Forward (DST Start)
During spring forward, one hour doesn't exist. In the US Eastern timezone on March 10, 2024, 2:00 AM became 3:00 AM. Times between 2:00 and 3:00 AM don't exist.
// Handle non-existent times
function safeTimeCreate(hour, minute, timezone) {
const dt = DateTime.fromObject(
{ year: 2024, month: 3, day: 10, hour, minute },
{ zone: timezone }
);
if (dt.isValid) return dt;
// Time doesn't exist — push forward
return dt.set({ hour: hour + 1 });
}
Fall Back (DST End)
During fall back, one hour repeats. In the US Eastern timezone on November 3, 2024, 2:00 AM occurs twice.
// Handle ambiguous times
// Specify which occurrence you want
const beforeFallBack = DateTime.fromObject(
{ year: 2024, month: 11, day: 3, hour: 1, minute: 30 },
{ zone: 'America/New_York' }
).toISO({ suppressMilliseconds: true });
// 2024-11-03T01:30:00-04:00 (before fall back)
Scheduling Across Timezones
Scenario: Meeting Scheduler
// Schedule a meeting at 10 AM New York time
// Show it in multiple timezones
const meetingTime = DateTime.fromObject(
{ year: 2024, month: 7, day: 8, hour: 10, minute: 0 },
{ zone: 'America/New_York' }
);
const timezones = [
'America/Los_Angeles', // 7:00 AM
'Europe/London', // 3:00 PM
'Europe/Paris', // 4:00 PM
'Asia/Shanghai', // 10:00 PM
'Asia/Tokyo', // 11:00 PM
'Australia/Sydney' // 12:00 AM+1
];
timezones.forEach(tz => {
const local = meetingTime.setZone(tz);
console.log(${tz}: ${local.toFormat('h:mm a')});
});
Recurring Events
// A daily meeting at 9 AM Shanghai time
// Using Luxon for reliability
const dailyMeeting = (date) => {
return DateTime.fromObject(
{ year: date.year, month: date.month, day: date.day, hour: 9, minute: 0 },
{ zone: 'Asia/Shanghai' }
);
};
// This correctly handles DST in other timezones
// The meeting is always 9 AM Shanghai, but may shift in other zones
Best Practices Checklist
- Always store UTC in databases and internal representations
- Use IANA timezone identifiers (Asia/Shanghai, not CST)
- Convert at the boundary — only for display
- Handle DST transitions explicitly
- Use timezone-aware libraries (Luxon, date-fns-tz)
- Test with edge cases — DST transitions, timezone changes
- Never trust client time — validate against server time
- Document timezone assumptions in your API
- Use ISO 8601 with offsets for external communication
- Keep your tzdata updated — timezone rules change
Conclusion
Timezone handling doesn't have to be a nightmare. By following the golden rule — store UTC, display local — and using the right tools and libraries, you can build applications that handle time correctly across any timezone. Always test edge cases, keep your timezone database updated, and use our Timestamp Converter for quick, accurate timezone conversions.