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/