X Xerobit

Timestamp to Date — Convert Unix Timestamps to Human-Readable Dates

Converting a Unix timestamp to a date requires knowing whether it's seconds or milliseconds and what timezone to display in. Here's how to convert timestamps in code and why...

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

Converting a Unix timestamp to a human-readable date requires two decisions: is the timestamp in seconds or milliseconds, and what timezone should the output be in? Get either wrong and the date is off.

Use the Timestamp Converter to convert any Unix timestamp to a date in any timezone.

Identifying seconds vs milliseconds timestamps

Unix timestamps are either:

  • Seconds: ~10 digits, starting with 1 for recent dates (~1.7 billion for 2024)
  • Milliseconds: ~13 digits, starting with 1 for recent dates (~1.7 trillion for 2024)
1715414400       = seconds → 2024-05-11 00:00:00 UTC
1715414400000    = milliseconds → same date/time

The digits test:

  • 10 digits → seconds
  • 13 digits → milliseconds
  • 16+ digits → microseconds or nanoseconds

If you convert a milliseconds timestamp as seconds, you’ll get a date ~50,000 years in the future. If you convert a seconds timestamp as milliseconds, you’ll get a date in 1970.

Converting in code

JavaScript

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

// Milliseconds to Date (no multiplication needed):
const tsMs = 1715414400000;
const dateMs = new Date(tsMs);
console.log(dateMs.toISOString()); // "2024-05-11T00:00:00.000Z"

// Format in a specific timezone:
const options = {
  timeZone: 'America/New_York',
  year: 'numeric', month: 'long', day: 'numeric',
  hour: '2-digit', minute: '2-digit'
};
console.log(date.toLocaleString('en-US', options));
// "May 10, 2024, 08:00 PM" (EDT = UTC-4)

// Quick check what timestamp is:
function tsToISO(ts) {
  // Auto-detect seconds vs milliseconds:
  const ms = ts < 1e12 ? ts * 1000 : ts;
  return new Date(ms).toISOString();
}

Python

from datetime import datetime, timezone
from zoneinfo import ZoneInfo  # Python 3.9+

ts = 1715414400

# To UTC:
dt_utc = datetime.fromtimestamp(ts, tz=timezone.utc)
print(dt_utc.isoformat())  # '2024-05-11T00:00:00+00:00'

# To specific timezone:
dt_ny = datetime.fromtimestamp(ts, tz=ZoneInfo('America/New_York'))
print(dt_ny.isoformat())   # '2024-05-10T20:00:00-04:00' (EDT)
print(dt_ny.strftime('%B %d, %Y %I:%M %p %Z'))
# 'May 10, 2024 08:00 PM EDT'

# Milliseconds timestamp:
ts_ms = 1715414400000
dt = datetime.fromtimestamp(ts_ms / 1000, tz=timezone.utc)
print(dt.isoformat())  # '2024-05-11T00:00:00+00:00'

PHP

// Seconds timestamp:
$ts = 1715414400;
$dt = new DateTime('@' . $ts);
$dt->setTimezone(new DateTimeZone('UTC'));
echo $dt->format('Y-m-d H:i:s T');  // 2024-05-11 00:00:00 UTC

// With timezone:
$dt->setTimezone(new DateTimeZone('America/New_York'));
echo $dt->format('Y-m-d H:i:s T');  // 2024-05-10 20:00:00 EDT

SQL

-- PostgreSQL: timestamp to human-readable
SELECT to_timestamp(1715414400) AT TIME ZONE 'UTC';
-- 2024-05-11 00:00:00+00

SELECT to_timestamp(1715414400) AT TIME ZONE 'America/New_York';
-- 2024-05-10 20:00:00

-- MySQL:
SELECT FROM_UNIXTIME(1715414400);
-- (in server timezone)

SELECT CONVERT_TZ(FROM_UNIXTIME(1715414400), '+00:00', 'America/New_York');

Common timestamp conversions

Unix = 0            → 1970-01-01 00:00:00 UTC (the epoch)
Unix = 1000000000   → 2001-09-09 01:46:40 UTC
Unix = 1234567890   → 2009-02-13 23:31:30 UTC
Unix = 1700000000   → 2023-11-14 22:13:20 UTC
Unix = 1715414400   → 2024-05-11 00:00:00 UTC
Unix = 2000000000   → 2033-05-18 03:33:20 UTC
Unix = 2147483647   → 2038-01-19 03:14:07 UTC (32-bit max!)

The 2038 problem in context

The maximum 32-bit signed integer is 2,147,483,647, which corresponds to January 19, 2038. Systems storing timestamps as 32-bit integers will overflow on that date.

Modern 64-bit systems use 64-bit timestamps, which can represent dates until approximately year 292,277,026,596. For any new system, always use 64-bit (BIGINT) storage for timestamps.

In databases:

  • MySQL TIMESTAMP type: 32-bit, limited to 2038. Use DATETIME or BIGINT instead
  • PostgreSQL TIMESTAMPTZ: 64-bit, no 2038 problem
  • SQLite: stores as INTEGER (64-bit) or TEXT

Displaying timestamps for users

Always display in the user’s local timezone. A Unix timestamp is always UTC internally; the display timezone is a presentation choice.

// Best practice: store UTC timestamp, display in user timezone
const timestamp = 1715414400;
const date = new Date(timestamp * 1000);

// User's local time (automatic):
date.toLocaleString();  // "May 10, 2024, 8:00:00 PM" (in New York browser)

// Or let the user pick their timezone:
date.toLocaleString('en-US', { timeZone: userSettings.timezone });

Relative time is often better than absolute for recent timestamps:

function relativeTime(ts) {
  const seconds = Math.floor(Date.now() / 1000) - ts;
  if (seconds < 60) return 'just now';
  if (seconds < 3600) return `${Math.floor(seconds/60)} minutes ago`;
  if (seconds < 86400) return `${Math.floor(seconds/3600)} hours ago`;
  return `${Math.floor(seconds/86400)} days ago`;
}

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.