-
Notifications
You must be signed in to change notification settings - Fork 3
Home
This page tracks the gaps and open questions in temporal-fmt β the stuff that's honest to call out but doesn't belong in the README. If you're looking for a way to contribute, this is the place to start.
Everything here falls into one of four buckets, and the bucket matters more than the description: it tells you whether there's a PR waiting to happen, a design conversation to have first, something already settled, or nothing to do at all.
These aren't bugs in temporal-fmt. They're consequences of how Intl and userland Temporal polyfills currently talk to each other. A PR against this repo can't close them; they'd need a spec or engine change somewhere else.
On Node < 26 without native Temporal, locale-aware tokens (MMMM, EEEE, a, etc.) throw Cannot use valueOf instead of working. The cause: Intl.DateTimeFormat reads fields directly off a native Temporal object, and a userland polyfill isn't one, so the read fails.
The documented workaround β swap in the polyfill's own Intl export in place of the global one β stays a workaround, not a fix, until Intl/Temporal interop is resolved upstream. If you hit this and know of movement on the spec side, link it in an issue; that's more useful than a PR here.
This was originally written against matchesFormat's locale-aware token matching, but it applies to parse too: parse calls the same getLocaleVocab()/Intl.DateTimeFormat machinery whenever a locale-aware token or non-default calendar is involved, with no separate path for polyfilled environments. Same failure mode, same workaround, now on both functions (well, on parse, since matchesFormat is gone β see Resolved below).
These are real gaps worth closing, but the fix changes what a function is, not just what it does. Open an issue and propose an approach before sending a PR β otherwise you're guessing at a decision nobody's made yet.
A format string that mixes H/HH (24-hour) and h/hh (12-hour) tokens β 'HH h a', say, likely a copy-paste leftover from editing an example β currently parses without error. resolveHour() checks fields.hour (from HH/H) first and returns it if present, silently ignoring anything captured into fields.hour12/isPM. No warning, no throw.
That's inconsistent with how parse handles every other ambiguity in the format string β missing a on a 12-hour token throws, an incomplete date throws, a weekday that doesn't match the actual date throws. Silently picking one hour value and dropping the other stands out as the one case that doesn't get the same treatment.
Open question: should this throw (matching the rest of parse's error philosophy), or is silently preferring 24-hour intentional and just needs a comment/README note saying so? Propose an approach in an issue before sending a PR β this is a "what should the behavior be," not a "here's the fix."
matchesFormat only checked shape and vocabulary β two digits for MM, a real month name for MMMM β not whether the date could actually exist. matchesFormat('yyyy-MM-dd', '2026-02-30') used to return true, because February never having 30 days wasn't something the function could know without real calendar math.
The open question this page used to track was whether that calendar math should get bolted onto matchesFormat directly, or live in a separate export. It ended up being neither: matchesFormat is gone, replaced by a parse function that builds a real Temporal object and lets Temporal itself reject invalid dates via overflow: 'reject'. parse('yyyy-MM-dd', '2026-02-30') now throws instead of silently matching.
parse also validates weekday tokens against the date they're paired with, and matches locale-aware vocabulary (month/weekday names, AM/PM) the same way format does. See the README for full usage and error cases.
Listed here so nobody spends a PR "fixing" a decision that was made on purpose. If you disagree with the reasoning, that's a fine thing to raise as an issue, but it's a request to revisit a decision, not a bug report.
yyyy, MM, dd, HH, mm, ss, SSS come out as 0-9 regardless of locale. Named fields (MMMM, EEEE, a) do localize, since those go through Intl.DateTimeFormat. The split is deliberate: most consumers of formatted output β logs, APIs, filenames β want predictable ASCII digits, and the library's zero-padding logic isn't built to handle non-Latin numeral systems like Arabic-Indic or Devanagari. If you need localized digits, run the numeric pieces through Intl.NumberFormat yourself.
Given a yy token, parse resolves 00β68 to 2000β2068 and 69β99 to 1900β1999 β the same convention POSIX strptime uses. This was a deliberate choice over the date-fns approach of picking the closest century to a caller-supplied reference date: a fixed rule keeps parse stateless and its output independent of when you happen to call it, at the cost of being a fairly arbitrary cutoff. If your use case needs unambiguous years, use yyyy instead of yy β that's the actual fix, not a different pivot point. See the README for the full writeup.
- Blocked-upstream items: track the relevant spec/engine issue, link it here, don't send a PR against this repo.
- Open design questions: start an issue proposing an approach before writing code.
- Found something new? If it's not listed above, it's not a known issue yet β open one.