A timestamp that displays a date in 1970 when you expected a recent event often has a units problem. Unix timestamps commonly use seconds, while JavaScript Date uses milliseconds. Passing a seconds value directly into a millisecond API scales the time by a factor of one thousand.
Start with the source field's documented unit and meaning. Then convert once, preserve numeric precision and format the resulting instant in an explicit timezone. Do not infer a timezone from the timestamp's digits or treat a local calendar date as an unambiguous instant.
Know what the number measures
Unix time counts from the epoch at 1970-01-01T00:00:00Z under the timekeeping model used by the system. A timestamp is not inherently a local clock reading. The same instant can be displayed as different local dates and times in different zones.
The timestamp converter supports explicit input modes so the unit or ISO representation can be selected deliberately. Its output describes the interpreted instant. The tool cannot know whether a field copied from another system was documented correctly.
Keep unit names in API fields or schema documentation, such as createdAtSeconds or an explicitly defined millisecond timestamp. A generic numeric field named time invites callers to guess. Consistent naming prevents many errors before conversion begins.
| Input | Unit | UTC interpretation |
|---|---|---|
| 0 | Seconds or milliseconds | 1970-01-01T00:00:00Z |
| 1,000,000,000 | Seconds | 2001-09-09T01:46:40Z |
| 1,000,000,000,000 | Milliseconds | The same instant as the preceding row |
| -1 | Seconds | 1969-12-31T23:59:59Z |
| -1 | Milliseconds | 1969-12-31T23:59:59.999Z |
Commas in this table are display grouping, not necessarily accepted input syntax. Use the converter's documented numeric format when entering a value.
Convert seconds and milliseconds exactly once
To use a seconds timestamp with JavaScript Date, multiply by 1,000. To derive whole seconds from milliseconds, choose a rounding rule appropriate to the protocol. Truncation and floor differ for negative values, so do not treat them as interchangeable around dates before the epoch.
const seconds = 1000000000;
const instant = new Date(seconds * 1000);
instant.toISOString(); // 2001-09-09T01:46:40.000Z
A helper that already returns milliseconds should not be multiplied again. Trace the value through parsing, storage and display, recording the unit at each boundary. Double conversion can produce a far-future date just as missing conversion can produce an unexpectedly early one.
Digit count can be a useful clue for current dates, but it is not a reliable parser contract. Historical values, future ranges, fractions and different units can break a rule based only on ten versus thirteen digits. Prefer an explicit mode.
Require an explicit offset for timed text
An ISO-style timestamp ending in Z represents UTC. A numeric offset such as +05:00 provides another unambiguous relation to UTC. A date-time string without a zone can be interpreted as local time or handled differently by systems, creating disagreement across environments.
The converter's ISO workflow requires explicit timezone information for the supported timed input. That makes the intended instant visible. A date-only value such as 2026-01-02 is a different kind of data and should not acquire an arbitrary time merely to fit a timestamp field.
Use strict parsing for application input. Invalid dates should be rejected rather than silently normalised into another day. Some programming APIs can roll overflowing components forward, which is convenient for arithmetic but surprising for user validation.
Repair an event that appears fifty years too early
Suppose an API sends created_at as a seconds timestamp and the frontend passes it directly to new Date. The displayed event falls near the epoch. Confirm the API documentation and inspect the raw numeric value before editing the formatter.
Convert seconds to milliseconds at one clearly named boundary, then keep the internal representation consistent. Add a regression case with a known instant and verify both UTC output and the intended local display. Do not compensate by adding a fixed number of years or a timezone offset.
Check the reverse path too. If the frontend sends a selected date back to the API, it must use the unit the API expects. A one-way display fix can leave updates storing values one thousand times too large.
Record the contract in the schema or client type definitions. The lasting repair is an explicit unit agreement, not a local formatting patch that the next caller must rediscover.
Format an instant without changing it
Use a timezone-aware formatter to display the instant in a named zone. A fixed offset is not a complete substitute for a zone with historical or seasonal changes. The appropriate offset depends on the instant being displayed.
For example, the same UTC instant can fall on the next calendar day in one zone and the previous day in another. That is expected. If the field represents a birthday or business date rather than an event instant, preserve its date-only semantics instead of converting it through UTC.
The locale inspector helps identify the browser's exposed formatting defaults. Those defaults are not proof of physical location and may differ from the user's preferred work timezone. Let the product's intended display rule control the formatter.
Handle ambiguous local input
During a daylight-saving transition, a local clock time can be skipped or repeated. A user entering a local time and zone may therefore provide a value with zero or two possible instants. Define how the application asks for clarification or selects an interpretation.
Do not use today's offset to interpret every date in that zone. A future meeting can occur under a different offset. Store the intended local scheduling rule and zone for recurring events where that is the product's meaning, rather than freezing one conversion forever.
Test transitions, midnight boundaries and a zone with a fractional-hour offset. These cases expose assumptions that all days have the same elapsed length or all offsets are whole hours. Keep expected semantics alongside the test values.
Preserve range and precision
JavaScript Number exactly represents integers only within its safe integer range, and Date has its own supported range. Millisecond values for ordinary contemporary dates fit comfortably, but microsecond or nanosecond counters can exceed exact integer precision when stored as Number.
If an API sends a very large integer timestamp, use an appropriate exact representation such as a string and a suitable integer type. Do not parse it into an inexact number and attempt to recover the lost digits later. Define how fractional units are handled.
Keep invalid and out-of-range values distinct from zero. The epoch is a valid instant, not a universal missing-value marker. A truthiness check that treats numeric zero as absent can corrupt legitimate historical or test data.
Use the right clock for elapsed time
Wall-clock timestamps can change when the system clock is adjusted. For measuring an operation's elapsed duration within a process, use a suitable monotonic clock such as performance.now in the browser. That value has a different origin and purpose from an epoch timestamp.
Do not subtract unrelated monotonic values from different machines or browser sessions as if they shared a global epoch. For distributed logs, use synchronised wall-clock timestamps with appropriate uncertainty and event identifiers. Timing analysis needs a clear clock model.
Leap-second handling and clock-smearing policies can also differ across systems. JavaScript Date and ordinary Unix-style workflows do not provide a universal representation of every civil timekeeping detail. For specialised precision requirements, use the system's documented time model rather than assuming all timestamps are interchangeable.
Keep machine values and display labels together
Logs should retain an unambiguous timestamp and unit or standard format. A label such as 01/02/26 03:04 can be ambiguous in both date order and timezone. Use locale formatting for readers while preserving a stable machine-readable value for correlation.
When reporting a bug, include the raw input, selected unit, expected instant, timezone and actual output. This lets another person reproduce the conversion without guessing which stage introduced the error.
Frequently asked questions
Is a Unix timestamp always in UTC?
It identifies elapsed time from a UTC-defined epoch under the system's model, rather than carrying a local timezone. Displaying it in a zone changes the clock label, not the instant. The numeric unit still needs to be specified.
Can I identify the unit from digit count?
Digit count is a clue for familiar contemporary values, not a reliable contract. Use the source documentation or an explicit mode. Historical, fractional and higher-precision timestamps can break a simple length-based guess.
Why does a date display on the previous day?
The instant may cross a calendar boundary when formatted in another zone, or a date-only value may have been converted incorrectly. Determine whether the field represents an event instant or a calendar date before changing offsets.
Should I add my timezone offset to the timestamp?
Normally use a timezone-aware formatter instead of altering the stored instant. Adding an offset changes the point on the timeline and can create double adjustments. Apply conversion only according to the field's defined semantics.
Is zero an invalid timestamp?
No. Zero represents the epoch in common second and millisecond conventions. Use an explicit missing value such as null where the schema permits it. Avoid truthiness checks that discard valid zero values.
Why use performance.now for a timer?
It is suited to elapsed-time measurement within its context and is not tied to ordinary wall-clock adjustments in the same way. It is not an epoch timestamp for cross-system logs. Choose the clock according to whether you need duration or calendar time.
What belongs in a timestamp regression test?
Include known seconds and milliseconds, zero, negative values, explicit offsets, invalid dates, range limits and timezone transitions. Verify the underlying instant separately from locale punctuation. This catches unit and semantic errors without overfitting to one display string.