What is Unix epoch time?
Unix time (also called epoch time or POSIX time) is a system for describing a point in time as a single integer: the number of seconds that have elapsed since 00:00:00 UTC on Thursday, January 1, 1970. This reference point is called the Unix epoch. Leap seconds are not counted.
The epoch was chosen when Unix was being developed at Bell Labs in the early 1970s. The exact date was arbitrary — the engineers simply needed a recent, fixed reference point that could be stored efficiently in a 32-bit integer. Over the following decades, the convention became universal.
Why developers use Unix timestamps
Human-readable timestamps are convenient for display but awkward to work with in code. A Unix timestamp solves several real problems:
- Timezone-independent — Unix timestamps are always UTC. Two timestamps from servers in different timezones are directly comparable without conversion.
- Trivially sortable — a larger integer is always a later moment in time. Sorting by timestamp requires no parsing.
- Arithmetic is simple — "one hour from now" is current epoch + 3600. "How many seconds between two events" is subtraction. No calendar library needed.
- Language-agnostic — an epoch integer passed between Python, Go, JavaScript, and a SQL database means the same thing to all of them.
- Compact storage — a 64-bit integer takes 8 bytes. An ISO 8601 string takes 20+ bytes.
Getting the current epoch in code
# Bash
date +%s # 1748534400
# Python
import time
int(time.time()) # 1748534400
# JavaScript (returns milliseconds — divide by 1000 for seconds)
Math.floor(Date.now() / 1000) # 1748534400
# Go
import "time"
time.Now().Unix() // 1748534400
# PHP
time(); // 1748534400
# PostgreSQL
SELECT EXTRACT(EPOCH FROM NOW())::BIGINT; -- 1748534400Milliseconds vs seconds — the JavaScript gotcha
This is the most common Unix timestamp bug. JavaScript's Date.now() returns milliseconds since the epoch, not seconds. Most other languages and systems use seconds. This means a JavaScript timestamp is a 13-digit number (~1,748,534,400,000) while a seconds-based timestamp is 10 digits (~1,748,534,400).
// JavaScript
Date.now() // 1748534400000 — milliseconds (wrong for most APIs)
Math.floor(Date.now() / 1000) // 1748534400 — seconds (correct)
// Quick sanity check:
// 10 digits = seconds
// 13 digits = millisecondsCommon use cases
API timestamps
REST APIs frequently use epoch timestamps in request and response payloads. JWT tokens carry an exp (expiration) field as a Unix timestamp in seconds. Webhook payloads from services like Stripe, GitHub, and Twilio include epoch timestamps for event timing.
Database storage
Storing timestamps as integers in a database column is faster to index and query than storing formatted strings. Many applications store created_at and updated_at as Unix timestamps and convert to local time only at display time.
Cache expiry and TTL
Cache systems like Redis use epoch timestamps for key expiry. A SET key value EX 3600 expires in 3600 seconds from now; an EXPIREAT command takes an absolute epoch timestamp.
The year 2038 problem
Older systems stored Unix timestamps as 32-bit signed integers, which overflow on January 19, 2038 at 03:14:07 UTC. After that point, a 32-bit counter wraps around to a large negative number — equivalent to December 13, 1901.
Modern systems use 64-bit integers, which can represent timestamps up to the year 292 billion — not a practical concern. If you maintain legacy systems with 32-bit timestamp columns (MySQL's TIMESTAMP type is the most common culprit), migrate to a 64-bit type (DATETIME in MySQL, BIGINT elsewhere) before 2038.