Time guide ยท Unix timestamps
One number.
One moment.
Every time zone.
A Unix timestamp is the number of seconds that have passed since midnight UTC on 1 January 1970. It's how databases, logs, JWTs, APIs and operating systems record "when" without arguing about time zones or date formats. Here's how to read one, spot the seconds-vs-milliseconds trap, and convert it in any language. ๐
1718352000 โ Unix seconds 1718352000000 โ Unix milliseconds 2024-06-14T08:00:00Z โ ISO 8601, UTC (13:30 in India, 04:00 in New York)
Also called: epoch time, POSIX time, Unix time, or just "epoch". The starting point โ 1970-01-01T00:00:00Z โ is the Unix epoch, and it's timestamp 0. Moments before it are negative numbers.
02 ยท Exactly what it counts
โฑ๏ธ The definition, precisely
Unix time counts seconds since 1970-01-01 00:00:00 UTC, with one important simplification: every day is treated as exactly 86,400 seconds. Leap seconds โ the occasional extra second added to UTC to keep it aligned with the Earth's rotation โ are simply not counted.
โ What that buys you
Date arithmetic is trivial. Midnight UTC on any day is a multiple of 86,400. "One day later" is + 86400. Converting to a calendar date needs no leap-second table.
๐ค What it costs
Unix time isn't a perfect count of elapsed physical seconds. Around a leap second, systems either repeat a second or "smear" it across several hours. For almost all application code, this never matters.
๐ Handy reference points
| Timestamp | UTC date & time | Why it's notable |
|---|---|---|
| 0 | 1970-01-01 00:00:00 | The epoch |
| 86400 | 1970-01-02 00:00:00 | Exactly one day |
| 1000000000 | 2001-09-09 01:46:40 | First 10-digit timestamp |
| 1767225600 | 2026-01-01 00:00:00 | Start of 2026 |
| 2147483647 | 2038-01-19 03:14:07 | Largest signed 32-bit value โ see the 2038 problem |
| 9999999999 | 2286-11-20 17:46:39 | Last 10-digit timestamp |
03 ยท The most common bug
๐ข Seconds vs milliseconds
Classic Unix tools, C, PHP, Python's time.time(), most SQL functions and JWT claims like exp use seconds. JavaScript's Date, Java's System.currentTimeMillis() and many logging and analytics systems use milliseconds. Mix them up and you get dates in January 1970 or tens of thousands of years in the future.
| Digits (for present-day dates) | Unit | Example |
|---|---|---|
| 10 | Seconds | 1718352000 |
| 13 | Milliseconds | 1718352000000 |
| 16 | Microseconds | 1718352000000000 |
| 19 | Nanoseconds | 1718352000000000000 |
The quick test: count the digits. Ten digits is seconds for any date between September 2001 and November 2286; thirteen is milliseconds over the same span. The rule breaks down for dates near 1970, where timestamps are short โ so when a value comes from an unfamiliar API, check the docs rather than guessing.
The symptom to recognise: a date showing as 20 January 1970 almost always means seconds were treated as milliseconds (1.7 billion ms is about 20 days). A year in the tens of thousands means the reverse.
04 ยท Where local time fits in
๐ Time zones & ISO 8601
A Unix timestamp has no time zone. It identifies a single instant that is the same everywhere on Earth. Time zones only appear when you display that instant: 1718352000 is 08:00 UTC โ which is 09:00 in London (British Summer Time), 13:30 in India (UTC+05:30) and 04:00 in New York (UTCโ04:00 in June).
-
๐พ Store the instant
Save timestamps in UTC โ as a Unix number or a UTC date-time column. Never store "local time" without its offset.
-
๐ Compute in UTC
Durations, comparisons and sorting all work directly on the number. Daylight-saving changes can't break them.
-
๐ฅ๏ธ Convert at the edge
Turn it into local time only when showing it to a person, using their time zone.
๐ Unix timestamp or ISO 8601?
ISO 8601 (and its stricter internet profile, RFC 3339) is the standard text format for dates: 2024-06-14T08:00:00Z, or with an offset, 2024-06-14T13:30:00+05:30. Both lines describe the same moment as 1718352000.
| What | Unix timestamp | ISO 8601 string |
|---|---|---|
| Readable by humans | No | Yes |
| Size | Compact number | ~20โ30 characters |
| Carries an offset | No โ always UTC by definition | Yes (Z or +05:30) |
| Unit ambiguity | Seconds or milliseconds? | None โ precision is visible |
| Sorting & maths | Plain number comparison | Sorts as text only if all values use the same offset and format |
| Typical use | Databases, JWTs, logs, caches | JSON APIs, config, anything a person reads |
A common, sensible split: use ISO 8601 with Z in public JSON APIs (see What is JSON?) and Unix numbers internally, where compactness and arithmetic matter.
05 ยท A deadline with a date
๐ฅ The Year 2038 problem
Many older systems store Unix time in a signed 32-bit integer. The largest value that type can hold is 2147483647 โ which is 2038-01-19 03:14:07 UTC. One second later, the value overflows and wraps round to -2147483648, which those systems read as 1901-12-13 20:45:52 UTC.
Modern 64-bit operating systems, languages and databases already use 64-bit time, so most application code is fine. The risk sits in the places people forget:
- Embedded devices and firmware with 32-bit clocks that will still be in service in 2038.
- Database columns โ MySQL's
TIMESTAMPtype, for example, has a range that ends at 2038-01-19 03:14:07 UTC.DATETIMEor a 64-bit integer column avoids it. - File formats and protocols that define a 32-bit time field.
- Your own code that casts a timestamp to a 32-bit
int. Uselong/int64.
It can bite before 2038. Anything that calculates dates in the future โ a 20-year mortgage schedule, a long-lived certificate, a far-off expiry date โ crosses the limit today.
06 ยท In your code
๐ ๏ธ Getting & converting timestamps
Date.now(); // milliseconds: 1718352000000 Math.floor(Date.now() / 1000); // seconds: 1718352000 new Date(1718352000 * 1000).toISOString(); // "2024-06-14T08:00:00.000Z" Date.parse("2024-06-14T08:00:00Z") / 1000; // 1718352000
long secs = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); long ms = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); DateTimeOffset when = DateTimeOffset.FromUnixTimeSeconds(1718352000); // 2024-06-14 08:00:00 +00:00 var ist = TimeZoneInfo.FindSystemTimeZoneById("Asia/Kolkata"); DateTimeOffset local = TimeZoneInfo.ConvertTime(when, ist); // 13:30 +05:30
import time from datetime import datetime, timezone int(time.time()) # seconds, now datetime.fromtimestamp(1718352000, tz=timezone.utc) # 2024-06-14 08:00:00+00:00 datetime(2024, 6, 14, 8, tzinfo=timezone.utc).timestamp() # 1718352000.0 # โ ๏ธ a naive datetime (no tzinfo) is treated as *local* time by .timestamp()
-- PostgreSQL SELECT extract(epoch FROM now()); -- now, as seconds SELECT to_timestamp(1718352000); -- โ timestamptz -- MySQL SELECT UNIX_TIMESTAMP(); SELECT FROM_UNIXTIME(1718352000); -- shown in the session time zone -- SQL Server SELECT DATEDIFF_BIG(SECOND, '1970-01-01', SYSUTCDATETIME()); SELECT DATEADD(SECOND, 1718352000, '1970-01-01'); -- SQLite SELECT strftime('%s', 'now'); SELECT datetime(1718352000, 'unixepoch');
date +%s # seconds, now date +%s%3N # milliseconds (GNU date) date -u -d @1718352000 # โ date, GNU/Linux date -u -r 1718352000 # โ date, macOS/BSD date -u -d "2024-06-14T08:00:00Z" +%s # date โ seconds (GNU)
Just need the answer? Paste any value into the Timestamp Converter โ it detects seconds vs milliseconds and shows UTC, local time and ISO 8601 together. To count days or hours between two dates, use the Date Difference Calculator.