Short answer: Unix seconds, milliseconds, microseconds, and nanoseconds differ by powers of 1,000. Near the present, positive values often contain 10, 13, 16, and 19 digits respectively, but digit count is only a heuristic. Confirm the producer’s documented unit, use exact integer division and remainders for long values, and keep the original timestamp when the readable date cannot display all of its precision.
Four numbers can represent the same instant
Unix time measures an offset from 1970-01-01T00:00:00Z, the Unix epoch. The scale of that offset is a separate choice. A service counting whole seconds and a tracing database counting nanoseconds can record the same event with values that differ by nine decimal places. There is no marker inside a bare integer that says which unit was chosen.
For example, each value below identifies 2025-08-03T08:00:00Z when interpreted with the unit in its row. The trailing zeros are not decorative; they change the scale.
| Unit | Symbol | Example value | Units per second |
|---|---|---|---|
| Seconds | s | 1754208000 | 1 |
| Milliseconds | ms | 1754208000000 | 1,000 |
| Microseconds | µs | 1754208000000000 | 1,000,000 |
| Nanoseconds | ns | 1754208000000000000 | 1,000,000,000 |
Resolution describes the size of a unit, not necessarily the accuracy of the clock. A value stored in nanoseconds might merely pad a millisecond clock with six zeros. Conversely, an instrument may measure fine intervals accurately but synchronize poorly with UTC. Do not advertise “nanosecond accuracy” solely because a field has nineteen digits.
How to identify a timestamp unit
Start with metadata, not arithmetic. Look for a schema property such as created_at_ms, a database column comment, an API specification, a serialization type, or the function that produced the value. Unit suffixes and explicit documentation are stronger evidence than a plausible converted date.
When documentation is unavailable, magnitude can narrow the options. In the 2020s, a positive timestamp near “now” is usually 10 digits in seconds, 13 in milliseconds, 16 in microseconds, or 19 in nanoseconds. Divide the larger candidates by powers of 1,000 and check whether the result falls into an expected operational range. A customer signup record should not resolve to 1970 or to a year centuries in the future.
- Preserve the raw token. Copy the exact text before opening it in software that may use scientific notation or round long integers.
- Inspect names and neighboring fields. A suffix, API version, SDK type, or adjacent ISO date can reveal the intended unit.
- Generate candidates. Interpret the value under each plausible scale with the LiveParse Unix Timestamp Converter.
- Apply domain bounds. Compare candidates with a known deployment date, account lifetime, retention window, or event sequence.
- Verify the producer. Turn the inferred unit into explicit schema documentation and add a test so the next consumer does not repeat the guess.
Digit detection is not universal. The seconds value 999999999 has nine digits and represents a date in 2001. A 10-digit number might be a short millisecond offset from a custom epoch. Negative signs, leading zeros, far-future dates, and duration counters also defeat simple length checks. Use auto-detection for exploration, not as an undocumented production rule.
What a wrong unit looks like
The classic JavaScript bug is passing Unix seconds directly to new Date(). The constructor expects milliseconds, so 1754208000 becomes only about twenty days after the epoch and appears in January 1970. Multiplying by 1,000 produces the intended 2025 instant. The opposite mistake—treating milliseconds as seconds—creates a date tens of thousands of years beyond ordinary date ranges.
Wrong-unit results are not always spectacular. A relative duration, custom epoch, or truncated value can produce a believable but incorrect date. The safest validation uses facts external to the number: the event happened after the system launched, before it was exported, and in the same interval as nearby records. Add minimum and maximum accepted instants at ingestion boundaries.
| Symptom | Likely cause | First check |
|---|---|---|
| Date in January 1970 | Seconds supplied to a millisecond API | Multiply seconds by 1,000 before the call |
| Invalid or extremely distant date | Milliseconds treated as seconds | Divide by 1,000 and confirm schema |
| Nearby events become identical | Microseconds or nanoseconds rounded as floating point | Keep the token as text or arbitrary-size integer |
| Time differs by whole hours | UTC/local interpretation, not scale | Inspect the offset and timezone |
Convert units with exact arithmetic
Moving to a finer unit multiplies by a power of 1,000. Moving to a coarser unit divides by the same factor. Seconds to milliseconds multiply by 1,000; milliseconds to microseconds multiply by another 1,000; microseconds to nanoseconds do the same. Seconds to nanoseconds multiply by 1,000,000,000.
Division needs a policy for the remainder. Converting 1754208000123456789 nanoseconds to whole milliseconds gives a quotient of 1754208000123 with 456789 nanoseconds left over. Dropping that remainder is truncation, not a lossless conversion. Keep a pair such as whole milliseconds plus a sub-millisecond remainder, or use a type that represents seconds and nanoseconds separately.
input: 1754208000123456789 ns
seconds: 1754208000 s
remainder: 123456789 ns
Date.toISOString(): 2025-08-03T08:00:00.123Z
exact fraction: 123456789
The native JavaScript Date.toISOString() display in this example shows milliseconds because Date stores millisecond precision. It must not be used to reconstruct the original nanoseconds; six digits would be lost. A converter can instead format UTC directly from exact seconds and the nanosecond remainder—LiveParse does this for its exact ISO/UTC output—but local and native Date projections remain millisecond-based.
Negative timestamps need careful division
Negative Unix timestamps represent instants before the epoch. Whole values are straightforward: -1 second is 1969-12-31T23:59:59Z. Fractions expose an important implementation detail. The instant half a second before the epoch is -0.5 seconds, equivalent to -500 milliseconds. A normalized seconds-plus-nanoseconds representation commonly expresses that as -1 second plus 500000000 nonnegative nanoseconds.
Many programming-language integer division operators truncate toward zero, whereas timestamp normalization often needs floor division so the remainder stays between zero and one unit. If negative historical dates are supported, test values immediately below zero, exact negative seconds, and values with a fractional remainder. A formula verified only with positive modern timestamps can be wrong for archival data.
Boundary test set: include 0, 1, -1, one unit below an exact second, one unit above it, the largest supported value, and the smallest supported value. Run the tests for every accepted unit.
Precision limits in JSON, JavaScript, and spreadsheets
JavaScript’s Number type uses IEEE 754 binary64. It represents every integer only through 9007199254740991, which is 2^53 - 1. Present-day millisecond timestamps and microsecond timestamps fit below that threshold, although calculations and future ranges still require care. Present-day nanosecond epoch values do not fit and can round as soon as a JSON parser creates a Number.
JSON defines a number grammar but does not require a particular machine representation. A JSON document can contain a nineteen-digit integer, yet a typical JSON.parse() call may round it. If exact nanoseconds are part of an API contract, encode them as a decimal string or use a lossless parser and an arbitrary-size integer type. Document the choice; changing a field between number and string is itself an API contract change.
Spreadsheets are another risk. A cell may display a long timestamp in scientific notation and retain only about fifteen significant decimal digits. Formatting the cell as text before import, exporting quoted strings, or using a database-aware import flow protects the raw token. Never use a visually shortened spreadsheet value as migration evidence.
Database precision varies by type and product. A native timestamp type may store microseconds while an integer column holds any documented scale. Verify range, rounding, timezone behavior, and driver mapping—not only the SQL column declaration. Drivers may convert a database integer to a JavaScript number even when the database stored it exactly.
Unit errors and timezone errors are different
A Unix timestamp identifies an instant without carrying a timezone. Formatting that instant in UTC, Seoul, or New York produces different calendar labels for the same point on the timeline. Changing from seconds to milliseconds changes scale; changing from UTC to a regional zone changes presentation. Debug these as separate dimensions.
An input such as 2026-08-03T09:00:00Z explicitly names UTC. An input with +09:00 carries a numeric offset. An input such as 2026-08-03 09:00:00 has neither, so software must assume a zone. That assumption can vary between servers and browsers. Require an offset for exchanged date strings, or pair the local calendar value with an IANA timezone and an explicit rule for daylight saving gaps and overlaps.
Daylight saving time does not make an epoch value ambiguous. Ambiguity appears when a local wall-clock time occurs twice during a fall-back transition. A spring-forward transition can create local times that never occur. Convert an already-known epoch freely; when converting a local date to an epoch, choose the intended zone and overlap policy before calculating.
Timestamp units do not cause the Year 2038 problem
The Year 2038 problem is an integer-range failure. A signed 32-bit seconds value reaches its maximum, 2147483647, at 2038-01-19T03:14:07Z. The next second cannot be represented by that type. Unix time itself continues; applications using wider types can represent later instants.
Switching the same 32-bit field to milliseconds makes the representable calendar range shorter because the counter advances one thousand times faster. The practical remedy is a sufficiently wide, consistently serialized representation. Audit database columns, protocol fields, native interfaces, device firmware, caches, language bindings, and validation limits. Test dates just before and after the boundary end to end.
Know the convention of the source API
Conventions help orientation but never replace documentation. JavaScript Date.now() returns milliseconds. Python’s common POSIX timestamp interfaces use seconds and may accept a fractional float, though exact high-resolution work should avoid relying on binary floating point. PostgreSQL’s to_timestamp(double precision) interprets a numeric argument as Unix seconds. Java and Go provide constructors whose names or arguments make seconds, milliseconds, and nanoseconds explicit.
JWT NumericDate claims are measured in seconds from the epoch and may be non-integer according to the underlying specification. A token’s readable expiration is not proof that it is authentic: decode for inspection, then verify its cryptographic signature, issuer, audience, allowed algorithms, and claim rules in trusted code.
File modification times, telemetry SDKs, cloud data warehouses, and database drivers each use their own resolution and range. Name the unit at every boundary. Prefer created_at_ms over created_at for a numeric column, and include examples in schemas so a ten-digit test fixture does not accidentally validate a millisecond field.
A safe unit-normalization workflow
- Inventory every producer and consumer. Record the current storage type, unit, precision, range, timezone interpretation, and transport representation.
- Select one canonical contract. Choose a numeric scale or an offset-bearing text format based on ordering, precision, interoperability, and human-debugging needs.
- Preserve raw input. During migration, keep the original field or immutable backup so conversions can be audited and reversed.
- Use exact conversion. Apply integer quotient-and-remainder logic, define rounding explicitly, and reject values outside the accepted date range.
- Validate representative records. Cover pre-epoch dates, sub-second values, daylight saving boundaries, maximum values, and the 2038 boundary where relevant.
- Deploy readers before writers. If a compatibility period is needed, make consumers understand both versions before producers switch, then remove the old path deliberately.
- Monitor semantic bounds. Alert on dates before the product existed, too far in the future, or out of sequence with ingestion time.
Check a value before changing code. LiveParse can interpret seconds, milliseconds, microseconds, and nanoseconds, show UTC and local dates, and keep large integer inputs exact in the current browser tab.
Open the Unix Timestamp ConverterFrequently asked questions
Is a 13-digit timestamp always milliseconds?
No. A positive epoch value near the present is often 13-digit milliseconds, but a different epoch, a duration counter, a padded string, or a far-future seconds value can have the same length. Confirm the producing contract and validate the converted date against domain bounds.
Should timestamps be stored as seconds or milliseconds?
Choose the coarsest unit that preserves required event ordering and the format best supported by every consumer. Seconds are widely interoperable; milliseconds fit browser and JavaScript conventions; higher resolutions may be needed for telemetry. The crucial requirement is explicit, exact, consistent documentation.
Can I recover nanoseconds after converting to a JavaScript Date?
No. A JavaScript Date represents milliseconds. Keep the original nanosecond integer or a separate sub-millisecond remainder. A millisecond ISO string cannot reconstruct discarded digits.
Why are two different nanosecond timestamps equal in my code?
They were probably converted to a floating-point number beyond the safe-integer limit. Parse them as decimal strings or arbitrary-size integers and compare them exactly before creating any millisecond display value.
Does a Unix timestamp include a timezone?
No. It names an instant relative to the UTC epoch. UTC and local time are renderings of that instant. A local date being converted in the other direction needs a timezone or offset before it identifies one instant.
Primary specifications and references
- POSIX.1-2024: Seconds Since the Epoch — the POSIX definition used by Unix time interfaces.
- RFC 3339: Date and Time on the Internet — an interoperable offset-bearing date-time profile.
- ECMAScript: Time Values and Time Range — the millisecond-based JavaScript time model.
- RFC 7519: NumericDate — the seconds-based time representation used by JWT claims.