Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .changeset/dataset-format-8263-impossible-date-prose.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
---

Comment-only repair in `@object-ui/core`'s `dataset-format.ts` — **no behaviour change**, so
nothing to release.

`formatMeasureDate`'s inline note and the `ISO_DATETIME_RE` docblock both asserted that a
well-shaped impossible calendar date such as `2026-02-30` is unparseable and therefore "keeps
falling through to `String(v)`". Measurement on objectui#8263 showed the opposite on **both**
arms: ECMAScript's Date Time String Format accepts `DD` in `01`-`31` syntactically and `MakeDay`
rolls the surplus into the next month, so `Date.parse` returns an instant, not `NaN`. What the
guard actually rejects is an out-of-range **month** (`2026-13-01`), which the two patterns admit.

Both sentences now say that. The rolled render itself is untouched and stays pinned by
`agrees with the list cell on a rolled-over date instead of second-guessing it` in the co-located
date suite, which the new prose points at rather than restates. Whether the shared display path
should refuse an impossible calendar day at all is carried by objectui#10026.
34 changes: 28 additions & 6 deletions packages/core/src/utils/dataset-format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,15 @@ const ISO_DATE_ONLY_RE = /^\d{4}-\d{2}-\d{2}$/;
/**
* ISO date carrying a time part — `2026-07-04T07:00:00.000Z`, or the same with
* a space separator, with or without seconds/offset. Matched only as far as
* `HH:mm`; `Date.parse` decides the rest, so a well-shaped impossible instant
* still falls through untouched.
* `HH:mm`; `Date.parse` decides the rest. What it rejects is an out-of-range
* MONTH or CLOCK reading (`2026-13-01T09:30`, `2024-07-04T99:99`), which this
* pattern admits — such a value falls through untouched.
*
* ⛔ A DAY that overflows its month does NOT fall through. `2026-02-30T09:30`
* parses and renders rolled over, exactly as the date-only arm renders
* `2026-02-30`. See the note inside {@link formatMeasureDate} for the
* instrument that holds that render in place, and for where the open question
* about it lives.
*/
const ISO_DATETIME_RE = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}/;

Expand Down Expand Up @@ -221,10 +228,25 @@ const ISO_DATETIME_RE = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}/;
*/
function formatMeasureDate(v: unknown, format: string | undefined, locale: string | undefined): string | undefined {
if (typeof v !== 'string') return undefined;
// `Date.parse` guards both arms so a well-shaped impossible date
// (`2026-02-30`) is NOT swallowed into the em dash `formatDate` returns for
// an unparseable value — it keeps falling through to `String(v)`, exactly as
// it does today. Only a value that is genuinely a date changes.
// `Date.parse` guards both arms, and what it rejects is an out-of-range
// MONTH (`2026-13-01`) — which both patterns above admit — ⛔ NOT an
// out-of-range DAY. ECMAScript's Date Time String Format accepts `DD` in
// `01`-`31` syntactically and `MakeDay` rolls the surplus into the next
// month, so a well-shaped impossible date (`2026-02-30`) is PARSEABLE on
// both arms: it does not fall through to `String(v)`, it renders as the
// rolled-over day (`2026-03-02`). This paragraph asserted the opposite —
// that such a value keeps falling through — until objectui#8263 measured it.
//
// ⭐ That rolled render is not a leak in this guard; it is pinned, by
// `agrees with the list cell on a rolled-over date instead of second-guessing it`
// in this file's co-located date suite. Read that test for the argument. It
// is deliberately NOT restated here: a comment restating a pin is how this
// paragraph came to assert a behaviour that nothing implemented.
//
// ⚠️ Whether the SHARED display path should refuse an impossible calendar
// day at all is OPEN, and it is not this function's to answer alone — the
// authoring boundary already refuses such a value while the display path
// rolls it. objectui#10026 carries that question.
if (ISO_DATE_ONLY_RE.test(v)) {
return Number.isNaN(Date.parse(v)) ? undefined : formatDate(v, format, { locale });
}
Expand Down
Loading