Why is my date showing 1970?

A date stuck at — or near — January 1, 1970 is an epoch bug. Paste the value your code passed in and get the exact diagnosis, plus the one-line fix.

What January 1, 1970 actually is

It is epoch zero: the instant Unix time starts counting from, defined as 1970-01-01T00:00:00Z. Every Unix timestamp is an offset from that moment, which means a timestamp of 0 is not a wrong date — it is a perfectly correct rendering of nothing at all. When your UI shows 1970, the interesting question is never "why 1970", it is "what turned into a zero".

The four ways dates land in 1970

1. A null or an undefined reached the formatter

null, undefined, false and the empty string all coerce to 0 in numeric context, and new Date(0) is epoch zero. This is the cause when the rendered date is exactly midnight on January 1. A JWT with a missing or zeroed exp claim hits the same bug — see the JWT expiry decoder if that is what you are actually staring at.

new Date(null)        // 1970-01-01T00:00:00.000Z
new Date(undefined)   // Invalid Date  (note: different bug)
new Date(Number(''))  // 1970-01-01T00:00:00.000Z

2. Seconds passed where milliseconds were expected

This is the most common one, and it is why your date lands in late January 1970 rather than exactly on the 1st. Unix tradition counts seconds; JavaScript and Java count milliseconds. A ten-digit epoch read as milliseconds is a thousand times too small, so it lands a couple of weeks after the epoch instead of decades later. The fix is one multiplication, but it belongs wherever the value enters the runtime — see how JavaScript's Date handles epoch values for which calls expect which unit.

new Date(1786795200)          // 1970-01-21T16:19:55.200Z  ✗
new Date(1786795200 * 1000)   // 2026-08-15T12:00:00.000Z  ✓

3. The string "0" rather than the number 0

A quoted zero out of a CSV, a form field or a JSON column coerces the same way a numeric zero does, but it survives a !== 0 guard and slips past most null checks. Test with == null plus an explicit falsy check, or normalise the column before it reaches the view layer.

4. An invalid date rendered as a fallback

Some formatting libraries swallow an unparseable value and render epoch zero instead of throwing. new Date("2026-13-45") is Invalid Date; whether that surfaces as "Invalid Date", as an empty string, or as 1970 depends entirely on the library.

The mirror bug: milliseconds read as seconds

Run the mix-up the other way and you get a date roughly fifty-eight thousand years in the future rather than 1970. A 13-digit millisecond value multiplied by 1000 a second time lands around the year 58,391 — comical enough to spot instantly, which is why it causes far fewer support tickets than its 1970 twin. If your dates are absurdly far forward, that is the bug you have.

Why do I see December 31, 1969?

Same bug, different timezone. Epoch zero rendered in any negative UTC offset — US Eastern, Central, Pacific — falls on the evening of 1969-12-31 local time. A "1969" date and a "1970" date are the same zero; only the renderer's timezone differs. If you want to see exactly how far a given instant moves between zones, render it as local time in any timezone — the offset, not the timestamp, is what changes.

A related trap: the year 2038

Systems that store Unix time in a signed 32-bit integer overflow on 2038-01-19, wrapping to 1901 rather than 1970. If your dates jump to the early twentieth century instead of the 1970s, look for a 32-bit column or an ancient C library rather than a unit mismatch — see the Year 2038 problem for the full explanation.

Not sure your value is even the problem?

Start with the unit. The digit-count check tells you whether a bare number is seconds, milliseconds or something stranger, and it never guesses when the digits genuinely cannot decide. If you have a whole column of suspect values, convert them all at once and look for the rows that stand out.

Frequently asked questions

Why does my date show January 1, 1970?

January 1, 1970 is epoch zero — the instant Unix time starts counting from, defined as 1970-01-01T00:00:00Z. A timestamp of 0 is not a wrong date, it is a correct rendering of nothing at all. So the question is never "why 1970", it is "what turned into a zero": a null, an undefined, a false, or an empty string, all of which coerce to 0 in numeric context.

Why is my date in late January 1970 rather than exactly on the 1st?

Seconds were passed where milliseconds were expected. Unix tradition counts seconds; JavaScript and Java count milliseconds. A ten-digit epoch read as milliseconds is a thousand times too small, so it lands a couple of weeks after the epoch instead of decades later — new Date(1786795200) gives 1970-01-21T16:19:55.200Z, while new Date(1786795200 * 1000) gives the correct 2026-08-15T12:00:00.000Z.

Why do I see December 31, 1969 instead of 1970?

Same bug, different timezone. Epoch zero rendered in any negative UTC offset — US Eastern, Central or Pacific — falls on the evening of 1969-12-31 local time. A 1969 date and a 1970 date are the same zero; only the renderer's timezone differs.

Why is the string "0" causing this when my null checks pass?

A quoted zero out of a CSV, a form field or a JSON column coerces to epoch zero exactly the way a numeric zero does, but it survives a !== 0 guard and slips past most null checks. Test with == null plus an explicit falsy check, or normalise the column before it reaches the view layer.

My dates are absurdly far in the future instead. Is that the same bug?

It is the mirror of it. A 13-digit millisecond value multiplied by 1000 a second time lands around the year 58,391 rather than in 1970. If instead your dates jump to the early twentieth century — 1901 rather than the 1970s — that is a different problem: a signed 32-bit integer overflowing on 2038-01-19.