What Is an Epoch Timestamp and How Do You Convert It to a Real Date?
An epoch timestamp is just a number that represents a moment in time, usually counted from the Unix epoch: 1970-01-01 00:00:00 UTC. If the raw value looks like machine noise, try our free epoch converter and turn it into a readable date without doing mental arithmetic in the dark.
The useful bit is not the math, it’s the translation. A timestamp can tell you exactly when something happened, but only if you know whether the number is in seconds, milliseconds, or something more exotic.
What an epoch timestamp actually means
Most developers mean Unix time when they say epoch timestamp. The count starts at midnight UTC on 1970-01-01 and increases as time moves forward. That makes it easy for systems to sort events, compare dates, and store time as a plain number instead of a locale-specific string.
In practice, epoch timestamps show up in logs, APIs, databases, file metadata, analytics events, and browser storage. They’re compact and boring in the best way. A number like 1700000000 is easier for a machine to handle than Tue, 14 Nov 2023 22:13:20 GMT.
The catch is that “epoch timestamp” is often used loosely. One service may use seconds, another milliseconds, and a third may hand you microseconds or nanoseconds if it really wants to be annoying. If you don’t check the unit, your date conversion will be wrong by a factor of 1,000.
If you want a broader refresher on why computers start counting time from 1970, see our guide to Unix timestamps.
Seconds, milliseconds, and the bug farm
The single biggest mistake with an epoch timestamp is mixing up units. A 10-digit value is usually seconds. A 13-digit value is usually milliseconds. That rule is not universal, but it’s a good first pass when you’re scanning logs or JSON.
Here’s why the bug gets ugly. If a system expects seconds and you send milliseconds, the date lands far in the future. If it expects milliseconds and you send seconds, the result falls somewhere near 1970, which is how you end up debugging a payment event that appears to have happened before the invention of your product.
Some quick checks help:
- Seconds: usually around 10 digits, for example
1700000000. - Milliseconds: usually around 13 digits, for example
1700000000000. - Microseconds: usually 16 digits.
- Nanoseconds: usually 19 digits.
When you’re reading raw JSON, it helps to format the payload before you guess. A tool like JSON formatter makes timestamp fields easier to spot, especially when they’re buried in nested objects.
How to convert an epoch timestamp to a real date
The conversion is simple once you know the unit. Take the epoch value, interpret it in the correct scale, then convert from UTC to whatever display format you need. In JavaScript, the classic move is to multiply seconds by 1,000 before passing them to Date.
// Seconds to JavaScript Date
const seconds = 1700000000;
const dateFromSeconds = new Date(seconds * 1000);
// Milliseconds already work as-is
const milliseconds = 1700000000000;
const dateFromMilliseconds = new Date(milliseconds);
console.log(dateFromSeconds.toISOString());
console.log(dateFromMilliseconds.toISOString());In Python, you can do the same thing with the standard library:
from datetime import datetime, timezone
seconds = 1700000000
ms = 1700000000000
print(datetime.fromtimestamp(seconds, tz=timezone.utc))
print(datetime.fromtimestamp(ms / 1000, tz=timezone.utc))Different languages have different defaults and footguns. Some treat the input as local time unless you explicitly ask for UTC. Others expect milliseconds when the value you found in a backend log is in seconds. The math is easy; the assumptions are where the damage happens.
Reading epoch values in APIs, databases, and logs
API payloads often use epoch timestamps because they serialize cleanly into JSON. You’ll see them in audit logs, event streams, webhook delivery records, and auth tokens. The value is easy to compare numerically, which is useful when you want to sort by recency or calculate age.
Databases can store timestamps either as native date types or as integers. Native types are nicer when you need calendar logic, but integers are sometimes preferred for event sourcing or high-volume write pipelines. If a table stores time as an integer, make sure the team has agreed on the unit. Future-you deserves that courtesy.
In logs, epoch values are often easier to grep than human dates because they’re exact and timezone-free. The tradeoff is readability. If you need to transform plain-text data before working with it, our JSON to CSV guide is useful when the source data is trapped in a structured export and you want a more manageable view.
Rule of thumb: if the number is suspiciously long, don’t convert it until you know the unit. Guessing is how timestamps become archaeology.
Timezone math is a separate problem
An epoch timestamp itself is timezone-agnostic. It represents an absolute point in time, usually in UTC. The confusion starts when humans want to see that same moment in local time, with daylight saving time and regional offsets layered on top.
That means the same epoch value can be displayed differently depending on where you are. The underlying instant does not change. Only the presentation does. If a bug report says “the timestamp is wrong,” it may actually mean “the timestamp is right, but the timezone rendering is wrong.”
When converting for a UI, always be explicit about the zone. Use UTC for storage and transport if possible, then format for display at the edge. That keeps the data sane and the front end flexible.
If you routinely switch between zones, a dedicated timezone converter is handy for checking what a timestamp should look like in another region.
Validate before you convert
Before you turn an epoch timestamp into a human date, ask three questions: what unit is it in, what timezone do you want to show, and is the source value actually valid. That last one matters more than people think. Empty strings, negative values, and malformed numbers all show up in real systems.
If you are building code around timestamps, guard the input first. A simple check can save you from weird output later:
function isLikelyEpoch(value) {
return Number.isFinite(value) && value > 0;
}
function toDate(value, unit = 'seconds') {
const n = Number(value);
if (!isLikelyEpoch(n)) return null;
return new Date(unit === 'seconds' ? n * 1000 : n);
}That example is intentionally plain. Real code may need stricter validation, range checks, or schema enforcement, but the idea is the same: don’t trust the input just because it looks numeric.
For test data, it’s useful to generate timestamps across a range so you can catch boundary issues. Old dates, current dates, and future dates can expose formatting bugs fast.
A Worked Example
Say you find this in an API response:
{
"created_at": 1700000000,
"updated_at": 1700003600000
}The first value is probably seconds. The second is probably milliseconds. If you feed them both into the same conversion path, one of them will be wrong by three orders of magnitude.
Here’s the practical conversion:
created_at = 1700000000 # seconds
updated_at = 1700003600000 # milliseconds
created_at_utc = 2023-11-14T22:13:20Z
updated_at_utc = 2023-11-14T23:13:20ZAnd here is what that looks like in JavaScript:
const payload = {
created_at: 1700000000,
updated_at: 1700003600000
};
const created = new Date(payload.created_at * 1000);
const updated = new Date(payload.updated_at);
console.log(created.toISOString());
console.log(updated.toISOString());The important part is not the exact date. It’s the pattern: inspect the digits, identify the unit, convert with the right multiplier, then format in the timezone you actually need. That’s the workflow whether you’re debugging a webhook or checking a database export by hand.
Frequently Asked Questions
Is an epoch timestamp always in UTC?
The epoch itself is defined from a UTC starting point, so the underlying number is timezone-neutral. Problems only appear when you display it as a local date string. Store and compare in UTC, then convert for presentation if needed.
How can I tell if an epoch timestamp is in seconds or milliseconds?
Look at the length first. Around 10 digits usually means seconds, while around 13 digits usually means milliseconds. It’s not perfect, but it catches most real-world cases quickly.
Why does my converted date look decades off?
That almost always means the unit is wrong. If you treated milliseconds as seconds, the date will land far in the future. If you treated seconds as milliseconds, it will collapse back toward 1970.
Can epoch timestamps be negative?
Yes. Negative values represent dates before 1970-01-01 00:00:00 UTC. Some systems support them cleanly, while others reject them or display them incorrectly, so check the platform before relying on that behavior.
The Bottom Line
An epoch timestamp is simple once you strip away the noise: it’s a numeric moment in time, usually measured from 1970 in UTC. The real work is identifying the unit, handling timezone display separately, and avoiding the classic seconds-versus-milliseconds trap.
If you’re debugging logs, an API payload, or a database field, convert the value in one place and verify the result in another. If the number still looks cursed, give the epoch converter a spin and check the output against the source.
That’s usually enough to turn a suspicious integer into something a human can read without squinting at the calendar and swearing at the stack trace.