X Xerobit

Unix Timestamp — What Epoch Time Is and How to Convert It

A Unix timestamp is seconds since January 1, 1970 UTC. It's the standard time representation for APIs, databases, and logs. Here's how to convert timestamps and avoid timezone...

Mian Ali Khalid · · 7 min read
Use the tool
Timestamp Converter
Convert Unix timestamps, epoch seconds/milliseconds, and ISO 8601 dates.
Open Timestamp Converter →

A Unix timestamp is a count of seconds elapsed since the Unix epoch: January 1, 1970 00:00:00 UTC. It’s timezone-independent, precise, and universally understood by programming languages and databases. When you see 1715414400 in an API response or database field, that’s a Unix timestamp.

Use the Timestamp Converter to convert between Unix timestamps and human-readable dates in any timezone.

The Unix epoch

January 1, 1970, 00:00:00 UTC is timestamp 0. Every second after that increments the counter by 1.

0           = 1970-01-01 00:00:00 UTC
86400       = 1970-01-02 00:00:00 UTC (one day = 86,400 seconds)
1000000000  = 2001-09-09 01:46:40 UTC
1715414400  = 2024-05-11 00:00:00 UTC

The name “epoch” refers to the reference point. The choice of January 1, 1970 was a practical decision by Unix developers in the early 1970s — it was a recent round date at the time of implementation.

Seconds, milliseconds, and microseconds

Modern systems use different precision levels:

UnitExampleUsed by
Seconds1715414400Unix, most POSIX APIs, databases
Milliseconds1715414400000JavaScript, Java (System.currentTimeMillis())
Microseconds1715414400000000Python time.time_ns(), high-precision logging
Nanoseconds1715414400000000000Go time.Now().UnixNano(), kernel timers

The confusion between seconds and milliseconds is the most common timestamp bug. 1715414400000 is a millisecond timestamp — passing it to a function expecting seconds would produce a date 1,715 years in the future.

How to tell the difference:

  • 10 digits (e.g., 1715414400) → seconds timestamp, recent date
  • 13 digits (e.g., 1715414400000) → milliseconds timestamp, recent date
  • 10 digits starting with 1 → seconds → likely 21st century
  • 16+ digits → microseconds or nanoseconds

A seconds timestamp should be roughly 1.7 billion for dates around 2024. A milliseconds timestamp should be roughly 1.7 trillion.

Current timestamp

The current Unix timestamp in various environments:

# Bash/Unix terminal:
date +%s                        # Seconds
date +%s%3N                     # Milliseconds
import time

time.time()        # Float: seconds with microsecond precision (1715414400.123456)
int(time.time())   # Integer seconds
round(time.time() * 1000)  # Milliseconds
Date.now()              // Milliseconds
Math.floor(Date.now() / 1000)  // Seconds
import "time"
time.Now().Unix()      // Seconds
time.Now().UnixMilli() // Milliseconds
time.Now().UnixNano()  // Nanoseconds
-- PostgreSQL:
SELECT EXTRACT(EPOCH FROM NOW())::INT;

-- MySQL:
SELECT UNIX_TIMESTAMP();

Converting timestamp to date

The math (seconds)

Unix timestamp → date:

1. Seconds from epoch to years: 1715414400 / (365.25 × 24 × 3600) ≈ 54.3 years
2. Add to 1970: 1970 + 54.3 ≈ 2024 ✓

Always use a library for actual date conversion — the math gets complicated with leap years, leap seconds, and timezone offsets.

In code

from datetime import datetime, timezone

ts = 1715414400

# Seconds timestamp:
dt = datetime.fromtimestamp(ts, tz=timezone.utc)
print(dt.isoformat())  # 2024-05-11T00:00:00+00:00

# Milliseconds timestamp:
dt_ms = datetime.fromtimestamp(ts / 1000, tz=timezone.utc)

# Custom timezone:
from zoneinfo import ZoneInfo
dt_ny = datetime.fromtimestamp(ts, tz=ZoneInfo('America/New_York'))
print(dt_ny.isoformat())  # 2024-05-10T20:00:00-04:00 (EDT)
const ts = 1715414400;

// Seconds to Date:
const date = new Date(ts * 1000); // JavaScript uses milliseconds
console.log(date.toISOString()); // "2024-05-11T00:00:00.000Z"

// Milliseconds timestamp (already in ms):
const dateMs = new Date(1715414400000);
console.log(dateMs.toISOString()); // Same result

// Format in local timezone:
console.log(date.toLocaleString('en-US', { timeZone: 'America/New_York' }));
-- PostgreSQL:
SELECT to_timestamp(1715414400);
-- 2024-05-11 00:00:00+00

-- MySQL:
SELECT FROM_UNIXTIME(1715414400);
-- 2024-05-11 00:00:00 (in server timezone)

SELECT FROM_UNIXTIME(1715414400, '%Y-%m-%d %H:%i:%s');
-- 2024-05-11 00:00:00

Converting date to timestamp

from datetime import datetime, timezone

# From UTC date string:
dt = datetime(2024, 5, 11, tzinfo=timezone.utc)
timestamp = int(dt.timestamp())
# 1715385600

# From ISO 8601 string:
dt = datetime.fromisoformat('2024-05-11T00:00:00+00:00')
timestamp = int(dt.timestamp())
// From date string:
const date = new Date('2024-05-11T00:00:00Z');
const timestamp = Math.floor(date.getTime() / 1000); // Seconds
const timestampMs = date.getTime(); // Milliseconds

// From year, month, day (UTC):
const ts = Date.UTC(2024, 4, 11) / 1000; // Month is 0-indexed: 4 = May

Common timestamp bugs

The 2038 problem

32-bit systems store Unix timestamps as int32_t (signed 32-bit integer), which overflows at 2,147,483,647 seconds — January 19, 2038. Any 32-bit system still running in 2038 will experience timestamp wraparound.

Modern 64-bit systems use int64_t, which can represent dates hundreds of billions of years in the future. The problem only affects legacy 32-bit code, embedded systems, and databases with 32-bit timestamp columns.

Check in your codebase: if you have INT or INT(11) columns storing timestamps in MySQL, they’re 32-bit and will break in 2038. Use BIGINT or a DATETIME/TIMESTAMP type with the database handling the storage.

Forgetting UTC

A Unix timestamp is always UTC. The confusion arises when converting to human-readable dates — the same timestamp represents different wall-clock times in different timezones.

1715414400 = 2024-05-11 00:00:00 UTC = 2024-05-10 20:00:00 EDT = 2024-05-11 09:00:00 JST

When storing dates for user-facing events, always store as UTC timestamp and convert to local timezone at display time. Never store “local time” in a database — it becomes ambiguous during DST transitions.

Seconds vs milliseconds confusion

// BUG: expecting seconds, got milliseconds
function displayAge(timestamp) {
  const now = Math.floor(Date.now() / 1000); // seconds
  const ageSeconds = now - timestamp; // if timestamp is ms, this is wrong
  return `${Math.floor(ageSeconds / 3600)} hours ago`;
}

// If someone passes Date.now() (ms) instead of Date.now()/1000 (s):
// ageSeconds = ~1.7 trillion, shows "470 million hours ago"

Always document whether a timestamp field is seconds or milliseconds. Add the unit to variable names: createdAtSec / createdAtMs.

Timestamp formats in APIs and databases

ISO 8601

Most modern APIs use ISO 8601 format instead of raw integers:

2024-05-11T00:00:00Z           (UTC)
2024-05-11T00:00:00+00:00      (UTC with explicit offset)
2024-05-10T20:00:00-04:00      (EDT)
2024-05-11T00:00:00.000Z       (with milliseconds)

ISO 8601 is human-readable and unambiguous. The downside: slower to compare and sort than integer timestamps (requires string parsing). Most databases index integers faster than strings.

Database timestamp types

DatabaseTypeStorageNotes
PostgreSQLTIMESTAMPTZ8 bytesAlways UTC internally; best practice
PostgreSQLTIMESTAMP8 bytesNo timezone info — avoid
MySQLDATETIME8 bytesStores as-is, no timezone
MySQLTIMESTAMP4 bytesStores as UTC, converts on read — 2038 risk
SQLiteTEXT/INTEGERVariableNo native type; store Unix int or ISO string

The Timestamp Converter tool

The Timestamp Converter converts between Unix timestamps (seconds and milliseconds) and human-readable dates in any timezone. Enter a timestamp to see the date, or enter a date to get the timestamp. It handles both directions and displays the result in UTC plus your local timezone.


Related posts

Related tool

Timestamp Converter

Convert Unix timestamps, epoch seconds/milliseconds, and ISO 8601 dates.

Written by Mian Ali Khalid. Part of the Dev Productivity pillar.