What is a Unix timestamp?

A Unix timestamp — also called an epoch timestamp or POSIX time — is a single integer that represents a moment in time as the number of seconds that have elapsed since 1970-01-01T00:00:00Z, a reference point known as the Unix epoch. That reference was chosen when the Unix operating system was being designed in the late 1960s and early 1970s at Bell Labs. It has since become the universal language for expressing time in software.

The most important property of a Unix timestamp is timezone independence. While a date string like "January 1, 2024, 9:00 AM" is ambiguous — it means completely different absolute moments depending on whether you are in New York, London, or Tokyo — the timestamp 1704067200 always and unambiguously refers to the exact same instant everywhere on Earth: midnight UTC on 1 January 2024. No timezone conversion is needed to compare two timestamps; you subtract one from the other and you have elapsed time in seconds.

This property makes Unix timestamps the backbone of virtually every computing system that needs to record or compare points in time. Relational databases store created_at and updated_at columns as integers or timestamp types backed by epoch arithmetic. Log aggregation systems like Elasticsearch and Splunk sort events by epoch time. Distributed systems use timestamps for ordering events, detecting clock drift, and implementing leader election algorithms. Every HTTP Date header, every JWT expiry, every cache TTL ultimately reduces to epoch arithmetic.

Event sourcing architectures — where the state of an application is derived entirely from an append-only log of events — depend on timestamps to establish causal order. Message queues, stream processors, and time-series databases all store event time as epoch values because integer comparisons are orders of magnitude faster than parsing and comparing formatted date strings. When milliseconds of throughput matter, the Unix timestamp wins every time.

Seconds vs milliseconds: the most common confusion

The single most common source of timestamp bugs in production software is confusing second-precision timestamps with millisecond-precision timestamps. The rule is simple: a Unix timestamp in seconds is a 10-digit number (e.g. 1704067200), while a millisecond timestamp is a 13-digit number (e.g. 1704067200000). If you ever see a timestamp and you are not sure which unit it is in, count the digits — ten digits means seconds, thirteen means milliseconds.

Different languages use different defaults, which is the root of the confusion. JavaScript's Date.now() returns milliseconds. Python's time.time() returns seconds as a float. Java's System.currentTimeMillis() returns milliseconds, matching JavaScript. Go's time.Now().Unix() returns seconds, while time.Now().UnixMilli() returns milliseconds. When you pass a JavaScript timestamp to a Python function that expects seconds, the value is 1,000 times too large, and your dates will land roughly in the year 56,000.

Silent double-division bug: A particularly insidious variant occurs when a millisecond timestamp is divided by 1,000 twice. The first division is correct and yields a valid seconds timestamp. The second division — perhaps because the value was passed through a function that "normalises" timestamps to seconds — produces a number around 1,704,067, which corresponds to January 1970. No exception is thrown. The timestamp silently lands in the past and corrupts whatever record it is stored in. Always verify the magnitude of a timestamp before operating on it.

The safest practice is to be explicit at every boundary. Name your variables createdAtSeconds or createdAtMs rather than a bare createdAt. Add a comment to any function that accepts a timestamp specifying which unit it expects. When reading timestamps from an external API, log the raw value and visually verify the digit count before storing it.

Common timestamp formats explained

Timestamps appear in many formats across different systems and protocols. Understanding which format a given context expects will save you hours of debugging. The table below covers the five formats you will encounter most often.

FormatExampleUsed in
Unix seconds1704067200Databases, server-side APIs, POSIX functions, JWT "exp" and "iat" fields, Redis TTLs, cron job scheduling
Unix milliseconds1704067200000JavaScript Date object, Java System.currentTimeMillis(), browser performance APIs, Elasticsearch, Kafka message timestamps
ISO 86012024-01-01T00:00:00ZREST API payloads, OpenAPI specs, logs (structured JSON logs), HTML datetime attributes, calendar applications
RFC 2822Mon, 01 Jan 2024 00:00:00 +0000Email headers (Date:), HTTP Date header, RSS/Atom feed timestamps, legacy mail clients
Local datetime01/01/2024 12:00:00 AMUI display only — platform and locale specific. Never use for storage or data exchange; contains no timezone information

ISO 8601 is the format recommended by most modern API style guides, including the Google API Design Guide and the OpenAPI Specification. Its unambiguous, sortable structure — where lexicographic ordering matches chronological ordering — makes it ideal for log storage and search. Always include the trailing Z suffix (indicating UTC) when serialising to ISO 8601; omitting it produces a "local time" string that different parsers may interpret differently.

The Year 2038 problem

In many legacy C and POSIX systems, Unix time is stored as a 32-bit signed integer. A signed 32-bit integer can hold values from −2,147,483,648 to 2,147,483,647. That upper limit corresponds to 2038-01-19T03:14:07Z. One second after that moment, the counter will overflow and wrap to its minimum value, causing any system still using 32-bit time to interpret the date as December 13, 1901 — a replay of the Y2K problem, but potentially more severe because many affected systems are deeply embedded.

The systems most at risk are embedded Linux devices — industrial controllers, legacy routers, medical devices, and automotive firmware that were shipped with 32-bit kernels and may never receive an update. Legacy C applications that use the time_t type on 32-bit platforms are similarly affected. MySQL's TIMESTAMP type was historically limited to the 2038 range (though modern versions use 64-bit storage). File systems that store modification times as 32-bit epoch values, such as older ext2/ext3 variants, will also be affected.

Modern 64-bit systems completely eliminate this issue. A 64-bit signed integer can represent timestamps up to roughly 292 billion years from the epoch — comfortably beyond any reasonable planning horizon. Linux on 64-bit hardware switched to 64-bit time_t decades ago. All modern databases — PostgreSQL, MySQL 8+, SQLite, MongoDB — use 64-bit time storage. If you are building new software today, you should use 64-bit integers for all timestamp storage and never use 32-bit time_t directly in C/C++ code. The problem is not academic: organisations with long-lived embedded systems should audit them for 32-bit time dependencies before 2038.

Best practices for timestamps in software

Consistent timestamp handling across a codebase prevents entire categories of bugs. These are the practices adopted by teams that have learned these lessons the hard way.

Always store UTC

Every timestamp stored in a database, message queue, or log should be in UTC. Storing local time in a database is one of the most common sources of subtle, hard-to-reproduce bugs — especially around daylight saving time transitions. UTC has no ambiguous hours and no clock shifts.

Use ISO 8601 for API payloads

When exchanging timestamps over HTTP or in JSON, use ISO 8601 with explicit UTC offset: 2024-01-01T00:00:00Z. It is human-readable, unambiguous, and parseable by every modern date library in every language without custom format strings.

Use 64-bit integers for storage

Never store Unix timestamps in 32-bit integers. Use BIGINT in SQL, int64 in Go/Rust/C, long in Java, or number in JavaScript (which uses 64-bit floats and can safely represent all epoch values well past the year 9999).

Never store local time in databases

A timestamp like "2024-03-10 02:30:00" in the America/New_York timezone is ambiguous — it could refer to two different UTC moments because of the spring DST gap. Storing it as a UTC epoch or UTC ISO string makes it unambiguous.

Display local time only at the UI layer

Convert UTC timestamps to the user's local timezone only at the point of display, using the browser's Intl API or a library like date-fns. Keep every layer below the UI — database, API, business logic — in UTC.

If you frequently work with time durations alongside timestamps, the Time Converter tool on this site lets you instantly convert between seconds, minutes, hours, days, and weeks — useful for setting cache TTLs, JWT expiry windows, and retry back-off limits.

How to get the current timestamp in different languages

The table below is a quick-reference cheat sheet for getting the current Unix timestamp — in both seconds and milliseconds — across the most common programming languages. Every snippet returns an integer; fractional seconds are stripped where relevant.

LanguageSecondsMilliseconds
JavaScriptMath.floor(Date.now() / 1000)Date.now()
Pythonint(time.time())int(time.time() * 1000)
Gotime.Now().Unix()time.Now().UnixMilli()
RustSystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis()
JavaInstant.now().getEpochSecond()System.currentTimeMillis()
PHPtime()(int)(microtime(true) * 1000)
RubyTime.now.to_i(Time.now.to_f * 1000).to_i
SQL (MySQL)UNIX_TIMESTAMP()ROUND(UNIX_TIMESTAMP(NOW(3)) * 1000)
SQL (PostgreSQL)EXTRACT(EPOCH FROM NOW())::BIGINT(EXTRACT(EPOCH FROM NOW()) * 1000)::BIGINT
C# / .NETDateTimeOffset.UtcNow.ToUnixTimeSeconds()DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()

Note that Rust requires importing std::time::{ SystemTime, UNIX_EPOCH }, and Python requires import time at the top of the file. In Go, UnixMilli() was added in Go 1.17; for older versions use time.Now().UnixNano() / int64(time.Millisecond). The SQL variants assume the server clock is set to UTC, which it always should be in production environments.

FAQ

Common questions

What is a Unix timestamp?

A Unix timestamp (also called epoch time or POSIX time) is the number of seconds that have elapsed since 00:00:00 UTC on 1 January 1970 — the "Unix epoch". It is a timezone-independent, single-integer representation of any moment in time, making it ideal for storage, sorting, and arithmetic in software systems.

What is the difference between seconds and milliseconds timestamps?

Unix timestamps in seconds are 10 digits long (e.g. 1704067200 for 2024-01-01). Millisecond timestamps are 13 digits long (e.g. 1704067200000) and are used in JavaScript (Date.now()), Java, and many APIs. This tool auto-detects which format you've entered based on the number of digits. You can also explicitly select the unit.

What output formats does this converter show?

The converter shows: ISO 8601 (2024-01-01T00:00:00Z — the international standard), RFC 2822 (Mon, 01 Jan 2024 00:00:00 +0000 — used in email headers), UTC date and time, your local date and time in your browser's timezone, relative time (e.g. "3 days ago"), and the day of week.

How do I get the current Unix timestamp?

Click the "Now" button to instantly load the current timestamp. The displayed values update in real time while "Now" is active. In code: JavaScript uses Date.now() for milliseconds or Math.floor(Date.now()/1000) for seconds; Python uses time.time(); Go uses time.Now().Unix().

What is the maximum date a Unix timestamp can represent?

A 32-bit signed integer can store timestamps up to 2,147,483,647 — which corresponds to 2038-01-19T03:14:07Z. This is the "Year 2038 problem". Modern systems use 64-bit integers which can represent dates billions of years into the future. This tool uses JavaScript's 64-bit floating-point numbers, so it handles any practical date range.

Can I convert a human-readable date to a Unix timestamp?

Yes. Use the date/time input fields on the right side of the converter. Select a date and time and the corresponding Unix timestamp (in both seconds and milliseconds) is shown instantly. The input treats the entered time as your local timezone unless you explicitly enter a UTC offset.

Why do different programming languages give different timestamps for the same moment?

They shouldn't if implemented correctly — Unix time is timezone-independent. Common sources of discrepancy: JavaScript's Date uses milliseconds while most others use seconds; local time vs UTC confusion; or clock skew between systems. Always store timestamps in UTC and convert to local time only at the display layer.

What is ISO 8601 and why is it preferred?

ISO 8601 is the international standard for date and time representation (e.g. 2024-01-15T09:30:00Z). The trailing "Z" means UTC. It is unambiguous, sortable lexicographically, and universally parseable by every major programming language and database. It is the recommended format for APIs, logs, and data exchange.

More in Code & Dev