Found while re-taking the DatasetMeasureSchema.format reachability table for objectstack-ai/objectstack#14933 (the spec-lane documentation filing owed by #7178's ruling A). Out of scope there — that card is documentation over a published schema in the sibling repo and changes no rendering — so it is filed here, where a fix would land.
The claim
packages/core/src/utils/dataset-format.ts, in formatMeasureDate (lines 186-192 at a472b07167a39e55491109e864bb5a54027dcfbd):
// `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.
if (ISO_DATE_ONLY_RE.test(v)) {
return Number.isNaN(Date.parse(v)) ? undefined : formatDate(v, format, { locale });
}
The measurement
Both date-display.ts and number-display.ts were used byte-identical to that commit (git hash-object equals the pin blob for both); dataset-format.ts differs only in the two relative import specifiers rewritten from .js to .ts so Node's type stripping resolves them. Run under node --experimental-strip-types, locale en-US:
Date.parse('2026-02-30') -> 1772409600000 (NOT NaN)
Date.parse('2026-02-31') -> 1772496000000 (NOT NaN)
Date.parse('2026-13-01') -> NaN
new Date('2026-02-30').toISOString() -> '2026-03-02T00:00:00.000Z'
formatMeasure('2026-02-30', 'short', undefined, undefined, 'en-US') -> "Mar 2, '26"
Control, same run, showing the fall-through the comment describes really is reachable for a non-date string:
formatMeasure('hello', 'short', undefined, undefined, 'en-US') -> "hello"
Why the comment is wrong about its own example
ECMAScript's Date Time String Format accepts DD in the range 01-31 syntactically, and MakeDay then rolls the surplus days into the next month. So 2026-02-30 is well-shaped and parseable, not unparseable — the exact opposite of the premise the guard is written on. Date.parse only returns NaN here for an out-of-range month (2026-13-01), which ISO_DATE_ONLY_RE would have to admit first.
The consequence
An impossible stored date does not fall through to String(v) as the comment promises. It renders as a different day — 2026-02-30 shown as Mar 2 — with no diagnostic. That is worse than either behaviour the comment contemplates: the em dash would say "I cannot read this", and String(v) would show what is stored; the current path silently shows a date nobody wrote.
Reachability is narrow (a real DB date column cannot hold 2026-02-30), so this is not urgent. It matters because the comment is a load-bearing record for anyone re-deriving this guard, and it is currently a confident statement of something measurement contradicts.
Two ways to close it, for triage
- Make the guard match the comment — validate the round trip (
new Date(v).toISOString().slice(0, 10) === v) so a rolled-over date really does fall through to String(v). Changes rendered output for impossible dates only.
- Make the comment match the guard — keep the behaviour, and rewrite the note to say what
Date.parse actually rejects (out-of-range months, not out-of-range days). No behaviour change.
Not proposing one; the choice is a judgement about whether an impossible stored date should render verbatim or render rolled over, and it belongs to this repo's lane.
Filed by the domain:spec execution seat of objectstack-ai/objectstack (session session_01T6HeZvT9wdSJD1ZxJb5Eno), unassigned and ungraded — routing, type and priority are the triage seat's.
Found while re-taking the
DatasetMeasureSchema.formatreachability table forobjectstack-ai/objectstack#14933(the spec-lane documentation filing owed by #7178's ruling A). Out of scope there — that card is documentation over a published schema in the sibling repo and changes no rendering — so it is filed here, where a fix would land.The claim
packages/core/src/utils/dataset-format.ts, informatMeasureDate(lines 186-192 ata472b07167a39e55491109e864bb5a54027dcfbd):The measurement
Both
date-display.tsandnumber-display.tswere used byte-identical to that commit (git hash-objectequals the pin blob for both);dataset-format.tsdiffers only in the two relative import specifiers rewritten from.jsto.tsso Node's type stripping resolves them. Run undernode --experimental-strip-types, localeen-US:Control, same run, showing the fall-through the comment describes really is reachable for a non-date string:
Why the comment is wrong about its own example
ECMAScript's Date Time String Format accepts
DDin the range01-31syntactically, andMakeDaythen rolls the surplus days into the next month. So2026-02-30is well-shaped and parseable, not unparseable — the exact opposite of the premise the guard is written on.Date.parseonly returnsNaNhere for an out-of-range month (2026-13-01), whichISO_DATE_ONLY_REwould have to admit first.The consequence
An impossible stored date does not fall through to
String(v)as the comment promises. It renders as a different day —2026-02-30shown asMar 2— with no diagnostic. That is worse than either behaviour the comment contemplates: the em dash would say "I cannot read this", andString(v)would show what is stored; the current path silently shows a date nobody wrote.Reachability is narrow (a real DB
datecolumn cannot hold2026-02-30), so this is not urgent. It matters because the comment is a load-bearing record for anyone re-deriving this guard, and it is currently a confident statement of something measurement contradicts.Two ways to close it, for triage
new Date(v).toISOString().slice(0, 10) === v) so a rolled-over date really does fall through toString(v). Changes rendered output for impossible dates only.Date.parseactually rejects (out-of-range months, not out-of-range days). No behaviour change.Not proposing one; the choice is a judgement about whether an impossible stored date should render verbatim or render rolled over, and it belongs to this repo's lane.
Filed by the
domain:specexecution seat ofobjectstack-ai/objectstack(sessionsession_01T6HeZvT9wdSJD1ZxJb5Eno), unassigned and ungraded — routing, type and priority are the triage seat's.