Skip to content

fix(transpiler): YEAR/MONTH/DAY use UTC serial math (local-time getters read dates a day early west of UTC)#64

Merged
ebootheee merged 1 commit into
mainfrom
fix/year-month-day-utc-serials
Jun 10, 2026
Merged

fix(transpiler): YEAR/MONTH/DAY use UTC serial math (local-time getters read dates a day early west of UTC)#64
ebootheee merged 1 commit into
mainfrom
fix/year-month-day-utc-serials

Conversation

@ebootheee

Copy link
Copy Markdown
Owner

Found by running the all-17-sheet warm-GT sweep on the post-#62 A-1 rebuild: 9/17 sheets came back numerically EXACT, and the residual divergences (Technology 284k, Owned Asset PP&E 84k, Lease Amortization 9k, Debt 7.4k, Working Capital 5.9k, Valuation 7) all carried a one-day-shift signature — Valuation!G7 GT=45107 (Jun 30 2023) vs got=45106, integer counts off by one, 0/1 flags flipped.

Root: the YEAR/MONTH/DAY lowerings used new Date((s-25569)*86400000).getMonth()/.getDate()/.getFullYear()local-time getters — so any engine runtime west of UTC reads every Excel serial one day early. The DATE(YEAR(x),MONTH(x),DAY(x)) reconstruction idiom rebuilds dates one serial low and every date-keyed COUNTIFS/SUMIFS window downstream shifts by a day. The engine's output depended on the machine's timezone.

Fix: route all three through the existing _serialToYMD helper (pure-integer UTC math, 1900-epoch-quirk aware); add it to the sheet-module helper imports.

Test: new TZ-pinned child-process cases in test-date-axis-sumifs.mjs — the engine runs under TZ=America/Denver and TZ=Pacific/Auckland, with a hazard probe (oldDay === 29) as the negative control so the case provably discriminates on any CI machine including UTC runners. RED pre-fix with exactly the A-1-observed values (DAY=29, rebuilt=45106); 26/26 GREEN post-fix. Full npm test + cargo test green.

A-1 rebuilt with the fixed parser; the before/after warm-GT sweep result will be posted to #33.

🤖 Generated with Claude Code

…ers read dates a day early west of UTC

The emitted lowerings called new Date((s-25569)*86400000).getMonth()/
getDate()/getFullYear() — LOCAL-time getters — so any engine runtime west
of UTC read every Excel serial one day early (DAY(Jun-30-2023)=29). The
DATE(YEAR(x),MONTH(x),DAY(x)) reconstruction idiom (live on A-1
Valuation!G7) rebuilt dates one serial low, shifting date-keyed
COUNTIFS/SUMIFS windows and flipping comparison flags across whole sheets;
the engine's results depended on the machine timezone.

YEAR/MONTH/DAY now route through _serialToYMD (pure-integer UTC math,
1900-epoch-quirk aware); _serialToYMD added to the sheet-module helper
imports. New TZ-pinned child-process cases in test-date-axis-sumifs.mjs
run the engine under America/Denver and Pacific/Auckland with a hazard
probe as negative control — RED pre-fix with exactly the A-1-observed
values (DAY=29, rebuilt serial 45106), 26/26 GREEN post-fix. Full npm
test + cargo test green.

Found by the all-17-sheet warm-GT sweep on the post-#62 A-1 rebuild: the
residual numeric divergences (Technology 284k, PP&E 84k, Lease Am 9k,
Debt 7.4k, WC 5.9k, Valuation 7) all carry the one-day-shift signature.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant