Date String Portability Checker
Paste a date or timestamp string (or a whole log excerpt) and see exactly which values would be read differently — or rejected outright — by JS Date, Python and other common parsers, and why.
Processed locally in your browser. Your file is never uploaded.
How to use this calculator
- Paste one date string, or a longer block of text with dates embedded in it — nothing leaves your browser.
- Select "Check dates".
- Review each flagged value: what makes it ambiguous or risky, and which runtimes disagree.
- Use the suggested ISO 8601 rewrite where one is offered — some ambiguities genuinely can't be auto-resolved, and those are explained instead of guessed.
Assumptions
- Recognises five specific date/time shapes: a full ISO 8601 datetime (with or without an offset), a plain YYYY-MM-DD date (padded or not), a dash-separated two-digit-year date, and a slash-separated date. Anything else — natural-language dates ("March 3rd"), Unix timestamps, or other locale-specific formats — is out of scope.
- A slash-separated date's day/month order is only ever guessed when it's numerically forced (one component is greater than 12) — when both components could be a month, the tool reports the ambiguity instead of picking one silently.
- A two-digit year's century is never inferred, even when common conventions exist, because those conventions genuinely differ between runtimes and libraries.
Methodology
Each date-like substring is classified by shape, then checked against the specific ways JS Date, Python and strict parsers (some SQL engines among them) are known to disagree: implicit UTC-vs-local midnight for date-only strings, local-vs-UTC interpretation for a datetime with no offset, century inference for two-digit years, and rejection of non-zero-padded components by stricter parsers. A rewrite to unambiguous ISO 8601 is offered only when the fix is unambiguously correct — never a guess.
Worked example
An ambiguous slash-separated date
Inputs: 01/02/2024
Result: Both 1 and 2 are valid months, so this could mean January 2nd or February 1st depending on the convention in use. Flagged as an error; no automatic rewrite is offered because guessing the intended order would be worse than leaving it as a visible problem.
A date-only ISO string
Inputs: 2024-01-15
Result: JS's `new Date("2024-01-15")` reads this as UTC midnight, but other languages and JS's own `new Date(year, month, day)` form read a bare date as local midnight — in a timezone behind UTC, that's a different calendar day. Flagged as a warning explaining the pitfall; already valid ISO 8601, so no rewrite is offered.
A non-padded date
Inputs: 2024-1-5
Result: JS and Python both accept this leniently, but some strict SQL date parsers reject it outright. Rewritten safely to 2024-01-05.
Practical guidance
- Always include an explicit UTC offset (or "Z") on any timestamp with a time component that crosses a system boundary — it is the one thing that reliably removes ambiguity everywhere.
- Never emit a two-digit year from code you control — the century-inference rules genuinely differ between runtimes, and there's no fix at read time once the year has been truncated.
- Prefer ISO 8601 ("YYYY-MM-DD" or full datetime with offset) for any date that will be read by more than one system, including a second version of your own code.
Common mistakes
- Treating "the date parsed without throwing" as proof it parsed correctly — every ambiguous case in this tool parses successfully in every runtime, just to a different value.
- Assuming a bare "YYYY-MM-DD" string is timezone-safe because it looks like ISO 8601 — the format is unambiguous as text, but its meaning as an instant still depends on how the specific parser fills in the missing time-of-day.
FAQs
Why is 01/02/2024 flagged as an error but 25/12/2024 only as info?
In 01/02/2024 both 1 and 2 are valid month numbers, so the order genuinely can't be determined from the string alone. In 25/12/2024, 25 can't be a month, so the order (day/month) is forced — it's still not ISO 8601, but it isn't ambiguous, so it's a lower-severity, auto-rewritable issue.
Why won't the tool just assume a two-digit year like "24" means 2024?
It very likely does, but the same string can and does mean 1924 to some systems and 2024 to others depending on the century-inference convention they implement, and this tool never silently guesses on the user's behalf when a wrong guess would be worse than no guess.
Is a date-only string like 2024-01-15 actually unsafe?
It's unsafe specifically for the moment-in-time it represents when read by JS `Date` versus most other parsers, because JS treats a bare date as UTC while most other languages treat it as local time. It's completely safe as plain text/storage — the risk only shows up once something parses it into a date object and asks what instant it represents.