Online Tools Toolshu.com Log In Sign Up

Mix Up Timestamp Units and Your Date Ends Up in 1970 or the Year Fifty Thousand

Author:bhnw Released on 2026-04-25 10:38 5 views Star (0)

Your Date Shows 1970, or the Year Is Somewhere in the Fifty-Thousands

Both symptoms come from the same bug.

You have a timestamp in your code, pass it to some function, and either get 1970-01-20 back or a date tens of thousands of years in the future. You look everywhere for the mistake, but the cause is just one thing: units.

Timestamps come in two precisions — seconds and milliseconds — differing by a factor of 1,000. Mix them up and your dates go spectacularly wrong.


Why Does JavaScript Use Milliseconds While Everything Else Uses Seconds?

The Unix standard defines a timestamp as "the number of seconds elapsed since 1970-01-01 00:00:00 UTC." That's the historical standard, and Python, PHP, Go, and databases all follow it.

JavaScript is the exception. When Brendan Eich designed the Date object, he chose milliseconds as the unit — probably because millisecond precision felt more appropriate for frontend work at the time. That decision was baked in and can't be changed, so the entire frontend ecosystem now runs on milliseconds.

The current landscape:

Language / System Default precision Typical digit count
Unix / Linux Seconds 10 digits
Python time.time() Seconds (float) 10 integer digits
PHP time() Seconds 10 digits
Go time.Now().Unix() Seconds 10 digits
MySQL UNIX_TIMESTAMP() Seconds 10 digits
JavaScript Date.now() Milliseconds 13 digits
Java System.currentTimeMillis() Milliseconds 13 digits

Counting digits is the fastest way to tell: 10 digits = seconds, 13 digits = milliseconds.


Four Common Mixing Scenarios and How to Fix Them

Scenario 1: Passing seconds to JavaScript's new Date()

// Backend returned a seconds-precision timestamp
const ts = 1745000000;  // 10 digits, seconds

// Wrong: new Date() expects milliseconds
const date = new Date(ts);
console.log(date.toISOString());
// Output: "1970-01-20T20:06:40.000Z"  ← 1970!

// Correct: multiply by 1000
const date = new Date(ts * 1000);
console.log(date.toISOString());
// Output: "2026-04-11T02:13:20.000Z"  ← correct

Scenario 2: Passing milliseconds to Python's datetime.fromtimestamp()

from datetime import datetime

ts = 1745000000000  # 13 digits, milliseconds (e.g. received from frontend)

# Wrong
dt = datetime.fromtimestamp(ts)
# ValueError: year 55916 is out of range  ← year fifty-something-thousand!

# Correct: divide by 1000
dt = datetime.fromtimestamp(ts / 1000)
print(dt)  # 2026-04-11 02:13:20

Scenario 3: Frontend sends milliseconds, backend expects seconds

This is the easiest to miss, because both sides work fine in isolation and the bug only appears during integration.

// Frontend: using Date.now()
const payload = {
    created_at: Date.now()  // 1745000000000, milliseconds
};

fetch('/api/save', {
    method: 'POST',
    body: JSON.stringify(payload)
});
# Backend Python: assuming it received seconds
from datetime import datetime

data = request.json
ts = data['created_at']  # actually 1745000000000
dt = datetime.fromtimestamp(ts)  # ValueError: year out of range

# Fix option 1: convert to seconds on the frontend before sending
# JavaScript: Math.floor(Date.now() / 1000)

# Fix option 2: detect the unit on the backend
if ts > 1e10:  # over 10 billion means it's milliseconds
    ts = ts / 1000
dt = datetime.fromtimestamp(ts)

Scenario 4: Database stores seconds, Node.js reads them as milliseconds

// Timestamp from the database is in seconds
const row = await db.query('SELECT created_at FROM users WHERE id = 1');
const ts = row.created_at;  // 1745000000, seconds

// Used directly — displays 1970
const date = new Date(ts);  // wrong

// Correct
const date = new Date(ts * 1000);

How to Tell Whether a Timestamp Is Seconds or Milliseconds

Method 1: Count the digits

A seconds timestamp in 2026 is 10 digits (between 1700000000 and 1800000000). A milliseconds timestamp is 13 digits. This pattern holds from 2001 until 2286.

Method 2: Write a detection function

function detectTimestamp(ts) {
    if (ts > 1e12) return 'milliseconds';
    if (ts > 1e9)  return 'seconds';
    return 'unknown';
}

// Normalize to milliseconds for use with Date
function toDate(ts) {
    return new Date(ts > 1e12 ? ts : ts * 1000);
}
def to_datetime(ts):
    from datetime import datetime, timezone
    if ts > 1e12:
        ts = ts / 1000
    return datetime.fromtimestamp(ts, tz=timezone.utc)

Two Rules That Eliminate This Problem

Rule 1: Use ISO 8601 strings at API boundaries, not raw timestamps

ISO 8601 looks like 2026-04-11T02:13:20Z — timezone included, precision unambiguous, human-readable. No seconds-vs-milliseconds confusion is possible. If you control the API design, prefer this format for any time field.

// Frontend sends
const payload = {
    created_at: new Date().toISOString()  // "2026-04-11T02:13:20.123Z"
};
# Backend receives
from datetime import datetime
dt = datetime.fromisoformat("2026-04-11T02:13:20.123Z".replace('Z', '+00:00'))

Rule 2: If you must use raw timestamps, document the unit and validate at the entry point

Put it in your API docs: created_at: Unix timestamp (seconds). Then enforce it:

def validate_timestamp(ts: int, unit: str = 'seconds'):
    if unit == 'seconds' and ts > 1e12:
        raise ValueError(f"Expected seconds timestamp, got what looks like milliseconds: {ts}")
    if unit == 'milliseconds' and ts < 1e10:
        raise ValueError(f"Expected milliseconds timestamp, got what looks like seconds: {ts}")

When you're staring at an unfamiliar timestamp and can't tell which unit it is, paste it into the Timestamp Online Converter — it auto-detects seconds vs milliseconds and shows the corresponding date immediately.

发现周边 发现周边
Comment area

Loading...