A few years ago I was debugging an order system where the creation time showed up as "Jan 18, 1970." The database stored a Unix timestamp, the frontend multiplied it by 1000 unnecessarily, and suddenly a recent order looked like it was placed before I was born.
That is the kind of confusion Unix timestamps create when you do not understand the basics. This guide covers what timestamps are, where they come from, and the practical patterns you need to avoid the mistakes I have made.
What Is a Unix Timestamp?
A Unix timestamp is the number of seconds that have passed since January 1, 1970, at midnight UTC. That starting point is called the Unix Epoch.
1704067200 → January 1, 2024 00:00:00 UTC
Every day adds 86,400 seconds. The number is always in UTC, which means it represents the same moment everywhere in the world. What changes is how you display that moment in a local time zone.
Seconds vs Milliseconds: The Most Expensive Difference
Here is where things go wrong. JavaScript's Date.now() returns milliseconds:
Date.now(); // 1704067200000
But Unix timestamps are traditionally in seconds:
date +%s # 1704067200
If you pass a millisecond value to a system expecting seconds, your date ends up tens of thousands of years in the future. If you pass seconds to JavaScript's new Date() without multiplying by 1000, you get a date in 1970. I have seen both bugs in production.
Other Common Formats
Besides seconds and milliseconds, you will also run into:
Unix Timestamp (seconds): 1704067200
Unix Timestamp (milliseconds): 1704067200000
ISO 8601: 2024-01-01T00:00:00Z
RFC 2822: Mon, 01 Jan 2024 00:00:00 +0000
ISO 8601 is usually the safest format for APIs because it includes time zone information and is human-readable. Unix timestamps are the safest for storage and sorting because they are just integers.
How the Timestamp Converter Helps
Our Unix Timestamp Converter handles the conversion in both directions. You can paste a timestamp and see the local, UTC, and ISO representations immediately, or pick a date and get the corresponding timestamp.
I use it most often when:
- A log file shows a raw timestamp and I need to know when something actually happened
- An API returns seconds but my frontend needs milliseconds
- I need to verify a boundary value, like the start of a month or the 2038 overflow point
Where Timestamps Show Up
API Responses
Most APIs return timestamps for created and updated fields:
{
"created_at": 1704067200,
"updated_at": 1704153600,
"expires_at": 1704240000
}
Always check the unit. Some APIs use seconds, others use milliseconds, and a few use ISO strings. Never assume.
Database Storage
Storing dates as integers makes range queries fast and unambiguous:
SELECT * FROM users
WHERE created_at > 1704067200;
But it also means your schema has to document whether the column is seconds or milliseconds. Otherwise the next developer will make the same mistake I did.
JavaScript Date Handling
const timestamp = 1704067200;
const date = new Date(timestamp * 1000); // seconds → milliseconds
console.log(date.toISOString());
For server-side Python:
import datetime
timestamp = 1704067200
date = datetime.datetime.fromtimestamp(timestamp, tz=datetime.timezone.utc)
print(date)
Time Zones and Daylight Saving Time
Because a Unix timestamp is always UTC, it never changes based on where you are. What changes is the local display:
1704067200 in UTC: 2024-01-01T00:00:00Z
1704067200 in EST: 2023-12-31T19:00:00
1704067200 in PST: 2023-12-31T16:00:00
Daylight Saving Time is also handled automatically when you convert to local time, because the conversion uses the timezone rules in effect on that specific date. This is one of the main reasons timestamps are safer than storing local date strings.
Best Practices I Follow
Document the unit. Every timestamp column or field should have a comment or schema note saying seconds or milliseconds.
Store and transmit in UTC. Convert to local time only at the display layer.
Use established libraries. Do not write your own date math. In JavaScript,
date-fnsorLuxonare solid. In Python, stick withdatetimeandpytzorzoneinfo.
The 2038 Problem
A signed 32-bit integer can only hold values up to 2,147,483,647, which corresponds to January 19, 2038. One second later, the value overflows and wraps around to 1901.
Most modern systems use 64-bit integers and are safe. But embedded devices, legacy databases, and old C code compiled with 32-bit time_t are still at risk. We cover this in more detail in the article on the 2038 problem.
Questions I Get Asked
Can timestamps represent dates before 1970?
Yes, with negative numbers. -1 represents one second before the Epoch. Support varies by system, so test before relying on it.
How do I convert timestamps in Excel?
For seconds: =A1/86400+DATE(1970,1,1), then format as a date.
Should I use seconds or milliseconds?
Use seconds for storage, APIs, and databases unless you genuinely need sub-second precision. Use milliseconds when working with JavaScript's Date object, because that is what it expects.
Conclusion
Unix timestamps are a simple idea with a long history of causing subtle bugs. The key is knowing your units, keeping everything in UTC until display time, and documenting your conventions clearly.
If you want to verify a timestamp quickly, use the FastUnix Timestamp Converter. For timestamp values embedded in JSON responses, paste the payload into the JSON Formatter to inspect the structure before you convert anything.