DeveloperTime

Unix Seconds vs Milliseconds

10-digit or 13-digit? A complete guide to Unix timestamp units — which languages use which, how to tell them apart, and how to avoid conversion bugs.

SecondsvsMilliseconds

TL;DR — Key Points

Seconds (10 digits)Current value ~1,748,000,000. Default in Python, Go, C, PHP, Ruby, PostgreSQL. POSIX standard. Smaller storage — fits in 4 bytes as 32-bit int.
Milliseconds (13 digits)Current value ~1,748,000,000,000. Default in JavaScript, Java, MongoDB. Required for sub-second precision. Always needs 64-bit storage.
Digit heuristic10 digits = seconds. 13 digits = milliseconds. Reliable until year 2286. Any other count is unusual.
Conversionseconds × 1,000 = milliseconds. milliseconds ÷ 1,000 = seconds (integer division). Simple but a common source of bugs when mixed.
Year 2038 problem32-bit signed int max = 2,147,483,647 = Jan 19, 2038 03:14:07 UTC. 64-bit integers are not affected — use 64-bit for all new systems.
Best practicePick one unit per system, document it in schema/column names, normalise at ingestion. Never mix units in the same column.

At a Glance

CriterionSecondsMilliseconds
Current value (2026)~1,748,000,000~1,748,000,000,000
Digit count10 digits13 digits
Precision1-second resolution1-millisecond resolution
Storage (integer)4 bytes (32-bit) or 8 bytes (64-bit)Always 8 bytes (64-bit)
JavaScript defaultNo — must divide Date.now() by 1000Yes — Date.now(), new Date().getTime()
Python defaultYes — time.time() (float), int(time.time())No — multiply by 1000
Java defaultNo — divide System.currentTimeMillis()Yes — System.currentTimeMillis()
Go defaultYes — time.Now().Unix()time.Now().UnixMilli() (Go 1.17+)
PostgreSQLYes — EXTRACT(EPOCH FROM …)Multiply epoch by 1000
MongoDBNoYes — BSON Date, ObjectId timestamp
Year 2038 riskYes, if stored as 32-bit intNo — requires 64-bit already

Language and Platform Defaults

Language / PlatformDefault UnitPrimary API
JavaScriptMillisecondsDate.now()
TypeScriptMillisecondsDate.now()
PythonSecondstime.time() → float
JavaMillisecondsSystem.currentTimeMillis()
GoSecondstime.Now().Unix()
C / C++Secondstime(NULL)
PHPSecondstime()
RubySecondsTime.now.to_i
RustSecondsSystemTime::UNIX_EPOCH.elapsed()
PostgreSQLSecondsEXTRACT(EPOCH FROM NOW())
MongoDBMillisecondsBSON Date / ObjectId
RedisMillisecondsTIME command (seconds + μs)

Quick Decision Guide

Use Seconds when…

  • Storing timestamps in PostgreSQL, MySQL, or SQLite
  • Python backend (time.time() is seconds by default)
  • C, C++, or Go applications (Unix() returns seconds)
  • POSIX-compliant systems and shell scripts
  • Storage-constrained environments where 4 bytes matters
  • Comparing with system time from Unix commands (date +%s)
  • HTTP headers like Last-Modified and Expires (RFC 7231 uses HTTP-date, often seconds-based)

Use Milliseconds when…

  • JavaScript or TypeScript — any front-end or Node.js code
  • Java applications (System.currentTimeMillis())
  • MongoDB documents and BSON dates
  • Browser APIs: setTimeout, setInterval, performance.now()
  • Web analytics and event tracking (sub-second ordering)
  • UI animation timing and requestAnimationFrame
  • High-frequency logs where multiple events occur per second

Deep Dive

Unix Seconds

Unix time in seconds is the original POSIX timestamp format — the number of seconds elapsed since the Unix Epoch (midnight UTC, January 1, 1970). It is the standard for all POSIX-compliant systems: C's time(NULL), Python's time.time(), Go's time.Now().Unix(), PHP's time(), Ruby's Time.now.to_i, and PostgreSQL's EXTRACT(EPOCH FROM …) all return seconds by default. The 10-digit length of current timestamps (~1,748,000,000 in mid-2026) is the primary identification heuristic.

The 32-bit integer limit (2,147,483,647) will overflow on January 19, 2038 at 03:14:07 UTC — the Year 2038 problem. Any system still using 32-bit signed integers for Unix timestamps will wrap to negative values representing December 1901. Most modern systems already use 64-bit integers which extend the range to approximately the year 292 billion. Legacy firmware and embedded systems remain at risk.

Storage advantage: a 32-bit integer uses 4 bytes vs 8 bytes for a 64-bit integer. For billions of rows, this can matter. PostgreSQL's TIMESTAMP WITH TIME ZONE type handles this internally and is generally preferred over raw integer seconds for new schema design.

Unix Milliseconds

Unix time in milliseconds is the number of milliseconds since the same Unix Epoch. The current value in mid-2026 is approximately 1,748,000,000,000 — 13 digits, always requiring 64-bit storage. JavaScript natively uses milliseconds for all time operations: Date.now() returns milliseconds, new Date(ms) accepts milliseconds, setTimeout(fn, ms) counts in milliseconds. Java's System.currentTimeMillis() and Instant.now().toEpochMilli() return milliseconds. MongoDB's BSON Date type stores milliseconds.

The 13-digit heuristic is reliable: any 13-digit integer in a timestamp context is almost certainly Unix milliseconds. The conversion is exact: multiply seconds by 1,000. Divide milliseconds by 1,000 for seconds (use integer division; the remainder is the sub-second milliseconds component).

For analytics and high-frequency logging, milliseconds allow correct ordering of up to 1,000 events per second. In practice, if two events share the same millisecond, a secondary sort key (sequence number or UUID) is still needed for total ordering.

Real-World Patterns

The JavaScript Ecosystem

Every time-related API in JavaScript natively uses milliseconds. Date.now() returns milliseconds since epoch. new Date(1716451200000) expects milliseconds. setTimeout(fn, 3000) waits 3,000 milliseconds (3 seconds). performance.now() returns floating-point milliseconds since page load. The implication: if you receive a timestamp from a JavaScript front-end, assume milliseconds unless documented otherwise. When sending timestamps to a JavaScript front-end from a Python or Go backend, multiply seconds by 1,000 before serialisation, or send ISO 8601 strings and let the JS Date parser handle the conversion.

Python + PostgreSQL Backend Stack

Python's time.time() returns a floating-point number of seconds (e.g., 1748000000.123456). PostgreSQL's EXTRACT(EPOCH FROM timestamp) also returns seconds as a float. This makes the Python/PostgreSQL stack naturally second-oriented. However, Python's datetime module stores microseconds internally (datetime.datetime has a microsecond field). When interfacing between Python and JavaScript — a common full-stack pattern — the conversion layer must multiply by 1,000 outbound and divide by 1,000 inbound. SQLAlchemy and Django ORM handle this automatically when using proper TIMESTAMP column types; raw SQL queries returning epoch values require manual conversion.

Mixed Systems and Conversion Bugs

The most common timestamp bug in distributed systems: a service emitting seconds, a consumer expecting milliseconds (or vice versa), with no validation. The result is a date 554 years in the future (seconds read as milliseconds) or a date in January 1970 (milliseconds read as seconds and landing near the epoch). Both are recognisable — any timestamp showing a date before 1971 or after 2200 in production data is almost always a unit mismatch. Defensive code should validate: seconds timestamps must be between 1,000,000,000 and 9,999,999,999; milliseconds timestamps must be between 1,000,000,000,000 and 9,999,999,999,999.

High-Frequency Analytics and Logging

At scale, multiple events arrive within the same second — page views, clicks, API calls, log lines. Sorting events stored with second precision is ambiguous: 50 events with the same timestamp cannot be chronologically ordered. Millisecond precision allows correct ordering of up to 1,000 events per second. Platforms like Datadog, Splunk, Elasticsearch, and Cloudwatch all store log events with millisecond timestamps. For financial trading systems, microseconds (10^−6) or nanoseconds (10^−9) are required — timestamps like 1748000000123456789 (nanoseconds, 19 digits) are common in market data feeds.

Which should you use?

Match the unit to your runtime. Seconds for Python, Go, C, PostgreSQL, and POSIX-native stacks. Milliseconds for JavaScript, Java, MongoDB, and any browser-facing code.

The cardinal rule: pick one unit per system and document it. If you receive timestamps from a JavaScript frontend and store them in PostgreSQL, normalise to seconds (or use ISO 8601 strings and let the DB handle conversion). Never store seconds and milliseconds in the same column — the bugs are subtle, the damage is real, and sorting will silently produce wrong results.

Decision Checklist

ScenarioUse
JavaScript Date.now() or new Date().getTime()Milliseconds
Python time.time() or int(time.time())Seconds
Java System.currentTimeMillis()Milliseconds
Go time.Now().Unix()Seconds
PostgreSQL EXTRACT(EPOCH FROM …)Seconds
MongoDB BSON Date or ObjectIdMilliseconds
Unix shell: date +%sSeconds
Browser setTimeout / setInterval argumentMilliseconds
Sorting multiple events within the same secondMilliseconds
Storage-constrained 32-bit embedded systemSeconds (with Year 2038 awareness)
HTTP Cache-Control max-age valueSeconds (RFC standard)
Web analytics event ingestion pipelineMilliseconds

Frequently Asked Questions

How do I tell Unix seconds from milliseconds just by looking at the number?

Count the digits. A Unix timestamp in seconds currently has 10 digits (the current value in mid-2026 is approximately 1,748,000,000). A Unix timestamp in milliseconds currently has 13 digits (approximately 1,748,000,000,000). This heuristic works reliably until the year 2286 when seconds will reach 11 digits. Quick rule: 10 digits = seconds, 13 digits = milliseconds. Any other digit count (9 digits, 11 digits, 12 digits) usually indicates a different epoch, a truncated value, or a bug.

What is the Unix Epoch?

The Unix Epoch is midnight UTC on January 1, 1970 — specifically 1970-01-01T00:00:00Z. All Unix timestamps count time elapsed since this reference point. The choice of 1970 was arbitrary — it was simply a convenient round date when Unix was being developed at Bell Labs in the late 1960s. Before the epoch (pre-1970 dates), Unix timestamps are negative. The epoch itself is represented as 0. The current timestamp in seconds is the number of seconds that have elapsed since that moment.

What is the Year 2038 problem?

The Year 2038 problem (also called Y2K38 or the Unix Millennium Bug) occurs when Unix timestamps stored as 32-bit signed integers overflow. The maximum value of a 32-bit signed integer is 2,147,483,647, which corresponds to January 19, 2038 at 03:14:07 UTC. After that moment, the counter wraps around to −2,147,483,648, which represents December 13, 1901. Modern systems using 64-bit integers are not affected — a 64-bit signed integer can represent times up to approximately the year 292 billion. The risk lies in embedded systems, legacy firmware, and older 32-bit databases that have not been updated.

Why does JavaScript use milliseconds instead of seconds?

JavaScript's Date object was designed in 1995 by Brendan Eich, who chose milliseconds to provide sub-second precision suitable for browser animations, UI interactions, and event timing. The decision also aligned with Java's Date class (which also uses milliseconds) since early JavaScript was designed to complement Java applets. Once the standard was set in ECMAScript, changing it would break every existing JavaScript program that uses Date.now() or new Date().getTime(). Today the entire browser ecosystem — setTimeout, setInterval, requestAnimationFrame, performance.now(), and the Web Animations API — all use milliseconds.

What happens if I accidentally pass milliseconds to a function expecting seconds?

The result is a date far in the future — approximately 554 years ahead. Passing 1,748,000,000,000 milliseconds (2026) to a function that interprets it as seconds produces a date around the year 57,000 AD. The opposite error — passing seconds to a function expecting milliseconds — produces a date in early 1970, typically January 21, 1970 at most. Both are recognisable bugs: a timestamp showing 57,000 AD or January 1970 when you expect a recent date is almost always a seconds/milliseconds mismatch. Always verify which unit an API or function expects before passing a timestamp.

Can I mix seconds and milliseconds in the same database table?

You can store the raw integers in the same column, but you must not. Mixed units in a single column make sorting incorrect, range queries wrong, and the data effectively unusable without external documentation. The correct approach is to standardise on one unit across the entire system, document it in the schema (e.g. column name: created_at_ms or created_at_s), and enforce it at the application layer. If you are receiving timestamps from multiple sources that use different units, normalise to your chosen unit at ingestion time before storage.

What precision do I need for web analytics or event logging?

For web analytics (page views, clicks, conversions), milliseconds are recommended — modern websites generate multiple events within the same second, and correct ordering and deduplication requires sub-second precision. For server-side logging of HTTP requests, second-level precision is often sufficient, but milliseconds are preferred for performance profiling. For high-frequency trading, financial tick data, or network packet capture, microseconds (Unix microseconds = 16 digits) or nanoseconds are required. Most analytics platforms (Segment, Amplitude, Mixpanel) use milliseconds. Structured logging libraries like Logstash and Loki default to milliseconds.

How do I convert between seconds and milliseconds in common languages?

JavaScript: seconds = Math.floor(Date.now() / 1000); ms = seconds * 1000. Python: import time; seconds = int(time.time()); ms = int(time.time() * 1000). Java: long ms = System.currentTimeMillis(); long s = ms / 1000L. Go: import time; s := time.Now().Unix(); ms := time.Now().UnixMilli(). Ruby: s = Time.now.to_i; ms = (Time.now.to_f * 1000).to_i. PHP: s = time(); ms = round(microtime(true) * 1000). SQL (PostgreSQL): seconds = EXTRACT(EPOCH FROM NOW())::bigint; ms = (EXTRACT(EPOCH FROM NOW()) * 1000)::bigint.

Related Comparisons

Related Tool

Timestamp to Date Converter

Convert any Unix timestamp (seconds or milliseconds) to a human-readable date and time.