Skip to main content

Practical guide

Convert UNIX Timestamps and Handle Time Zones Safely

A timestamp can produce a plausible date with the wrong unit. Start with the source contract, then check one fixed example.

Reproduce a seconds-versus-milliseconds bug

JavaScript Date takes milliseconds. Passing Unix seconds directly creates a date near the start of 1970. This executable example shows the bug and its correction:

const seconds = 1725148800;
new Date(seconds).toISOString(); // "1970-01-20T23:12:28.800Z"
new Date(seconds * 1000).toISOString(); // "2024-09-01T00:00:00.000Z"

The first call does not throw. It interprets the supplied number in the wrong unit. The ECMAScript Date specification defines this millisecond time value. A valid result can therefore still describe the wrong event.

Read the source field’s unit before conversion. Digit count provides a clue, not a reliable type check. Negative dates, fractions, and distant dates can defeat a ten-digit or thirteen-digit rule. Prefer a documented field such as createdAtEpochSeconds over an unexplained timestamp.

Keep the original value in a bug report. Include its declared unit, expected date, actual date, and receiving API. That information lets another person reproduce the error without guessing your device’s time zone. For a batch import, check the earliest and latest converted dates against the source records.

Check the converter with a fixed instant

Open the UNIX timestamp converter. Select Date to timestamp and enter 2024-09-01T00:00:00Z. Keep Treat as UTC enabled and disable Show parsed datetime.

Units Expected output
Seconds (s) 1725148800
Milliseconds (ms) 1725148800000

For the reverse check, select Timestamp to date with the matching unit. The seconds input returns Sun 1 September 2024 00:00:00 UTC. The milliseconds input returns Sun 1 September 2024 00:00:00.000 UTC.

This mode displays UTC. It does not provide a named IANA time-zone selector. Use a separate formatter for local display. A fixed instant gives a repeatable check; a changing “now” value does not.

Read T, Z, and offsets

In RFC 3339 text, T separates the date from the time. Z specifies a zero UTC offset. For example, 2024-09-01T05:30:00+05:30 identifies the same instant as midnight UTC on that date. RFC 3339 section 5.6 defines these fields.

A local string without an offset does not identify an instant by itself. A parser may supply the device’s zone or another default. Do not remove a supplied offset just to make the displayed clock time look familiar. For interchange, preserve the offset and fractional precision required by the receiving system.

Keep the instant separate from the time zone

Unix time counts from the epoch at January 1, 1970 UTC. A named zone controls how that instant appears as local calendar fields. Formatting the same instant in another zone can change its displayed date without changing its timestamp.

A numeric offset describes one relationship with UTC. It does not encode a location’s historical or future rules. The IANA Time Zone Database records these rules and receives updates when governments change them. Use identifiers such as America/New_York when location rules matter. Abbreviations such as CST do not identify one unique rule set.

For a past event, store its instant and useful source context. For a recurring local appointment, also store local time, named zone, and recurrence rules. A fixed sequence of elapsed hours can move the displayed appointment time after an offset change. Define how future appointments respond when the rule database changes.

Resolve daylight-saving gaps and overlaps

A forward clock change can skip a local time. A backward change can repeat it with two different offsets. A local timestamp alone cannot distinguish the repeated occurrences. Choose an explicit rule: reject ambiguity, select the earlier instant, or select the later instant.

The TC39 Temporal repository reports Stage 4 as checked on November 6, 2026. Its ZonedDateTime model represents an instant with a named zone and calendar. The Temporal documentation explains disambiguation options. Feature-detect Temporal in each supported runtime before using it.

Test both sides of a transition in the zones your application supports. Record the runtime and time-zone data version when two systems disagree. An offset copied from another season cannot resolve the mismatch.

Preserve timestamp precision

JavaScript Number represents integers exactly only within its safe integer range. Current millisecond timestamps fit that range, but nanosecond timestamps do not. Read long integer timestamps as strings or BigInt values before arithmetic. Converting a rounded number to BigInt cannot restore the lost digits.

An integer’s storage unit does not prove measurement accuracy. A device can store nanoseconds while updating its clock less often. Keep the source precision in the data contract, and avoid adding digits that imply a more precise measurement. Use a monotonic clock for elapsed durations within a process, rather than subtracting adjustable wall-clock readings.

Unix time also differs from an uninterrupted count of physical seconds. RFC 9636 defines Unix time using the POSIX epoch without leap seconds. Systems can apply different leap-second handling policies. Check that policy when comparing clocks from different systems; an ordinary date converter cannot reconcile it automatically.

Convert Windows FILETIME without rounding

Windows FILETIME uses 100-nanosecond intervals from January 1, 1601 UTC. The Windows file-time documentation also describes file-system differences in resolution and updates. For whole Unix seconds, the conversion is:

const unixSeconds = 1700000000n;
const filetime = (unixSeconds + 11644473600n) * 10000000n;
// 133444736000000000n

Use the Unix-to-FILETIME converter with explicit input units. Choose decimal output for comparison with this formula. Use the reverse converter to check the original timestamp. Keep byte order explicit when inspecting file bytes; decimal text has no byte-order setting.

A fractional input must map to complete FILETIME ticks. The converter rejects smaller fractions rather than rounding them. Its unsigned range is wider than the range accepted by Windows FileTimeToSystemTime. Check the receiving API as well as the stored field.