Javascript is required
Best practicesPublished 2026-07-28Updated 2026-08-086 min read

Unix Timestamps: UTC, CST and Daylight Saving Time

Handling timezones in internationalized apps can easily lead to bugs: Does 'CST' mean China Standard Time (UTC+8) or Central Standard Time (UTC-6)? How do we account for the missing or extra hour during Daylight Saving Time (DST) transitions? This article explains timezone physics and IANA standards.

By: Tiny
TimezoneUTCCSTDaylight SavingBest Practices

1. Problem: timezone abbreviation ambiguities and DST clock shift errors

Distributed systems suffer from two main timezone bugs: First, passing ambiguous 3-letter abbreviations like CST causes US and Chinese teams to interpret times as UTC-6 and UTC+8 respectively (a 14-hour discrepancy); second, adding +24h during Daylight Saving Time (DST) transitions in March/November causes 1-hour calculation errors.

2. Minimal reproduction: CST ambiguities and DST arithmetic failures

This example demonstrates the ambiguity of 'CST' and the failure of hardcoded millisecond additions across DST transitions:

/* Pitfall 1: "CST" abbreviation has at least 4 distinct meanings! */
// - China Standard Time: UTC+8
// - Central Standard Time (USA): UTC-6
// - Cuba Standard Time: UTC-5
// - Australia Central Standard Time: UTC+9:30
// Passing "CST" leaves the receiver unable to determine the physical instant!

/* Pitfall 2: Adding 24 hours (86,400,000 ms) on DST transition day */
// On DST spring-forward days (e.g., 2024-03-10), a day has only 23 hours!

3. Root cause: decoupling Instants from Zone Views

1. Instant: a globally unique point in physical time, identified by Unix timestamps or UTC ISO strings (with Z), independent of geographic location. 2. Zone View: converts an Instant into local year, month, day, hour, minute, second values per geographic rules. 3. IANA tz database: timezone rules change due to political or historical factors. Always use IANA names (e.g., Asia/Shanghai or America/Chicago) rather than static offsets like UTC+8.

4. Recommendation: store UTC on the backend, format dynamically with IANA on the frontend

1. Unified storage: store and transmit UTC millisecond timestamps or ISO 8601 UTC strings (2026-07-28T12:00:00Z). 2. Localized rendering: use native Intl.DateTimeFormat with timeZone: 'Asia/Shanghai'. 3. Avoid hardcoded offsets: delegate DST transitions and calendar calculations to timezone libraries.

5. Complete code: IANA timezone formatting with native Intl.DateTimeFormat

This TypeScript snippet demonstrates using modern JavaScript native Intl APIs to safely format absolute timestamps into localized representations for any IANA timezone.

function formatZonedDateTime(
  timestamp: number | Date,
  timeZone: string,
  locale = "zh-CN"
): string {
  const date = typeof timestamp === "number" ? new Date(timestamp) : timestamp;
  if (isNaN(date.getTime())) {
    throw new RangeError("Invalid date input");
  }

  const formatter = new Intl.DateTimeFormat(locale, {
    timeZone: timeZone,
    year: "numeric",
    month: "2-digit",
    day: "2-digit",
    hour: "2-digit",
    minute: "2-digit",
    second: "2-digit",
    hour12: false,
  });

  return formatter.format(date);
}

const now = 1700000000000;
console.log("Beijing Time:", formatZonedDateTime(now, "Asia/Shanghai"));
console.log("Chicago Time:", formatZonedDateTime(now, "America/Chicago"));

6. Incorrect approaches

Using 3-letter abbreviations like CST or EST in API protocols. Assuming countries maintain fixed offsets without DST. Manually adding +8 hours via string manipulation.

7. Boundaries: date arithmetic across DST transition days

When performing calendar additions (e.g., 'add 1 day'), use calendar methods like date.setUTCDate(date.getUTCDate() + 1) or dayjs.add(1, 'day') rather than adding 86400000 ms, avoiding 23-hour or 25-hour DST anomaly days.

8. Verification

Fix IANA zones such as America/New_York and test skipped/repeated local times plus day/year boundaries. Validate zone names by constructing Intl.DateTimeFormat, then assert exact formatted parts.

9. FAQ

Why shouldn't I use UTC+8 instead of Asia/Shanghai? UTC+8 is a static offset that fails to account for historical DST shifts or future policy adjustments; IANA Asia/Shanghai encompasses full historical rules.

How do I retrieve the user's current IANA timezone on the front-end? Retrieve it via Intl.DateTimeFormat().resolvedOptions().timeZone (e.g., returns Asia/Shanghai).

What is the relationship between GMT and UTC? UTC (Coordinated Universal Time) is an atomic-clock international standard; GMT (Greenwich Mean Time) is an astronomical standard. In computing, both are practically identical, but UTC is preferred.

10. Summary

Decoupling physical UTC Instants from geographic Zone Views is key to mastering international timezones. Using IANA identifiers and Intl APIs ensures robust cross-border application behavior.

Sources and further reading

Specifications and references for checking the article’s technical details.

Related articles

Keep exploring

Use the related browser tool to test the workflow with your own sample data.

Open related tool