How to Read a Unix Timestamp
You are debugging an API response and you see a field like "created_at": 1705363200. That large integer is a Unix timestamp — a count of seconds since a specific moment in the past. Once you understand what it means and how to convert it, these numbers become immediately readable.
What Is Unix Time and Why January 1, 1970?
Unix time (also called epoch time or POSIX time) is the number of seconds that have elapsed since 00:00:00 Coordinated Universal Time (UTC) on Thursday, January 1, 1970. That specific moment is called the Unix epoch.
Why 1970? When Unix was being developed at Bell Labs in the late 1960s and early 1970s, the engineers needed a reference point for measuring time. January 1, 1970 was chosen because it was recent, easy to reason about, and predated the first widespread Unix installations. It was a practical choice, not a meaningful one.
The key properties that make Unix timestamps so useful are simplicity and timezone neutrality. A Unix timestamp is always in UTC. It is a single integer. Comparing two timestamps is as simple as comparing two numbers — no timezone conversion needed, no date string parsing. These properties make timestamps the standard for storing dates in databases, transmitting dates in APIs, and tracking time in log files.
Seconds vs Milliseconds: The 10-Digit vs 13-Digit Rule
Unix timestamps traditionally count seconds. As of early 2026, the current timestamp is approximately 1,748,000,000 — a 10-digit number. However, many modern systems (especially JavaScript environments) use milliseconds, making timestamps 13 digits long.
10 digits → seconds-based timestamp (traditional Unix time)
13 digits → milliseconds-based timestamp (JavaScript, many modern APIs)
If you see a timestamp like 1705363200 (10 digits), it is in seconds. If you see 1705363200000 (13 digits), it is in milliseconds — the same moment with three zeros appended. Getting this wrong leads to dates in the year 55,000+ (if you treat milliseconds as seconds) or dates in 1970 (if you treat seconds as milliseconds and forget to multiply).
A quick sanity check: a 10-digit Unix timestamp representing a date in 2024–2030 will start with 17. A 13-digit timestamp representing the same era will start with 170 or 171.
Converting Timestamps in Different Languages
JavaScript
JavaScript's Date object works natively with millisecond timestamps. Date.now() returns the current time as milliseconds since epoch. To convert a seconds-based timestamp to a readable date:
const ts = 1705363200; // seconds
const date = new Date(ts * 1000); // multiply by 1000 for ms
console.log(date.toISOString()); // "2024-01-16T00:00:00.000Z"
If you already have a millisecond timestamp, pass it directly without multiplying: new Date(1705363200000).
Python
Python's datetime module provides fromtimestamp() and utcfromtimestamp(). The difference matters: fromtimestamp() returns the time in your local timezone, while utcfromtimestamp() returns UTC. For consistent cross-timezone behavior, prefer the UTC version or use timezone-aware datetimes.
from datetime import datetime, timezone
ts = 1705363200
dt = datetime.fromtimestamp(ts, tz=timezone.utc)
print(dt) # 2024-01-16 00:00:00+00:00
Other Languages
Most languages have similar built-in support. In PHP, date('Y-m-d H:i:s', $timestamp) formats a Unix timestamp. In Go, time.Unix(ts, 0).UTC() converts it. In Ruby, Time.at(ts).utc. The pattern is consistent: pass the timestamp and optionally specify UTC to avoid local timezone surprises.
Timezone Gotchas
Unix timestamps are always UTC. The confusion arises when you convert them to a human-readable format — that conversion is inherently local. If someone in New York and someone in Tokyo both convert timestamp 1705363200, they will get different time-of-day representations even though they are referring to the same moment.
The safest approach in applications is to store all timestamps as UTC in the database, transmit them as UTC in APIs, and convert to local time only at the point of display — typically in the user's browser or app, using their device's timezone setting. Never store "local time" as a timestamp without also recording the timezone, because the timestamp loses its meaning without that context.
Convert Unix timestamps instantly
Paste any Unix timestamp — seconds or milliseconds — and get the human-readable date in any timezone.
Negative Timestamps: Before 1970
Unix timestamps can be negative. A negative timestamp represents a moment before the Unix epoch. For example, -86400 is 86,400 seconds (one day) before January 1, 1970, which is December 31, 1969. Most modern languages and libraries handle negative timestamps correctly, but older systems and some databases may not. If you are storing historical dates from the 20th century, verify that your stack supports negative timestamps before assuming they will work.
The Y2K38 Problem: 32-Bit Overflow
This is one of the more interesting time problems in computing. Many older Unix systems store timestamps as a 32-bit signed integer. The maximum value of a signed 32-bit integer is 2,147,483,647. That value corresponds to January 19, 2038, at 03:14:07 UTC — sometimes called the "Year 2038 problem" or Y2K38.
When a 32-bit system tries to increment past this maximum, the integer overflows to a large negative number, representing a date in 1901 rather than 2038. This is not a theoretical concern — embedded systems, older Linux kernels on 32-bit hardware, and legacy software could be affected.
Modern 64-bit systems do not have this problem. A 64-bit signed integer can represent dates hundreds of billions of years into the future, well past any practical concern. The fix for older systems is migrating to 64-bit timestamp storage — something the Linux kernel completed in 2021 with kernel version 5.10, which added 64-bit time support for 32-bit architectures.
Practical Debugging Tips
When you encounter an unknown timestamp in a log or API response, a few heuristics help quickly establish what you are looking at:
- Count the digits. 10 digits = seconds, 13 digits = milliseconds. If you see 12 digits, something unusual is going on (maybe microseconds, or a custom epoch).
- Check the rough magnitude. Timestamps in the 1.7 billion range (10-digit) represent dates in 2023–2024. Timestamps starting with 2 billion represent dates after 2033.
- Watch for milliseconds in JavaScript.
Date.now(),performance.now(), and most JS APIs use milliseconds. If you copy a timestamp from browser DevTools, it is almost certainly milliseconds. - Always confirm timezone. A timestamp of 0 is midnight January 1, 1970 UTC — but 8:00 AM in Tokyo and 7:00 PM on December 31, 1969 in New York. The timestamp itself is unambiguous; the display depends on timezone.
The Bottom Line
Unix timestamps are one of the most reliable representations of time in computing precisely because they are simple: a single integer in UTC with no timezone or locale ambiguity. Learning to read them quickly — and knowing the seconds vs milliseconds distinction, the Y2K38 edge case, and the timezone conversion rules — will save you hours of debugging time over the course of your career.
Try the Epoch Converter
Instantly convert Unix timestamps to readable dates, or get the current timestamp in seconds and milliseconds.