← All archived runs
Run: fix-date-test-timezone
run.md
Run: fix-date-test-timezone
- lane: bug
- branch: claude/fix-date-test-timezone-zwkmbv
- pr: #774
lane/output/notes.md
Bug: fix-date-test-timezone
- observed:
formatDurationBetween → "formats spans of sixty days or more in months" asserts
'2 months' and gets '3 months' on any UTC machine, so it fails on every GitHub Actions runner
while passing on the European laptops it was written on · expected: the test passes in every
timezone, because nothing it exercises is timezone-dependent
- cause: the assertion built both endpoints in local time —
formatDurationBetween(new Date(2026, 0, 1), new Date(2026, 3, 1)). formatDurationBetween
measures a raw epoch-millisecond span, and 1 Jan → 1 Apr straddles the spring-forward
transition, so in Europe/* the span is 90 days minus an hour → Math.floor(89 / 30) = 2,
while in UTC it is a clean 90 days → Math.floor(90 / 30) = 3. The test enshrined the European
reading; 3 is the correct answer (1 Jan to 1 Apr is three calendar months). Introduced by #768.
- fix:
packages/services/src/utils/date.test.ts: the formatDurationBetween block now builds
every endpoint through a local utc(y, m, d) helper (new Date(Date.UTC(...))) and expects
'3 months'. Test-only — src/utils/date.ts is untouched, and flipping the expected string
without moving the endpoints to UTC was explicitly rejected as it just relocates the failure onto
European machines.
- sweep: the other ten
new Date(y, m, d) sites in the file are correct as they stand and were
deliberately left local. parseToUTC reads getFullYear/getMonth/getDate, and formatTime /
formatDate / formatYYYYMMDD render through date-fns format — all local-calendar
operations, so a UTC endpoint there would introduce the mirror-image bug (a shifted expected
day at any non-zero offset). None of their spans cross a DST boundary either: the formatTime
cases sit within Aug 5 2026 or run Aug 1 → Aug 5 (96h against a 24h threshold), and no timezone
in the tz database transitions in August. A file-header comment records the rule — build the
endpoint the way the function under test reads it — so the next sweep doesn't "fix" them.
- verified:
src/utils/date.test.ts 24/24 under UTC, Europe/Brussels, America/Los_Angeles,
Pacific/Kiritimati (+14), Australia/Lord_Howe (half-hour offset), Pacific/Chatham
(45-minute offset) and America/Santiago (southern-hemisphere DST). Full suite green under
TZ=UTC: @sustentus/services 122/122, @sustentus/web 66/66.
- changelog: not user-visible — a test-only fix, no product behaviour changes.
- unblocks: CI on #772 (markdown-only, does not touch
packages/services).