unixtimestampdatetimegopython

Unix Timestamps Explained — Convert and Format Dates in Every Language

·8 min read

What is a Unix Timestamp?

A Unix timestamp is the number of seconds (or milliseconds) elapsed since the Unix epoch: January 1, 1970, 00:00:00 UTC. It is a single integer that uniquely identifies any moment in time, completely timezone-independent.

Epoch: 1970-01-01T00:00:00Z
1716000000 = 2024-05-18T08:00:00Z (approximately)
1716000000000 = 2024-05-18T08:00:00Z in milliseconds (JavaScript)

Unix timestamps are used in: - APIs — most REST APIs return createdAt and updatedAt as ISO strings or timestamps - JWT tokensiat (issued at), exp (expiry), nbf (not before) are Unix timestamps - Log files — structured logs use timestamps for sorting and filtering - Databases — PostgreSQL EXTRACT(EPOCH FROM ...), MySQL UNIX_TIMESTAMP() - Rate limiting — retry-after headers and token bucket timestamps

Seconds vs Milliseconds — The Source of Most Bugs

FormatDigitsExampleUsed by
Seconds101716000000Most Unix tools, JWT, Go, Python
Milliseconds131716000000000JavaScript Date, Java, Android
Microseconds161716000000000000PostgreSQL precision, some C libs
Nanoseconds191716000000000000000Go time.UnixNano(), Linux kernel

The most common bug: passing a second timestamp to JavaScript's new Date() — you get January 1970 instead of 2024. Always check the digit count first.

Go — Working with Timestamps

go
import (
    "fmt"
    "time"
)

// Get current timestamp
nowSeconds  := time.Now().Unix()          // int64 seconds since epoch
nowMillis   := time.Now().UnixMilli()     // int64 milliseconds (Go 1.17+)
nowMicros   := time.Now().UnixMicro()     // int64 microseconds (Go 1.17+)
nowNano     := time.Now().UnixNano()      // int64 nanoseconds

// Convert timestamp to time.Time
ts := int64(1716000000)
t := time.Unix(ts, 0).UTC()              // seconds, no nanoseconds
fmt.Println(t.Format(time.RFC3339))       // => "2024-05-18T08:00:00Z"

// From milliseconds
tsMs := int64(1716000000000)
t2 := time.UnixMilli(tsMs).UTC()

// From nanoseconds
tsNs := int64(1716000000000000000)
t3 := time.Unix(0, tsNs).UTC()

// Formatting options
fmt.Println(t.Format("2006-01-02"))              // => "2024-05-18"
fmt.Println(t.Format("2006-01-02 15:04:05"))     // => "2024-05-18 08:00:00"
fmt.Println(t.Format(time.RFC3339))              // => "2024-05-18T08:00:00Z"
fmt.Println(t.Format(time.RFC1123))              // => "Sat, 18 May 2024 08:00:00 UTC"

// Convert to specific timezone
ist := time.FixedZone("IST", 5*60*60+30*60) // UTC+5:30
istTime := t.In(ist)
fmt.Println(istTime.Format("2006-01-02 15:04:05 MST")) // => "2024-05-18 13:30:00 IST"

// Compare timestamps
future := time.Now().Add(24 * time.Hour)
isExpired := time.Now().After(future) // false

Python — Working with Timestamps

python
import time
from datetime import datetime, timezone, timedelta

# Get current timestamp
now_s  = int(time.time())             # seconds
now_ms = int(time.time() * 1000)      # milliseconds

# Convert timestamp to datetime (always use tz=timezone.utc!)
ts = 1716000000
dt = datetime.fromtimestamp(ts, tz=timezone.utc)
print(dt.isoformat())                # => "2024-05-18T08:00:00+00:00"
print(dt.strftime("%Y-%m-%d"))       # => "2024-05-18"
print(dt.strftime("%Y-%m-%d %H:%M:%S UTC"))  # => "2024-05-18 08:00:00 UTC"

# From milliseconds
ts_ms = 1716000000000
dt2 = datetime.fromtimestamp(ts_ms / 1000, tz=timezone.utc)

# Convert datetime to timestamp
dt3 = datetime(2024, 5, 18, 8, 0, 0, tzinfo=timezone.utc)
ts_back = int(dt3.timestamp())       # => 1716019200 (approximately)

# Convert to specific timezone
ist = timezone(timedelta(hours=5, minutes=30))  # UTC+5:30
dt_ist = dt.astimezone(ist)
print(dt_ist.strftime("%Y-%m-%d %H:%M:%S %Z"))  # => "2024-05-18 13:30:00 UTC+05:30"

# WRONG — naive datetime (no timezone) is unreliable
dt_naive = datetime.fromtimestamp(ts)  # uses local timezone — avoid in servers

JavaScript — Working with Timestamps

javascript
// Get current timestamp
const nowMs = Date.now();                       // milliseconds
const nowS = Math.floor(Date.now() / 1000);    // seconds

// Parse millisecond timestamp
const ts = 1716000000000;
const d = new Date(ts);
console.log(d.toISOString());   // => "2024-05-18T08:00:00.000Z"

// Parse SECOND timestamp (the most common mistake!)
const tsS = 1716000000;
const d2 = new Date(tsS * 1000); // multiply by 1000 to get ms
console.log(d2.toISOString());  // => "2024-05-18T08:00:00.000Z"

// Check digit count before parsing
function parseTimestamp(ts) {
  const n = Number(ts);
  // 10 digits = seconds, 13 digits = milliseconds
  return new Date(String(ts).length <= 10 ? n * 1000 : n);
}

// Format for display
d.toLocaleDateString("en-IN", { timeZone: "Asia/Kolkata" });
// => "18/5/2024"

d.toLocaleString("en-IN", {
  timeZone: "Asia/Kolkata",
  dateStyle: "medium",
  timeStyle: "short",
});
// => "18 May 2024, 1:30 pm"

// Get the timestamp from an ISO string
const ts2 = new Date("2024-05-18T08:00:00Z").getTime(); // => 1716019200000 (ms)

SQL Timestamp Operations

sql
-- PostgreSQL — convert to epoch
SELECT EXTRACT(EPOCH FROM NOW())::BIGINT;   -- => 1716000000 (seconds)
SELECT EXTRACT(EPOCH FROM NOW()) * 1000;    -- milliseconds

-- PostgreSQL — convert epoch to timestamp
SELECT TO_TIMESTAMP(1716000000);            -- => 2024-05-18 08:00:00+00

-- MySQL
SELECT UNIX_TIMESTAMP();                    -- current timestamp (seconds)
SELECT FROM_UNIXTIME(1716000000);           -- => 2024-05-18 08:00:00

-- Filter by time range
SELECT * FROM events
WHERE created_at BETWEEN
  TO_TIMESTAMP(1716000000) AND TO_TIMESTAMP(1716086400);

Storing Timestamps in APIs — ISO vs Epoch

FormatExampleProsCons
ISO 8601 string"2024-05-18T08:00:00Z"Human-readable, unambiguous timezoneLarger payload, must parse
Unix epoch (seconds)1716000000Compact, easy arithmeticNot human-readable, ms vs s confusion
Unix epoch (ms)1716000000000JavaScript-nativeNot human-readable

Recommendation: Use ISO 8601 strings ("2024-05-18T08:00:00Z") in REST APIs for human-readable dates. Use Unix timestamps for performance-critical internal systems, JWT claims, and cache TTLs.

The Year 2038 Problem

32-bit signed integers can represent timestamps up to January 19, 2038, 03:14:07 UTC — after that they overflow to negative values. This affects: - Old embedded systems using time_t (32-bit) - Some legacy MySQL TIMESTAMP columns (internally 32-bit) - Any system that casts a timestamp to a 32-bit int

Modern systems are safe: Go's int64 handles timestamps until year 292,277,026,596. JavaScript uses 64-bit floats (safe until year 275,760). PostgreSQL TIMESTAMPTZ is safe until year 294,276.

Check your legacy code for any int32 or uint32 timestamp arithmetic.

Use JSONKit's Unix Timestamp Converter to convert any timestamp to a human-readable date in any timezone — paste a number and get the ISO date, or enter a date and get the epoch value.

Try Unix Timestamp Converter

Convert Unix timestamps to human-readable dates and generate code for 6 languages.