You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[finding] outside calendar-day.ts, a year from 0001 to 0099 is still read as 1900..1999: Date.UTC's two-digit-year remap in core's datetime and bucket helpers, filter-tokens and the REST import's datetime cell #20599
Filing gate: ① a product defect family with a measured reach:, one card. Finding class (a).
Filed by the domain:spec execution seat 2 (session_014EJ1ED8X4MMrT18BhVx4tx, seat post #18549) from the #20550 dev report 5884426792 (out_of_scope_findings[0]). PR #20591's at-tier record 5884564940 confirmed every site below from the code and found none of them introduced or worsened by that PR. ⛔ Filed bare: routing, grading and any per-lane split belong to triage. ⛔ Not a claim.
The family
Date.UTC(year, …) and the Date(year, month, …) constructor read a year from 0 to 99 as 1900 + year (ECMA-262 MakeFullYear). setUTCFullYear does not. The years 0001..9999 are the supported range since #20264. PR #20591 (Fixes #20550) removes the remap from packages/spec/src/data/calendar-day.ts only. The same construction remains at these sites.
Locations (read at origin/maine666636fd9)
packages/core/src/utils/datetime.tszonedWallClockToUtcMs (:142; Date.UTC at :143, and the offset read at :174).
isoWeekLabelFromCalendarDay (:309–:313), through bucketDateKey('0050-01-01T10:00Z', week), gives 1949-W52.
packages/core/src/utils/filter-tokens.ts: Date.UTC(year, …) at :198, and the period starts at :215–:243. This is the same construction, with no measurement yet.
Same shape, unmeasured, named by the dev: service-analyticspreview-evaluator.ts:358 (the week key), trigger-scheduletime-relative-trigger.ts:118 / :123 (a record date's window), and formula's stdlib.ts:59.
Controls: year 0100 answers correctly at every measured site.
Shape (⛔ not a ruling)
The construction PR #20591 landed, a private new Date(0) plus setUTCFullYear(year, monthIndex, day), or one shared helper that the sites import. Pin 0001, 0050, 0099 and 0100, plus a 2026 control, at each door the site feeds. The sites span domain:engine (core, formula), domain:cli (rest), and domain:services (analytics, trigger-schedule). Triage may split per lane.
A REST listing of the 1,000 most recently updated issues and PRs, open and closed, grepped locally for Date.UTC, two-digit year, 1900, year below 100 and parseDateCell. The hits are #20550 (the spec helper, fixed by PR #20591), #20534 (the padding), #20280 (MySQL read-back) and #20264 (the supported range, closed). None carries these sites.
Filing gate: ① a product defect family with a measured
reach:, one card. Finding class (a).Filed by the
domain:specexecution seat 2 (session_014EJ1ED8X4MMrT18BhVx4tx, seat post #18549) from the #20550 dev report5884426792(out_of_scope_findings[0]). PR #20591's at-tier record5884564940confirmed every site below from the code and found none of them introduced or worsened by that PR. ⛔ Filed bare: routing, grading and any per-lane split belong to triage. ⛔ Not a claim.The family
Date.UTC(year, …)and theDate(year, month, …)constructor read a year from 0 to 99 as 1900 + year (ECMA-262MakeFullYear).setUTCFullYeardoes not. The years 0001..9999 are the supported range since #20264. PR #20591 (Fixes #20550) removes the remap frompackages/spec/src/data/calendar-day.tsonly. The same construction remains at these sites.Locations (read at
origin/maine666636fd9)packages/core/src/utils/datetime.tszonedWallClockToUtcMs(:142;Date.UTCat:143, and the offset read at:174).reach:POST /api/v1/data/:object/import. A CSV cell0050-01-01 10:00in adatetimecolumn is stored, and reads back throughPOST /api/v1/data/:object/query, as1950-01-01T10:00:00.000Z, on SQLite and on PostgreSQL 16. The control2026-07-15is stored as written. Measured by the specnextUtcCalendarDayanswers null for every day in years 0001..0099 (Date.UTC reads them as 1900..1999), so a datetime$lte/$betweenmax on such a day skips whole-day widening and misses that day's rows #20550 dev.{ year: 50, month: 1, day: 1, hour: 10 }gives1950-01-01T10:00Zin UTC, and1950-01-01T02:00ZinAsia/Shanghai.packages/rest/src/import-coerce.tsparseDateCell, the date-onlydatetimefast path (:388).parseDateCell('0050-01-01', datetime)answers1950-01-01T00:00:00.000Z(function level).zonedDateStartToUtcMs('0050-01-01', 'UTC')gives1950-01-01T00:00Z.bucketKeyToCalendarRange(:354;Date.UTCat:370–:410) gives('0050', year)→1950-01-01..1951-01-01, and0050-Q1/0050-01likewise land in 1950.('0050-01-01', day)and('0050-W01', week)answernull, the same round-trip failure specnextUtcCalendarDayanswers null for every day in years 0001..0099 (Date.UTC reads them as 1900..1999), so a datetime$lte/$betweenmax on such a day skips whole-day widening and misses that day's rows #20550 had.isoWeekLabelFromCalendarDay(:309–:313), throughbucketDateKey('0050-01-01T10:00Z', week), gives1949-W52.packages/core/src/utils/filter-tokens.ts:Date.UTC(year, …)at:198, and the period starts at:215–:243. This is the same construction, with no measurement yet.service-analyticspreview-evaluator.ts:358(the week key),trigger-scheduletime-relative-trigger.ts:118/:123(a record date's window), andformula'sstdlib.ts:59.Controls: year 0100 answers correctly at every measured site.
Shape (⛔ not a ruling)
The construction PR #20591 landed, a private
new Date(0)plussetUTCFullYear(year, monthIndex, day), or one shared helper that the sites import. Pin 0001, 0050, 0099 and 0100, plus a 2026 control, at each door the site feeds. The sites spandomain:engine(core, formula),domain:cli(rest), anddomain:services(analytics, trigger-schedule). Triage may split per lane.Not in this card
parseDateCell'sdatearm (parseDateCell('0050-01-01', date)→50-01-01, refused asinvalid_dateat the import door): carried by /import: parseDateCell emits adatecell year below 1000 unpadded (0500-01-01→500-01-01), so after PR #20524 a valid ISO date cell is refused per row asinvalid_date, and before it a non-day was stored #20534.bucketDateKeyfor year / quarter / month / day (50,50-Q1,50-01,50-01-01): the same padding family as /import: parseDateCell emits adatecell year below 1000 unpadded (0500-01-01→500-01-01), so after PR #20524 a valid ISO date cell is refused per row asinvalid_date, and before it a non-day was stored #20534. Whether that card takes them is for triage to decide.nextUtcCalendarDay('9999-12-31')answering10000-01-01: filed separately, because it is a different defect in the same helper.placed_on: "0009-03-04"correctly, and…/queryreturns"1909-03-04"; adatetime0009-03-04T10:00Zreturns2004-09-03T10:00Z#20280.Dedupe
A REST listing of the 1,000 most recently updated issues and PRs, open and closed, grepped locally for
Date.UTC,two-digit year,1900,year below 100andparseDateCell. The hits are #20550 (the spec helper, fixed by PR #20591), #20534 (the padding), #20280 (MySQL read-back) and #20264 (the supported range, closed). None carries these sites.Dedupe words:
Date.UTC two-digit year 1900 import datetime 0050·zonedWallClockToUtcMs year below 100·bucketKeyToCalendarRange 0050 1950·parseDateCell datetime 0050-01-01 1950Generated by Claude Code