Developer tools · Unix timestamp converter
The off-by-1000 bug: when a date shows January 1970 or the year 56000
· Why it matters
timestamps debugging developer-workflow
Passing seconds where milliseconds are expected (or the reverse) is the most common timestamp bug there is. This post shows how it looks in each direction, where it hides between languages, and how to catch it in seconds.
Every user joined on 1 January 1970 — the screen that gives the bug away, and the backend that was perfectly correct
A profile page showing every account near January 1970 is a strong scale symptom. The backend may have returned correct epoch seconds while frontend code passed them directly to a Date constructor that interprets milliseconds. A present-day count then shrinks by a factor of one thousand on the calendar axis.
Do not patch the display by adding a constant year or replacing the date. Capture the raw field, its API contract and the exact constructor call. ToolAcre lets you force both units, so one value can be tested without changing production data. The reading matching another known event identifies the likely boundary error.
The two symptoms — seconds fed to a millisecond API landing in January 1970, and milliseconds fed to a seconds API landing tens of thousands of years out
Seconds interpreted as milliseconds land close to the epoch because a billion milliseconds is only a small fraction of a century. The reverse mistake expands a trillion-millisecond value into a trillion seconds, often outside ordinary application ranges. Both failures preserve the digits while changing their scale.
The published ten-versus-thirteen-digit article already explains the contemporary visual heuristic and its limits. This article focuses instead on diagnosis and prevention: explicit unit selection, independent event evidence, and one conversion at the interface where a producer’s representation meets a consumer’s contract.
Because both branches are deterministic, the symptom can be reproduced with one fixture. That makes unit mismatch easier to prove than intermittent clock drift or locale formatting behavior.
Where the boundary usually is — JavaScript and Java in milliseconds, Unix tools, Python and most databases in seconds, and the JSON payload between them
This repository proves that JavaScript Date consumes milliseconds and that ToolAcre multiplies seconds before constructing one. It does not establish the defaults of every Java, Python, shell or database API named in the workbook. Those contracts must be checked where they are used.
A JSON number carries no unit metadata. Naming a field `created_at` transfers the ambiguity across services; naming it `created_at_s` or documenting an ISO string makes the contract reviewable. The receiving adapter should convert once into its internal representation rather than scattering multiplications across views.
Write the conversion beside the boundary definition, not inside a reusable display helper. The adapter knows the producer contract; a generic formatter should receive an already normalized instant.
The unit boundary is API-specific; this repository proves JavaScript Date uses milliseconds
A weak fixture such as `0` cannot detect the bug because zero seconds and zero milliseconds both name the epoch. Small fabricated values can also look like plausible 1970 dates. A mock that returns the same scale expected by its consumer never exercises a real integration mismatch.
Choose a nonzero known instant and make the two interpretations observably different. Assert the canonical ISO result at the boundary, not merely that a Date object exists. Include a milliseconds case and a seconds case; ToolAcre’s own tests compare 1,000,000 under each unit for exactly this reason.
Unit bugs survive whenever tests fail to distinguish the two scales
Consider `created_at: 1738578000`. Forced as seconds, it becomes `2025-02-03T10:20:00.000Z`; forced as milliseconds, it becomes `1970-01-21T02:56:18.000Z`. A deployment record known to have been created in February 2025 resolves the ambiguity without relying solely on digit count.
Keep the raw JSON beside that known event while fixing the adapter. If the field were `1738578000000`, the millisecond interpretation would identify the same instant. The two values should never be accepted interchangeably inside one schema, even though a converter can demonstrate their equivalence after applying the correct scale.
The known deployment date is independent evidence. Without it, choosing the more plausible output can encode an investigator’s expectation rather than establish what the producer intended.
Worked example: test a created_at value under both explicit units
Durable repair begins at the boundary: parse the documented source unit, convert exactly once and expose a typed or clearly named internal value. Schema descriptions, examples and generated clients should preserve the suffix or date-time format. A reviewer can then spot an extra multiplication before runtime.
Add a regression fixture with the real scale and a fixed ISO expectation. Avoid auto-detection in application code when the producer has a contract; heuristics are for investigating uncertain legacy data. ToolAcre labels its detected choice precisely so the guess cannot masquerade as guaranteed metadata.
What this does not cover — time zone mistakes, which shift a date by hours rather than by decades
A time-zone error typically shifts a display by hours and may cross one calendar day. A factor-of-1,000 error shifts decades or millennia. Mixing the diagnoses encourages offset adjustments around a value whose scale is already wrong. Verify the unit before inspecting local formatting.
Similarly, a wrong epoch origin can remain nonsensical under both seconds and milliseconds. If neither interpretation matches any known event, stop toggling and investigate the producer. A converter narrows hypotheses; it does not prove that every large integer is Unix time.
If the year is plausible but the hour is consistently displaced, then investigate zone presentation. Keeping these symptom scales separate shortens the path from screenshot to root cause.
Takeaway: a wrong unit is a wrong century — and how the Unix timestamp converter's stated unit lets you test both readings in a moment
A wrong unit is not cosmetic metadata—it changes the instant. Treat 1970-heavy screens and implausibly distant years as signals to inspect the producer-consumer seam. The value, unit contract and known event form a three-part proof stronger than an apparently reasonable date.
Use the converter to compare explicit readings, then encode the chosen scale in names, types and tests. The goal is not to teach software to guess more cleverly. It is to remove the guess from the path that creates dates for users.
A code review can then ask one precise question at each boundary: what unit enters, and what unit leaves? That is more reliable than recognizing a particular number of digits.