Unix Timestamps: How Epoch Time Works and How to Convert It

1 6 109
calendar_todayschedule5 min read

Unix timestamps appear constantly in API responses, log files, database records, and JavaScript code. Here's how they work, why they exist, and how to convert them in every common language.

What is a Unix timestamp?

A Unix timestamp (also called epoch time or POSIX time) is the number of seconds that have elapsed since January 1, 1970, 00:00:00 UTC. This reference point is called the Unix epoch.

Current timestamp: approximately 1,748,600,000 (changes every second).

Why 1970? When Unix was developed at Bell Labs in the late 1960s, 1970 was a convenient recent reference point. A 32-bit signed integer could then represent dates from 1901 to 2038 — sufficient for the systems of that era.

For quick conversion between Unix timestamps and human-readable dates, a Unix timestamp converter shows the human-readable equivalent and relative time ("3 days ago") in real time.

Seconds vs milliseconds

This is the most common source of bugs.

| Language | Unit | Example |

|----------|------|---------|

| Python time.time() | Seconds (float) | 1748600000.123 |

| Python datetime | Seconds | 1748600000 |

| JavaScript Date.now() | Milliseconds | 1748600000123 |

| JavaScript Date.getTime() | Milliseconds | 1748600000123 |

| MySQL UNIX_TIMESTAMP() | Seconds | 1748600000 |

| PostgreSQL EXTRACT(epoch FROM now()) | Seconds (float) | 1748600000.123 |

| Linux date +%s | Seconds | 1748600000 |

JavaScript uses milliseconds. Every other common system uses seconds. The × 1000 / / 1000 conversion is the most frequent bug:

``javascript

// WRONG: creates date in year 1970 for seconds input

new Date(1748600000) // Jan 1, 1970 + 1.7 billion milliseconds

// CORRECT: multiply seconds by 1000 for JavaScript Date

new Date(1748600000 * 1000) // 2025-05-30 (correct)

`

JavaScript

`javascript
// Get current timestamp (milliseconds)


const ms = Date.now();


const msAlt = new Date().getTime();

// Convert to seconds (for APIs expecting seconds)

const sec = Math.floor(Date.now() / 1000);

// Timestamp to Date object

const d = new Date(1748600000 * 1000); // seconds → milliseconds

// Date to ISO string

d.toISOString() // "2025-05-30T10:13:20.000Z" (UTC)

d.toLocaleString() // Local timezone string

// Date to Unix timestamp (seconds)

Math.floor(d.getTime() / 1000)

// → 1748600000

// Format a timestamp

const date = new Date(1748600000 * 1000);

const formatted = new Intl.DateTimeFormat('en-US', {

year: 'numeric', month: 'long', day: 'numeric',

hour: '2-digit', minute: '2-digit', timeZone: 'UTC'

}).format(date);

// → "May 30, 2025 at 10:13 AM" (UTC)

`

Python

`python
import time


from datetime import datetime, timezone, timedelta

Current timestamp (float, seconds)

ts = time.time()

→ 1748600000.123

Current timestamp (integer seconds)

ts_int = int(time.time())

→ 1748600000

Timestamp to datetime (local timezone)

dt = datetime.fromtimestamp(1748600000)

print(dt)

→ 2025-05-30 10:13:20 (in your local timezone)

Timestamp to datetime (UTC) — recommended

dt_utc = datetime.fromtimestamp(1748600000, tz=timezone.utc)

print(dt_utc)

→ 2025-05-30 10:13:20+00:00

Datetime to timestamp

dt = datetime(2025, 5, 30, 10, 0, 0, tzinfo=timezone.utc)

ts = dt.timestamp()

→ 1748596800.0

Format

dt.strftime('%Y-%m-%d %H:%M:%S')

→ '2025-05-30 10:00:00'

Parse a timestamp string

ts_str = '2025-05-30T10:00:00Z'

dt = datetime.fromisoformat(ts_str.replace('Z', '+00:00'))

`

SQL

`sql
-- PostgreSQL


SELECT NOW(); -- timestamp with timezone


SELECT EXTRACT(epoch FROM NOW()); -- float seconds since epoch


SELECT TO_TIMESTAMP(1748600000); -- timestamp from epoch seconds


SELECT TO_TIMESTAMP(1748600000) AT TIME ZONE 'UTC';

-- Convert timestamp column to epoch

SELECT EXTRACT(epoch FROM created_at)::bigint FROM events;

-- Filter by epoch range

SELECT * FROM events

WHERE created_at BETWEEN TO_TIMESTAMP(1748500000) AND TO_TIMESTAMP(1748600000);

-- MySQL

SELECT UNIX_TIMESTAMP(); -- current timestamp as integer

SELECT UNIX_TIMESTAMP(created_at) FROM events; -- datetime to timestamp

SELECT FROM_UNIXTIME(1748600000); -- timestamp to datetime

SELECT FROM_UNIXTIME(1748600000, '%Y-%m-%d'); -- formatted

`

Timezone handling

Unix timestamps are always UTC. The conversion to a human-readable date is timezone-dependent.

Best practice: Store timestamps as Unix seconds (or UTC datetime) in the database. Convert to local time only for display, as close to the user as possible (ideally in the client's browser).

`javascript
// Display in user's local timezone (browser handles this automatically)


new Date(1748600000 * 1000).toLocaleString()

// Display in a specific timezone

new Intl.DateTimeFormat('en-US', {

timeZone: 'America/New_York',

dateStyle: 'full',

timeStyle: 'long'

}).format(new Date(1748600000 * 1000))

`

`python
Display in a specific timezone
from datetime import timezone


from zoneinfo import ZoneInfo # Python 3.9+

dt = datetime.fromtimestamp(1748600000, tz=timezone.utc)

dt_ny = dt.astimezone(ZoneInfo('America/New_York'))

print(dt_ny.strftime('%Y-%m-%d %H:%M %Z'))

→ '2025-05-30 06:13 EDT'

`

The Year 2038 problem

32-bit signed integers overflow at 2,147,483,647 — which corresponds to January 19, 2038, 03:14:07 UTC. After this, a 32-bit timestamp wraps to a large negative number representing 1901.

Modern 64-bit systems are safe until the year 292,277,026,596. The risk remains in:

  • Embedded systems with 32-bit processors
  • Legacy database columns using INT (4 bytes) for timestamps
  • Old 32-bit application code

For new code: always use BIGINT for timestamp storage in MySQL, TIMESTAMPTZ in PostgreSQL, and 64-bit integers in application code.

Relative time display

Showing "3 minutes ago" or "2 days ago" is more readable than exact timestamps for recent events:

<code>javascript <p>function relativeTime(ts) {</p> <p>const diff = (Date.now() / 1000) - ts;</p> <p>if (diff < 60) return 'just now';</p> <p>if (diff < 3600) return </code>${Math.floor(diff / 60)} minutes ago<code>;</p> <p>if (diff < 86400) return </code>${Math.floor(diff / 3600)} hours ago<code>;</p> <p>if (diff < 604800) return </code>${Math.floor(diff / 86400)} days ago<code>;</p> <p>return new Date(ts * 1000).toLocaleDateString();</p> <p>}</p> </code>`


The main pitfalls with Unix timestamps are the seconds/milliseconds distinction (mostly JavaScript) and timezone handling. Keeping timestamps in UTC throughout the backend and converting to local time only at the display layer eliminates most of the common bugs.

Originally published at https://snappytools.app/unix-timestamp-converter/

🔥 Join developers growing publicly
Share your knowledge, build in public, and grow your developer presence with a global community.

More Posts

I’m a Senior Dev and I’ve Forgotten How to Think Without a Prompt

Karol Modelskiverified - Mar 19

What Is SARIF and How Does It Help Security Tools Work Together?

Ganesh Kumar - Jul 4

How I Built a React Portfolio in 7 Days That Landed ₹1.2L in Freelance Work

Dharanidharan - Feb 9

TypeScript Complexity Has Finally Reached the Point of Total Absurdity

Karol Modelskiverified - Apr 23

Sovereign Intelligence: The Complete 25,000 Word Blueprint (Download)

Pocket Portfolio - Apr 1
chevron_left
2.4k Points116 Badges
101Posts
0Comments
SnappyTools builds free, fast, browser-based tools for developers, writers, and designers. No signup... Show more

Related Jobs

View all jobs →

Commenters (This Week)

2 comments
1 comment
1 comment

Contribute meaningful comments to climb the leaderboard and earn badges!