dev cosmos/blog/timestamp-converter-guide

Unix Timestamps Explained: The Developer Guide to Epoch Time

Master Unix timestamps, ISO 8601, timezone handling, seconds vs milliseconds, and the common pitfalls that cause silent date bugs in production.

UTC

Timestamp Converter

Epoch · UTC · ISO 8601

Unix timestamps are one of the most universally used data types in software — every log line, every database record, every API response includes a timestamp of some kind. Yet they remain a constant source of bugs in production. This guide gives you a complete mental model.

UTC
Open in Dev Cosmos
Timestamp Converter →

What Is the Unix Epoch?

The Unix epoch is the reference point: January 1, 1970, 00:00:00 UTC. A Unix timestamp is simply the number of seconds (or milliseconds) that have elapsed since that moment. The choice of 1970 was arbitrary — it was the beginning of the Unix operating system's widespread deployment.

// Current timestamps in various languages
JavaScript: Date.now()                          // milliseconds
JavaScript: Math.floor(Date.now() / 1000)       // seconds
Python:     import time; time.time()            // seconds (float)
Python:     int(time.time())                    // seconds (int)
Go:         time.Now().Unix()                   // seconds
Go:         time.Now().UnixMilli()              // milliseconds
SQL:        EXTRACT(EPOCH FROM NOW())::bigint   // PostgreSQL, seconds

Seconds vs Milliseconds: The Biggest Footgun

The most common timestamp bug is mixing seconds and milliseconds. Seconds timestamps are 10 digits (e.g. 1705318200). Milliseconds timestamps are 13 digits (e.g. 1705318200000). If you pass a milliseconds value to code expecting seconds, dates will appear thousands of years in the future.

🚨
The Millisecond Trap
JavaScript's Date.now() returns milliseconds. Most Unix tools and databases expect seconds. Always divide by 1000 when passing JS timestamps to Unix-native systems.

ISO 8601 — The Right String Format

When you must store or transmit a timestamp as a string (JSON APIs, logs, HTML), always use ISO 8601:

2025-07-20T14:30:00Z          // UTC, recommended
2025-07-20T14:30:00+05:30     // with offset
2025-07-20T14:30:00.123Z      // with milliseconds

The trailing Z denotes UTC (zero offset). Always include timezone information — a timestamp without a timezone is ambiguous and dangerous.

Timezone Pitfalls

Unix timestamps themselves are always UTC — there is no timezone embedded in a timestamp. The timezone only matters when converting to a human-readable display. The rule is: store in UTC, display in local.

Anti-PatternProblemFix
Store local time in DBAmbiguous during DST transitionsStore UTC Unix timestamps
Parse date without timezoneInterpreted as local time, wrong in UTCAlways append Z or offset
Compare timestamps cross-timezoneString comparison gives wrong orderConvert to Unix int, then compare
Use Date string in SQLServer timezone affects interpretationUse TIMESTAMP WITH TIME ZONE

The Year 2038 Problem

32-bit signed integers overflow at 2147483647 — January 19, 2038 at 03:14:07 UTC. Systems still using 32-bit timestamps will roll over to negative values, behaving as if it's January 1, 1901. Modern 64-bit systems are immune (they safely represent dates 292 billion years into the future), but embedded systems and legacy code are at risk.

Date Arithmetic

Timestamp arithmetic is simple when you think in seconds:

// Add 30 days to a timestamp
var thirtyDaysLater = timestamp + (30 * 24 * 60 * 60);  // seconds
// or
var thirtyDaysLater = timestamp + (30 * 24 * 60 * 60 * 1000); // ms

// Check if a token has expired
var isExpired = Date.now() / 1000 > exp_claim; // JWT exp is in seconds

// Get days between two timestamps
var days = Math.abs(ts2 - ts1) / 86400;
💡
Seconds per unit cheat sheet
Minute: 60 · Hour: 3,600 · Day: 86,400 · Week: 604,800 · 30 days: 2,592,000 · Year: 31,536,000
More from the Blog