DD
DevDash
timeepochjavascriptpython

Unix Epoch Timestamps: Everything You Need to Know

It's 1770422400. Do you know what time it is?

If you work with APIs, databases, or logs, you deal with Unix epoch timestamps constantly. They're the lingua franca of time in computing. Let's make sure you actually understand them.

What is epoch time?

The Unix epoch is January 1, 1970, 00:00:00 UTC. An epoch timestamp is simply the number of seconds that have elapsed since that moment.

TimestampDate
0Jan 1, 1970 00:00:00 UTC
1000000000Sep 9, 2001 01:46:40 UTC
1700000000Nov 14, 2023 22:13:20 UTC
1770422400Feb 7, 2026 08:00:00 UTC
2000000000May 18, 2033 03:33:20 UTC

Negative values represent dates before 1970. For example, -86400 is December 31, 1969.

Why 1970? Unix was being developed at Bell Labs in the late 1960s. The original epoch was January 1, 1971, but it was later moved back to 1970 for a rounder number. The choice was pragmatic, not profound.

Seconds vs. milliseconds: the common trap

This is the single most common source of epoch-related bugs. Some systems use seconds, others use milliseconds.

Seconds:      1770422400
Milliseconds: 1770422400000

If you pass milliseconds to a function expecting seconds, you'll get a date thousands of years in the future. If you pass seconds where milliseconds are expected, you'll get January 1970.

Who uses what:

SystemUnit
Unix/Linux time()Seconds
Python time.time()Seconds (float)
JavaScript Date.now()Milliseconds
Java System.currentTimeMillis()Milliseconds
PostgreSQL EXTRACT(EPOCH FROM ...)Seconds
MySQL UNIX_TIMESTAMP()Seconds
API common practiceUsually seconds

The rule of thumb: if the number is 10 digits, it's seconds. If it's 13 digits, it's milliseconds. In 2026, a seconds timestamp starts with 17, a milliseconds timestamp starts with 177.

Getting the current epoch

JavaScript

// Milliseconds (native)
const ms = Date.now();
console.log(ms); // 1770422400000

// Seconds const sec = Math.floor(Date.now() / 1000); console.log(sec); // 1770422400

Python

import time
from datetime import datetime

Seconds (float)

epoch = time.time() print(epoch) # 1770422400.123456

Seconds (integer)

epoch_int = int(time.time()) print(epoch_int) # 1770422400

Bash

# Seconds
date +%s

1770422400

Milliseconds (GNU coreutils)

date +%s%3N

1770422400123

macOS (no native milliseconds, use Python)

python3 -c "import time; print(int(time.time() * 1000))"

Go

import "time"

// Seconds epoch := time.Now().Unix()

// Milliseconds epochMs := time.Now().UnixMilli()

SQL

-- PostgreSQL
SELECT EXTRACT(EPOCH FROM NOW());

-- MySQL SELECT UNIX_TIMESTAMP();

-- SQLite SELECT strftime('%s', 'now');

Converting epoch to human-readable dates

JavaScript

// From seconds
const date = new Date(1770422400 * 1000); // multiply by 1000!
console.log(date.toISOString());
// "2026-02-07T08:00:00.000Z"

console.log(date.toLocaleString('en-US', { timeZone: 'America/New_York' })); // "2/7/2026, 3:00:00 AM"

Python

from datetime import datetime, timezone

UTC

dt = datetime.fromtimestamp(1770422400, tz=timezone.utc) print(dt.isoformat())

"2026-02-07T08:00:00+00:00"

Local time

dt_local = datetime.fromtimestamp(1770422400) print(dt_local)

Bash

# GNU/Linux
date -d @1770422400

Sat Feb 7 08:00:00 UTC 2026

macOS

date -r 1770422400

Converting human-readable dates to epoch

JavaScript

const epoch = Math.floor(new Date('2026-02-07T08:00:00Z').getTime() / 1000);
console.log(epoch); // 1770422400

Python

from datetime import datetime, timezone

dt = datetime(2026, 2, 7, 8, 0, 0, tzinfo=timezone.utc) epoch = int(dt.timestamp()) print(epoch) # 1770422400

Bash

# GNU/Linux
date -d "2026-02-07T08:00:00Z" +%s

macOS

date -j -f "%Y-%m-%dT%H:%M:%S" "2026-02-07T08:00:00" +%s

The Y2038 problem

On January 19, 2038, at 03:14:07 UTC, the Unix epoch timestamp will reach 2,147,483,647 -- the maximum value for a signed 32-bit integer. One second later, systems using 32-bit timestamps will overflow, potentially wrapping around to December 13, 1901.

2147483647 → Tue Jan 19 03:14:07 UTC 2038
2147483648 → ??? (overflow on 32-bit systems)

Is this a real problem? For most modern systems, no. 64-bit timestamps have been the default on Linux since the mid-2000s. A signed 64-bit epoch won't overflow until the year 292,277,026,596. Your code will be fine.

But embedded systems, IoT devices, old databases, and some file formats still use 32-bit timestamps. If you're working with any of these, it's worth checking. The Linux kernel completed its internal Y2038 remediation, but userspace code varies.

Epoch timestamps in databases

Storing timestamps

Most databases offer both epoch integers and native timestamp types. Use native types when possible:

-- Prefer this
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()

-- Over this created_at BIGINT DEFAULT EXTRACT(EPOCH FROM NOW())

Native timestamp types give you timezone handling, comparison operators, and date math for free. Epoch integers are useful for interoperability with external systems.

Indexing

Epoch integers are slightly more efficient to index than timestamps, but the difference is negligible for most applications. Don't optimize for this unless you're dealing with billions of rows.

Quick conversions

For quick conversions when you're debugging or reading logs, devdash.io/tools/epoch-converter lets you paste a timestamp and see the human-readable date instantly, or go the other direction. Handy when you're staring at a log full of 1770422400 values and need to know what happened when.

Common patterns

Generate a unique-ish ID:

const id = evt_${Date.now()}_${Math.random().toString(36).slice(2, 7)};
// "evt_1770422400123_k8f2j"

Check if a token is expired:

const isExpired = (exp) => Math.floor(Date.now() / 1000) > exp;

Calculate time ago:

function timeAgo(epochSeconds) {
  const diff = Math.floor(Date.now() / 1000) - epochSeconds;
  if (diff < 60) return ${diff}s ago;
  if (diff < 3600) return ${Math.floor(diff / 60)}m ago;
  if (diff < 86400) return ${Math.floor(diff / 3600)}h ago;
  return ${Math.floor(diff / 86400)}d ago;
}

Key takeaways

  • Epoch time = seconds since January 1, 1970 UTC
  • JavaScript uses milliseconds; most other systems use seconds
  • 10 digits = seconds, 13 digits = milliseconds
  • Always handle timezones explicitly -- fromtimestamp() without a timezone is a bug waiting to happen
  • Y2038 is real but mostly affects 32-bit embedded systems
  • Use native database timestamp types unless you have a specific reason for epoch integers

Related Tools

Want API access + no ads? Pro coming soon.