webtrajans
en

Unix timestamps explained: epoch time, time zones and cron

A Unix timestamp is the number of seconds since 1 January 1970 UTC. It is time-zone-free, easy to compare and everywhere in software. Here is how to read, convert and schedule with it.

Updated: 5 min read

Behind almost every “created at” field, log line, API response and cookie expiry, there’s a plain integer: the Unix timestamp. It’s the simplest way for computers to agree on a moment in time, regardless of time zone, language or calendar. This guide explains what the number means, how to convert it reliably, the classic bugs (milliseconds, time zones, 2038) and how cron uses time to schedule jobs. Paste any timestamp into our Unix timestamp converter to see it as a date.

What a Unix timestamp is

Unix time (also called epoch time or POSIX time) counts seconds since 00:00:00 UTC on Thursday, 1 January 1970, the “Unix epoch”.

Timestamp UTC date and time
0 1970-01-01 00:00:00
1000000000 2001-09-09 01:46:40
1791417600 2026-10-08 00:00:00
1800000000 2027-01-15 08:00:00
2147483647 2038-01-19 03:14:07

Dates before 1970 are negative numbers. Unix time ignores leap seconds: every day is treated as exactly 86,400 seconds.

Why developers like it

  • Time-zone-free: one number represents the same instant everywhere.
  • Easy arithmetic: add 3,600 for an hour, 86,400 for a day.
  • Sortable and compact: compare two integers instead of parsing date strings.

Seconds vs milliseconds (and more)

Unit Digits today Example Used by
Seconds 10 1791460800 Unix/Linux, PHP, Python time.time() (float), most APIs
Milliseconds 13 1791460800000 JavaScript, Java, many JSON APIs
Microseconds 16 1791460800000000 PostgreSQL internals, some logging
Nanoseconds 19 1791460800000000000 Go UnixNano, high-resolution tracing

The most common bug is treating milliseconds as seconds, which produces a date tens of thousands of years in the future, or the reverse, which produces a date in January 1970.

Converting in code

// JavaScript (milliseconds)
const now = Math.floor(Date.now() / 1000);            // seconds
const d = new Date(1791460800 * 1000);
d.toISOString();                                       // "2026-10-08T12:00:00.000Z"
d.toLocaleString("en-GB", { timeZone: "Europe/London" });
# Python
from datetime import datetime, timezone
datetime.fromtimestamp(1791460800, tz=timezone.utc)    # 2026-10-08 12:00:00+00:00
int(datetime.now(timezone.utc).timestamp())
# Shell
date +%s                         # current timestamp
date -u -d @1791460800           # GNU/Linux
date -u -r 1791460800            # macOS/BSD
-- PostgreSQL
SELECT to_timestamp(1791460800);
SELECT extract(epoch FROM now());
-- MySQL
SELECT FROM_UNIXTIME(1791460800);
SELECT UNIX_TIMESTAMP();

Time zones: convert at the edges

A timestamp doesn’t have a time zone; the display does. 1791460800 is 12:00 UTC, 13:00 in London (BST), 08:00 in New York (EDT) and 21:00 in Tokyo, all at once.

Best practice:

  • Store UTC timestamps (or ISO 8601 strings with Z or an offset).
  • Convert to the user’s time zone only when displaying.
  • Use IANA zone names (Europe/London) so daylight saving time is handled; see our time zones guide.
  • Beware of “naive” date functions that silently use the server’s local time. Python’s datetime.fromtimestamp(ts) without tz and datetime.utcnow() (deprecated) are classic traps.

The year 2038 problem

Many older systems store Unix time in a signed 32-bit integer, whose maximum is 2,147,483,647. One second after 03:14:07 UTC on 19 January 2038, the value overflows to −2,147,483,648, which is interpreted as 13 December 1901.

Who might still be affected:

  • Embedded devices and industrial controllers with long lifespans.
  • Old 32-bit operating systems and C programs using a 32-bit time_t.
  • Database columns defined as 32-bit integers, and MySQL’s TIMESTAMP type, whose range ends in January 2038.
  • File formats and protocols with 32-bit time fields.

Modern 64-bit systems use 64-bit time, which lasts for billions of years. If you’re designing a schema today, use 64-bit integers or native date/time types. Some systems already hit the bug when computing dates more than 12 years ahead, such as long mortgages or certificate expiry dates.

Cron: scheduling with time

Cron runs jobs on a schedule on Unix-like systems, and the same syntax is used by many cloud schedulers and CI pipelines. A standard cron expression has five fields:

┌───────── minute (0–59)
│ ┌─────── hour (0–23)
│ │ ┌───── day of month (1–31)
│ │ │ ┌─── month (1–12)
│ │ │ │ ┌─ day of week (0–6, Sunday = 0; 7 is also Sunday on many systems)
│ │ │ │ │
* * * * *  command
Expression Meaning
0 * * * * Every hour, on the hour
*/15 * * * * Every 15 minutes
30 2 * * * Every day at 02:30
0 9 * * 1-5 09:00 Monday to Friday
0 0 1 * * Midnight on the 1st of every month
0 6 * * 0 06:00 every Sunday

Special characters: * any value, , list (1,15), - range (1-5), / step (*/10).

Cron gotchas

  • Time zone: cron uses the server’s time zone unless configured otherwise. Many cloud schedulers default to UTC.
  • Daylight saving time: a job at 01:30 may run twice or not at all on clock-change nights. Schedule critical jobs outside 01:00–03:00 local time, or use UTC.
  • Day of month and day of week together: in standard cron, if both are restricted, the job runs when either matches.
  • Different dialects: Quartz and some platforms add a seconds field or use ?.

Our cron expression generator builds and explains expressions so you can double-check them.

Checklist

  • Know whether a timestamp is in seconds or milliseconds.
  • Store times in UTC; convert to local time for display.
  • Use time-zone-aware functions and IANA zone names.
  • Use 64-bit integers or native date types to avoid the 2038 problem.
  • Check cron’s time zone and avoid DST transition hours for critical jobs.

Storing timestamps in JSON? See our JSON basics guide.

Frequently asked questions

What is the Unix epoch?

The epoch is 00:00:00 UTC on 1 January 1970. A Unix timestamp counts the seconds elapsed since then, ignoring leap seconds, so 0 is the epoch and 1,800,000,000 is 08:00:00 UTC on 15 January 2027.

How do I tell if a timestamp is in seconds or milliseconds?

Count the digits. Present-day timestamps in seconds have 10 digits (about 1.79 billion in late 2026); in milliseconds they have 13 digits. JavaScript's Date.now() returns milliseconds.

What is the year 2038 problem?

Systems that store Unix time as a signed 32-bit integer overflow after 2,147,483,647 seconds, which is 03:14:07 UTC on 19 January 2038. Modern systems use 64-bit time, but old embedded devices, databases and file formats may still be affected.

Do Unix timestamps have a time zone?

No. A timestamp is the same instant everywhere in the world. Time zones only matter when you convert it to a human-readable local date and time.

Related guides