What is a Unix timestamp?
A Unix timestamp (also called epoch time, POSIX time, or Unix time) is the number of seconds elapsed since 00:00:00 UTC on Thursday, 1 January 1970 — a moment known as the Unix epoch. It's the universal way computers store and exchange points in time. While humans read dates like "April 30, 2026 at 3:45 PM," computers store this same moment as 1746028800: a single integer that's unambiguous, time-zone-free, locale-independent, and easy to sort.
The Unix timestamp is the de-facto standard for nearly every machine-readable timestamp:
- Databases — MySQL
INTtimestamps, MongoDB ObjectIDs, Redis expiration times - HTTP headers —
Cache-Control: max-age=..., JWTexp/iat/nbfclaims (per RFC 7519) - Filesystems — Linux
statoutput (mtime, ctime, atime), macOS HFS+ & APFS - APIs & logs — most JSON APIs use Unix timestamps for created_at, updated_at fields
- Cookies — the
Expiresattribute is a Unix timestamp - Cron jobs, distributed systems, blockchain transactions (Bitcoin, Ethereum) — all use epoch time
The fundamental advantage: a Unix timestamp is a single integer. No parsing ambiguity (is "11/12/2026" November or December?), no time zone confusion, easy arithmetic (seconds-since-X = current - X), trivial to sort. The disadvantage: not human-readable. That's where converters like this one come in.
How epoch time works under the hood
The Unix epoch was chosen pragmatically. When Bell Labs designed Unix in 1971, they needed a fixed reference point. 1970-01-01 00:00:00 UTC was recent enough to be easy to mentally subtract from, far enough back to handle existing dates in their systems, and aligned with the Gregorian calendar. The choice has since become indelible — billions of timestamps in databases worldwide reference this moment.
Seconds vs milliseconds
The original Unix time was second-precision. JavaScript and many modern systems use millisecond precision (multiplied by 1000). Telling them apart by length:
| Length | Unit | Example (current era) |
|---|---|---|
| 10 digits | Seconds | 1746028800 = 2026-04-30 12:00:00 UTC |
| 13 digits | Milliseconds | 1746028800000 = same moment, ms precision |
| 16 digits | Microseconds | Linux clock_gettime(CLOCK_REALTIME) |
| 19 digits | Nanoseconds | Go's time.Now().UnixNano() |
The Y2038 problem
32-bit signed integers can store values from -2,147,483,648 to +2,147,483,647. Unix timestamps stored as 32-bit signed integers will overflow on 19 January 2038 at 03:14:07 UTC (the Y2038 problem, also called "Epochalypse"). Systems that haven't migrated to 64-bit timestamps will wrap around to 13 December 1901 — date arithmetic everywhere will silently break.
By 2026, most operating systems and major databases have migrated:
- Linux — kernel 5.6+ (March 2020) supports 64-bit time_t on 32-bit ARM. Glibc 2.32+ (Aug 2020) does the same in userspace.
- macOS, Windows 64-bit, BSDs — already 64-bit time_t since the early 2000s.
- JavaScript —
Dateuses 64-bit floats, never had Y2038. Safe until ~year 275,760. - MySQL —
TIMESTAMPstill 32-bit (max 2038-01-19). UseDATETIMEfor dates beyond. (Or upgrade to MySQL 8.0+ which has fixes pending.) - PostgreSQL, SQLite — already 64-bit timestamps. No Y2038 issue.
- Embedded systems — millions of devices still vulnerable. IoT, industrial controllers, legacy financial systems.
- Use
BIGINT(8 bytes) instead ofINT(4 bytes) for any timestamp column. - In MySQL, prefer
DATETIMEoverTIMESTAMPfor dates after 2038. - Audit any C/C++ code that uses
time_ton 32-bit platforms. - Test with timestamps near
2^31 - 1in CI — many bugs appear only then.
Time zones, ISO 8601, and the eternal confusion
A Unix timestamp is always UTC. There's no such thing as "Unix timestamp in PST" — the same instant is the same number everywhere on Earth. Time zones come in only when displaying or accepting human input.
ISO 8601 — the international standard
ISO 8601 defines the universal date-time string format. Used by JSON APIs, JWT, log files, RSS, and most modern data formats:
// Date only
2026-04-30
// Date + time + UTC ('Z' = Zulu = UTC)
2026-04-30T12:00:00Z
// With timezone offset (-05:00 = EST)
2026-04-30T07:00:00-05:00
// With sub-second precision
2026-04-30T12:00:00.123Z
// Duration / interval
P1Y2M10DT2H30M // 1 year, 2 months, 10 days, 2 hours, 30 minutes
// All represent the same moment as Unix timestamp 1746028800
Common timezone gotchas
- Don't store timestamps in local time. Always store UTC; render in user's local time at display. Daylight-saving transitions corrupt local-time storage.
- "PST" is ambiguous. Use IANA timezone names (
America/Los_Angeles) instead. PST = Pacific Standard Time, but in summer that region is on PDT (Pacific Daylight Time). - Two timestamps that "look the same" can be different moments.
2026-04-30T12:00:00in Tokyo vs London is 9 hours apart. Always include the timezone offset. - Watch out for leap seconds. Unix time pretends they don't exist (it skips them). Some systems (TAI, GPS time) handle them differently. Mostly only matters for sub-second-precision systems.
Working with timestamps in 8 programming languages
JavaScript
// Current Unix timestamp (milliseconds — JS standard)
Date.now(); // 1746028800000
// Convert to seconds (Unix-classic)
Math.floor(Date.now() / 1000); // 1746028800
// From timestamp to Date object
new Date(1746028800000); // ms input
new Date(1746028800 * 1000); // seconds input — multiply by 1000
// To ISO 8601
new Date(1746028800000).toISOString();
// "2026-04-30T12:00:00.000Z"
// To human-readable in user's timezone
new Date(1746028800000).toLocaleString('en-US', { timeZone: 'America/New_York' });
Python
from datetime import datetime, timezone
# Current Unix timestamp
import time
time.time() # 1746028800.123 (float seconds)
int(time.time()) # 1746028800
# Convert timestamp to datetime
datetime.fromtimestamp(1746028800) # local time
datetime.fromtimestamp(1746028800, timezone.utc) # UTC (recommended)
# datetime to timestamp
datetime(2026, 4, 30, 12, 0, tzinfo=timezone.utc).timestamp() # 1746028800.0
# ISO 8601 parsing (Python 3.11+)
datetime.fromisoformat("2026-04-30T12:00:00Z")
PHP
// Current timestamp
time(); // 1746028800
// To formatted date
date('Y-m-d H:i:s', 1746028800); // 2026-04-30 12:00:00 (server timezone)
gmdate('Y-m-d H:i:s', 1746028800); // 2026-04-30 12:00:00 (UTC)
// Date string to timestamp
strtotime('2026-04-30 12:00:00 UTC'); // 1746028800
strtotime('+1 hour'); // current time + 3600
// ISO 8601 parsing
$dt = new DateTimeImmutable('2026-04-30T12:00:00Z');
$dt->getTimestamp();
Java
import java.time.*;
// Current epoch
Instant.now().getEpochSecond(); // 1746028800
Instant.now().toEpochMilli(); // 1746028800123
// Timestamp to Instant
Instant.ofEpochSecond(1746028800);
Instant.ofEpochMilli(1746028800000L);
// To ISO 8601
Instant.now().toString(); // "2026-04-30T12:00:00Z"
// Local time formatting
ZonedDateTime.now(ZoneId.of("America/New_York"))
.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
Go
import "time"
// Current epoch
time.Now().Unix() // 1746028800
time.Now().UnixMilli() // 1746028800000
time.Now().UnixNano() // 1746028800123456789
// From timestamp to time.Time
time.Unix(1746028800, 0) // 2nd arg = nanoseconds
time.UnixMilli(1746028800000)
// ISO 8601 (RFC 3339 in Go's terminology)
time.Now().UTC().Format(time.RFC3339) // "2026-04-30T12:00:00Z"
// Parse ISO 8601
t, _ := time.Parse(time.RFC3339, "2026-04-30T12:00:00Z")
t.Unix()
Rust
use std::time::{SystemTime, UNIX_EPOCH};
// Current epoch
let secs = SystemTime::now()
.duration_since(UNIX_EPOCH).unwrap().as_secs();
// Better: use chrono crate for date manipulation
use chrono::{DateTime, Utc, TimeZone};
let now: DateTime<Utc> = Utc::now();
println!("{}", now.timestamp()); // 1746028800
println!("{}", now.to_rfc3339()); // "2026-04-30T12:00:00+00:00"
// From timestamp
Utc.timestamp_opt(1746028800, 0).unwrap();
Ruby
require 'time'
# Current epoch
Time.now.to_i # 1746028800
Time.now.to_f # 1746028800.123 (with subseconds)
# Timestamp to Time
Time.at(1746028800) # local time
Time.at(1746028800).utc # UTC
# ISO 8601
Time.now.utc.iso8601 # "2026-04-30T12:00:00Z"
# Parse ISO 8601
Time.parse("2026-04-30T12:00:00Z").to_i
Bash / shell
# Current Unix timestamp
date +%s # 1746028800
# Timestamp to readable date
date -d @1746028800 # GNU date (Linux)
date -r 1746028800 # BSD date (macOS, *BSD)
# Date string to timestamp (GNU)
date -d '2026-04-30 12:00:00 UTC' +%s
# ISO 8601 in UTC
date -u +%Y-%m-%dT%H:%M:%SZ
# Time arithmetic
date -d '7 days ago' +%s # GNU
date -v -7d +%s # BSD
Common timestamp use cases
Database created_at / updated_at columns
Storing timestamps as BIGINT (Unix milliseconds) is fast, indexable, sortable, and timezone-independent. Use DATETIME with explicit UTC if you need readable storage. Don't use TIMESTAMP in MySQL for dates after 2038.
JWT exp/iat/nbf claims
RFC 7519 defines these as NumericDate — Unix seconds since epoch. The most common bug: passing milliseconds when seconds are expected, making the token "expire" 1000 years in the future.
HTTP cache headers
Cache-Control: max-age=3600 means "cache for 3600 seconds." Expires: ... is a date string. Last-Modified and If-Modified-Since use HTTP-date format (a specific RFC 1123 variant), not Unix timestamps.
Logging & monitoring
Structured logs (JSON, log4j, syslog) timestamp every event with Unix milliseconds. Logging systems (Elasticsearch, Loki, Splunk) parse and index by timestamp for fast time-range queries.
Distributed systems & databases
Snowflake IDs, MongoDB ObjectIDs, ULIDs, UUIDv7 — all embed timestamps in their structure for sortability. Even when not directly visible to applications, the underlying timestamp is critical to system behavior.
Cron jobs & scheduled tasks
Schedulers run jobs at specific Unix timestamps. The job may want to know "the timestamp when I should have run" vs "the actual time I ran" — useful for backfills and idempotent processing.
Blockchain transactions
Bitcoin block timestamps are Unix seconds. Ethereum is the same. Smart contracts rely heavily on block.timestamp for time-locked operations and randomness.
Common timestamp mistakes
- Mixing seconds and milliseconds. The #1 timestamp bug. Multiplying or dividing by 1000 in the wrong place. Use language conventions consistently — JS uses ms, Python defaults to seconds.
- Storing local time instead of UTC. Always store UTC. Render to local time only when displaying. Daylight-saving transitions silently corrupt data.
- Using "yesterday at midnight" without a timezone. "Midnight" varies by 24 hours globally. Always specify timezone or use UTC.
- Off-by-one with epoch boundaries. January 1, 1970 at 00:00:00 UTC is timestamp
0— not 1. Some buggy code starts at 1. - Comparing timestamps in different units.
if (db_ts > api_ts)may compare seconds against ms — always 1000× off. - Not handling Y2038. Audit your stack now. Use BIGINT for new timestamp columns; verify older systems handle 64-bit time_t.
- Forgetting leap seconds. Unix timestamps don't represent leap seconds — they skip them. Sub-second precision systems sometimes need TAI (atomic time) instead.
- Using
Date.now()in tests. Tests become time-dependent and flake. Inject a clock or mockDate.now.
Unix epoch online — common queries answered
Variations: "unix epoch date", "unix epoch online", "epoch unix timestamp", "epoch timestamp to time", "epoch to timestamp", "posix time converter". They all describe the same operation: converting between a number-of-seconds-since-1970-01-01-UTC and a human-readable date. Each section below addresses one phrasing directly.
Unix epoch date — what "the epoch" actually is
The Unix epoch is the moment 1970-01-01T00:00:00Z — the zero point. Every Unix timestamp is the count of seconds (or milliseconds) elapsed since that instant in UTC. It's a numeric line, not a calendar — the same timestamp 1700000000 represents the same instant everywhere on Earth, but renders as different local clock times depending on the viewer's timezone. The converter above shows the UTC interpretation alongside your local time so you can spot timezone bugs immediately.
Epoch unix timestamp now — the live clock
The current epoch second updates every second at the top of the converter. Copy it for use in iat/exp claims of a JWT, in cache TTL calculations, or in audit-log rows. For the millisecond version (which JavaScript's Date.now() returns), append three zeros to the second value or click the "ms" toggle. To verify a JWT's expiry against now, paste the token into the JWT decoder and the relative-time of the exp claim renders alongside.
Epoch to timestamp / timestamp to epoch — bidirectional conversion
The two conversions are different operations sharing one workflow:
- Epoch → date. Paste
1700000000and the converter shows2023-11-14T22:13:20Z(UTC), the local-time equivalent, the relative time ("about 2 years ago"), the ISO 8601 representation, and the day of the week. Auto-detects whether the number is seconds (10 digits today) or milliseconds (13 digits). - Date → epoch. Pick a date and time from the calendar widget; the seconds and milliseconds versions both render. Useful for SQL
WHERE created_at > 1700000000queries when your column stores epoch.
POSIX time converter — same thing as Unix epoch
POSIX time and Unix time are the same thing. POSIX is the formal IEEE specification (POSIX.1) that codifies what most operating systems implemented as Unix time in the 1970s. The defining sentence: "Seconds Since the Epoch" — measured against UTC, with leap seconds intentionally not counted. This means POSIX time runs slightly slow during leap-second insertions (one second is replayed) and one timestamp can occasionally map to two real-world instants. The converter above ignores this for display purposes (which matches how JavaScript's Date object behaves); for second-precision astronomy or GPS work, use TAI time instead.
ISO 8601 date format vs Unix timestamp — when to use each
Same instant, two representations: 1700000000 (Unix) and 2023-11-14T22:13:20Z (ISO 8601). Use Unix timestamps for: arithmetic (subtracting one from another gives elapsed seconds), efficient indexed range queries in databases, log files where bytes matter. Use ISO 8601 for: human-readable timestamps in API responses, calendar systems, anywhere a non-developer reads the value. The converter above shows both side-by-side so you can pick the format your destination expects.
Milliseconds to date — JavaScript Date.now() and equivalents
JavaScript's Date.now() and Java's System.currentTimeMillis() return milliseconds since epoch (13 digits today), not seconds. Most other languages return seconds: Python's time.time(), Go's time.Now().Unix(), PostgreSQL's EXTRACT(EPOCH FROM NOW()). The converter auto-detects: 10-digit input is treated as seconds, 13-digit as milliseconds. To force one mode, use the toggle. The classic "off by 1000" bug happens when one service produces ms and another consumes seconds — the resulting date is roughly year 53,718.
Timestamp best practices
- Always store UTC. Convert to local time only when rendering to the user.
- Use BIGINT (or 64-bit integers) for new timestamp columns. 4-byte INTs hit the Y2038 limit.
- Pick one unit per system. Either seconds or milliseconds — don't mix. Document it in the API spec.
- Use ISO 8601 in JSON APIs. More human-readable than Unix timestamps; trivial to parse in every language.
- Use IANA timezone names (
America/Los_Angeles) not abbreviations (PST) — abbreviations are ambiguous. - Inject a clock for testability. Don't call
Date.now()directly in business logic; pass a clock object you can mock. - Validate timestamps on input. Reject obvious garbage (negative, far-future) before saving.
- Log all timestamps in UTC. Multi-region applications cannot debug logs that are in mixed timezones.
- For high-precision systems, consider TAI. Trading, scientific instruments, and GPS use TAI (atomic time) which doesn't skip leap seconds.