Guides
Unix timestamp in seconds or milliseconds: why does the date show 1970?
Check why a timestamp becomes 1970, compare seconds with milliseconds, and use Convertix Online to read UTC dates without losing the field’s meaning.
Eternity Labs ·If a recent timestamp turns into a date in January 1970, first check whether seconds were read as milliseconds. Unix-style seconds and JavaScript milliseconds count from the same starting point, but one second contains 1,000 milliseconds. A wrong unit can move the displayed date by decades. A missing value converted to zero can also produce the epoch date, so 1970 is a clue, not a diagnosis.
Here is a fictional support investigation. I receive a small event export containing `1704067200`, while another file shows `1704067200000`. A colleague thinks the records describe different moments. I want to establish what the fields mean before changing the export or reporting a fault. The files and conversation are invented; the numerical examples are reproducible calculations.
The two numbers describe the same example instant
With Unix seconds as the unit, `1704067200` corresponds to January 1, 2024, at 00:00:00 UTC. Expressed in milliseconds, the same instant is `1704067200000`. Multiplying the first value by 1,000 changes its unit, not the event it represents.
If software instead reads `1704067200` as milliseconds, the result is January 20, 1970, at 17:21:07.200 UTC. That surprisingly early date is exactly what the mistaken arithmetic produces. It does not mean the original event happened in 1970.
The POSIX explanation of the epoch identifies the Unix/POSIX starting point as January 1, 1970, at midnight UTC. JavaScript's ordinary `Date` representation uses milliseconds from that starting point, as documented in the MDN Date reference.
I would keep both the number and its declared unit in my notes. Without that second piece, a large integer is simply an ambiguous value. The field name, export documentation, or producing system must supply the meaning.
A quick comparison before touching the original file
I would start with a copy of one harmless example row. A complete customer export is unnecessary when the question concerns only a number's representation. The investigation becomes easier when names, account identifiers, and unrelated fields are absent.
| Example input | Declared interpretation | Corresponding UTC instant |
|---|---|---|
| `1704067200` | Seconds since the Unix epoch | `2024-01-01T00:00:00Z` |
| `1704067200000` | Milliseconds since the Unix epoch | `2024-01-01T00:00:00Z` |
| `1704067200` | Mistakenly treated as milliseconds | `1970-01-20T17:21:07.200Z` |
| `0` | Zero seconds or milliseconds | `1970-01-01T00:00:00Z` |
The last row deserves attention. Zero is a valid timestamp value. It should not automatically mean “unknown,” “not yet received,” or “no appointment.” Those states need their own representation in the system producing the file.
I would also preserve the original text. If a spreadsheet has already rounded the number or displayed it in scientific notation, the visible cell may no longer be enough to establish the original value. The first check is what the source actually exported.
Using the timestamp tools in Convertix Online
The public Convertix Online interface includes Text & data, with Timestamp → date and Date → timestamp operations. These names and the public conversion implementation were checked on September 14, 2026. This guide concerns the browser tool.
For the first operation, I would enter one of the example numbers without grouping commas. The two correctly interpreted values above correspond to the same UTC date. The current timestamp operation infers seconds or milliseconds from the magnitude of the input, which is convenient for common recent values. Automatic inference still cannot establish what an undocumented source field means.
For the reverse direction, I would use an explicit date-time such as `2024-01-01T00:00:00Z`. The current Date → timestamp operation returns whole seconds. That distinction matters when comparing its output with a system that expects milliseconds or preserves fractions of a second.
These are expected results established by the arithmetic and the public implementation, not a report of an interactive test performed for this article. I would check the actual output before using it elsewhere, especially with dates outside the ordinary recent range or a format from an unfamiliar system.
Ten digits or thirteen digits: a useful hint, with limits
For dates around the present period, Unix seconds commonly appear as ten-digit integers, and milliseconds as thirteen-digit integers. That makes the two example values easy to recognize. It is a practical clue when looking at an export, not a permanent rule that applies to every timestamp.
Older dates may use fewer digits. Values before the epoch can be negative. Other systems can count microseconds, nanoseconds, days, or time from a different origin. An identifier can also happen to contain ten or thirteen digits without representing a date at all.
I would therefore ask what generated the field before deciding what to do with it. A label such as `created_at` tells me the intended event, but does not necessarily declare the unit. A data contract saying “integer Unix seconds” is much more useful.
In our fictional case, I would annotate the two sources as `created_at_seconds` and `created_at_milliseconds` in my working notes. I would not rename a production field or rewrite every value merely because the digit counts look familiar. The explanation should be established before any change is proposed.
UTC and local time can show different calendar dates
Once the unit is correct, two displays can still look different because they format the same instant in different time zones. That is a separate question from the seconds/milliseconds distinction.
For a simple fixed-offset example, `2024-01-01T00:00:00Z` is the same instant as `2023-12-31T19:00:00-05:00`. The date on the second clock is still December 31. Nothing has moved backward in time; the labels describe different positions relative to UTC.
The final `Z` indicates UTC in the standard date-time string format. An explicit offset such as `-05:00` provides another way to anchor the displayed local clock reading. A string containing only `2024-01-01 00:00` does not provide that same clarity. The ECMAScript date-time string specification defines the interoperable format used by JavaScript.
I would compare UTC instants first, then choose a display appropriate for the reader. A screen showing local time and an export showing UTC can both be correct. Their documentation should make the difference visible rather than requiring someone to infer it from a five-hour gap.
A named time zone is more than a fixed offset
An offset describes the difference from UTC at an instant. A named region's time zone can carry rules that change the offset across dates. Those two pieces of information serve related but different purposes.
For an event that already happened, preserving an explicit instant helps systems agree on chronology. For a recurring instruction such as “every morning at nine in this city,” the region's time-zone rules may also be necessary. Repeating a fixed number of seconds is not automatically the same instruction as repeating a local calendar time.
The MDN guide to date and time formats distinguishes local date-time values from values that include an offset. In my notes, I would keep “when it happened” separate from “how the person should see it.”
Convertix can help translate a supported input. It does not know whether my fictional export describes a one-time event, a recurring schedule, or a date with no time of day. I need that business meaning before choosing a representation. Otherwise, a technically valid conversion can still answer the wrong question.
Fractions of a second are information too
Now suppose the example input is `2024-01-01T00:00:00.250Z`. The `.250` represents 250 milliseconds after midnight. If the receiving format keeps only whole seconds, that detail cannot remain in the returned integer.
That is relevant to Convertix's current reverse operation, which returns whole Unix seconds. I would not use a seconds-only round trip as proof that millisecond precision had been preserved. The result may describe the right second while losing information within it.
For an ordinary human-readable activity note, whole seconds might be sufficient. For comparing closely spaced events, I would first establish the precision required by the source and destination. The decision comes from the task, not from how many digits look convenient on the screen.
I would also distinguish precision from accuracy. A timestamp containing three decimal places can express milliseconds, but that alone does not prove the originating clock was accurate to a millisecond. Formatting a value more precisely does not improve the clock that produced it.
When 1970 points to an empty field instead
The fictional investigation changes if the source row contains an empty value. A downstream program might replace it with zero, intentionally or accidentally. The resulting epoch date can look legitimate even though the source did not supply an event time.
I would trace the value through the smallest available chain: original field, parsed value, conversion input, displayed date. At each step, I would ask whether absence has remained absence. This is more informative than repeatedly converting the same zero and hoping for another date.
A value marked “unknown” should not silently become midnight at the epoch. Equally, a genuine zero should not be discarded solely because it looks unusual. The right distinction depends on the source format and the event being recorded.
The practical question is: did the system receive a date, or did a default create one? Convertix can display the meaning of a numeric input; it cannot recover a missing event time from an empty field.
A timestamp does not establish the event's meaning
Even two correctly converted instants can refer to different stages. One might record when a device created an event, another when a server received it, and a third when an export was generated. A difference between them is not automatically a clock error.
In my fictional support note, I would keep the field names beside the results. “Created” and “received” deserve separate rows until their definitions say otherwise. If delivery was delayed, both timestamps might be accurate descriptions of their respective events.
I would also avoid inferring that a record is authentic simply because its date is plausible. A timestamp is data. Understanding its representation does not verify who produced the event or whether the file was modified.
Unix-style time also has conventions around leap seconds. The POSIX rationale explains that they are not applied to its seconds count. That is another reason to avoid describing every such timestamp as an exact physical stopwatch of all elapsed seconds since 1970.
The support note I would send after checking
A useful conclusion would be short and specific: “The first file stores seconds and the second stores milliseconds. Both example values represent January 1, 2024, at midnight UTC. The 1970 display came from interpreting the seconds value as milliseconds.” Each sentence identifies a fact that can be checked.
If the source unit remained undocumented, I would say so instead: “The seconds interpretation produces the expected period, but the export format still needs confirmation.” A plausible date is supporting evidence, not a replacement for the source definition.
I would attach the harmless example, the declared units, the expected UTC representation, and the field meanings. That is enough for another person to repeat the comparison without receiving the full original file.
To work through a supported example, open Convertix Online and choose Text & data. The general Convertix guide describes the broader toolkit. For this investigation, one correctly labeled value is a better starting point than changing an entire export at once.