What Is a Unix Timestamp?
Unix timestamps count seconds since January 1, 1970 UTC. Covers why 1970 was chosen, seconds vs milliseconds, and how to use Unix time in JavaScript, Python, Go, and SQL.
Table of contents
TL;DR: A Unix timestamp is the number of seconds that have elapsed since January 1, 1970, 00:00:00 UTC (the Unix epoch). It is timezone-independent, always UTC, and stored as a single integer — making it ideal for sorting, arithmetic, and cross-system date storage. Example: 1746785400 is May 9, 2026 at 18:00:00 UTC.
A short history — why 1970-01-01
When the Unix operating system was being developed at Bell Labs in the late 1960s, the team needed a reference point for time. They chose January 1, 1970 not for any deep technical reason, but because it was recent, round, and easy to work with on the hardware of the era.
At the time, Unix stored time as a 32-bit signed integer counting seconds. This gives a range of roughly ±68 years from the epoch — enough to last until January 19, 2038 (a problem covered in the year 2038 article).
The epoch date stuck because Unix became the foundation for most of the internet’s infrastructure. Linux, macOS, BSD, and POSIX-compliant systems all share the same epoch. Languages and runtimes built on top of these systems inherited it, and it became the de facto standard for machine-to-machine time exchange.
Seconds vs milliseconds vs microseconds
Unix timestamps come in three common precisions, and mixing them up is one of the most frequent bugs in time-related code.
| Precision | Digits (current) | Example | Use case |
|---|---|---|---|
| Seconds | 10 | 1746785400 | Unix tradition, databases, cron |
| Milliseconds | 13 | 1746785400000 | JavaScript, web APIs, event logs |
| Microseconds | 16 | 1746785400000000 | High-precision systems, C/C++, Rust |
How to tell them apart: If a value is 10 digits, it is in seconds. If it is 13 digits, it is in milliseconds. You can verify any value at epochkit’s Unix converter.
A common mistake is passing a millisecond value to an API that expects seconds. Discord’s timestamp syntax requires seconds — passing a 13-digit JavaScript Date.now() value directly results in a date far in the future (around year 57000).
How each language handles Unix time
JavaScript / TypeScript
// Current time in milliseconds
const ms = Date.now();
// Current time in seconds (for APIs, Discord, etc.)
const sec = Math.floor(Date.now() / 1000);
// Convert a Unix second timestamp to a Date object
const date = new Date(sec * 1000);
// Format with Intl.DateTimeFormat (no library needed)
const formatted = new Intl.DateTimeFormat('en-US', {
dateStyle: 'long',
timeStyle: 'short',
timeZone: 'America/New_York',
}).format(date);
JavaScript always uses milliseconds internally. When working with external systems that use seconds, multiply by 1000 when reading and divide by 1000 when writing.
Python
import time
from datetime import datetime, timezone
# Current time in seconds
sec = time.time() # float: 1746785400.123
sec_int = int(time.time()) # int: 1746785400
# Convert to a datetime object (UTC-aware)
dt = datetime.fromtimestamp(sec_int, tz=timezone.utc)
print(dt.isoformat()) # 2026-05-09T18:00:00+00:00
# Convert a datetime to a Unix timestamp
from datetime import datetime, timezone
dt = datetime(2026, 5, 9, 18, 0, 0, tzinfo=timezone.utc)
unix = int(dt.timestamp())
Always pass tz=timezone.utc to fromtimestamp to avoid interpreting the timestamp in the local timezone.
Go
package main
import (
"fmt"
"time"
)
func main() {
// Current Unix time in seconds
sec := time.Now().Unix()
// Current Unix time in milliseconds
ms := time.Now().UnixMilli()
// Convert from Unix seconds to time.Time
t := time.Unix(sec, 0).UTC()
fmt.Println(t.Format(time.RFC3339)) // 2026-05-09T18:00:00Z
// Convert a time.Time to Unix seconds
ts := time.Date(2026, 5, 9, 18, 0, 0, 0, time.UTC)
fmt.Println(ts.Unix()) // 1746785400
}
Go’s time package is explicit about Unix precision — .Unix() returns seconds, .UnixMilli() returns milliseconds, and .UnixNano() returns nanoseconds.
Rust
use std::time::{SystemTime, UNIX_EPOCH};
fn main() {
// Current Unix time in seconds
let sec = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("time went backwards")
.as_secs();
// Current Unix time in milliseconds
let ms = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("time went backwards")
.as_millis();
println!("seconds: {sec}");
println!("milliseconds: {ms}");
}
For more ergonomic date/time handling in Rust, the chrono crate is the standard choice.
SQL (PostgreSQL / MySQL)
-- PostgreSQL: current Unix timestamp (seconds)
SELECT EXTRACT(EPOCH FROM NOW())::BIGINT;
-- PostgreSQL: convert Unix seconds to a timestamp
SELECT to_timestamp(1746785400);
-- MySQL: current Unix timestamp (seconds)
SELECT UNIX_TIMESTAMP();
-- MySQL: convert Unix seconds to a datetime
SELECT FROM_UNIXTIME(1746785400);
Both databases store dates as their own internal type, but these functions let you convert to and from Unix seconds at query time.
Where you will see Unix timestamps in the wild
- HTTP headers —
Last-Modified,Expires,If-Modified-Sinceuse RFC 2822 dates, but cache systems often use Unix internally. - JWT tokens — the
iat(issued at) andexp(expiration) claims are Unix seconds. - Log files — syslog, nginx, and most server logs use Unix timestamps for fast sorting and filtering.
- Databases — columns typed as
TIMESTAMPorBIGINToften store Unix seconds for portability. - APIs — GitHub, Stripe, and most REST APIs return created/updated fields as Unix seconds.
- File systems —
staton any file shows atime/mtime/ctime as Unix timestamps.
Common pitfalls
Mixing seconds and milliseconds is the most common error. If a date displays as 1970 or year 57000, you have the wrong precision.
Naive timezone conversion — Unix timestamps are always UTC. Converting them to a local time requires knowing the timezone at display time, not at storage time. Never store a “local Unix timestamp”.
Year 2038 in 32-bit systems — signed 32-bit integers overflow on January 19, 2038. Any system storing Unix seconds in a 32-bit int or int32 field will break. See the year 2038 problem for details.
Assuming monotonicity — Unix time can go backwards if a system clock is adjusted (NTP correction, daylight saving on broken implementations, manual reset). Use a monotonic clock for measuring elapsed time, not System.currentTimeMillis() or time.time().
Related tools
Convert any Unix timestamp to a human-readable date, or convert a date to its Unix value, at epochkit’s Unix Timestamp Converter. Supports both seconds and milliseconds, with code snippets in 9 languages.