Symptom
cargo test -p perry-runtime --lib date::tests::test_full_year_setters_revive_invalid_date_only fails on any machine whose current UTC offset differs from the offset at the target date, and passes under TZ=UTC:
- Run in June (CEST, UTC+2):
setFullYear(2020) on an Invalid Date revives to a timestamp whose getHours() is 1, not 0 (expected local 2020-01-01T00:00:00, January is CET, UTC+1).
TZ=America/New_York fails the same way; TZ=UTC passes — which is why CI (UTC) is green and the bug goes unnoticed.
Root cause (suspected)
The local→UTC conversion in the setter/revive path (rebuild_local_with / the components→timestamp helper in crates/perry-runtime/src/date.rs) applies the timezone offset at the current time rather than the offset at the target instant. Per ECMA-262 LocalTZA(t, false) / MakeDay semantics, the offset must be computed for the time value being constructed (and needs the usual fixed-point iteration around DST transitions, since the offset depends on the result).
getHours() decodes with the offset at the stored instant (correct), so the two disagree by exactly the DST delta whenever the construction-time offset ≠ target-date offset.
Impact
Any local-time Date setter (setFullYear/setMonth/setDate/setHours/…) and likely new Date(y, m, d, …) local construction is off by the DST delta when the target date is on the other side of a DST boundary from "now". Affects real programs, not just the test.
Found while triaging PR #4924 (the test failure reproduces on unmodified main; it is unrelated to that PR's changes).
Symptom
cargo test -p perry-runtime --lib date::tests::test_full_year_setters_revive_invalid_date_onlyfails on any machine whose current UTC offset differs from the offset at the target date, and passes underTZ=UTC:setFullYear(2020)on an Invalid Date revives to a timestamp whosegetHours()is1, not0(expected local2020-01-01T00:00:00, January is CET, UTC+1).TZ=America/New_Yorkfails the same way;TZ=UTCpasses — which is why CI (UTC) is green and the bug goes unnoticed.Root cause (suspected)
The local→UTC conversion in the setter/revive path (
rebuild_local_with/ the components→timestamp helper incrates/perry-runtime/src/date.rs) applies the timezone offset at the current time rather than the offset at the target instant. Per ECMA-262LocalTZA(t, false)/ MakeDay semantics, the offset must be computed for the time value being constructed (and needs the usual fixed-point iteration around DST transitions, since the offset depends on the result).getHours()decodes with the offset at the stored instant (correct), so the two disagree by exactly the DST delta whenever the construction-time offset ≠ target-date offset.Impact
Any local-time Date setter (
setFullYear/setMonth/setDate/setHours/…) and likelynew Date(y, m, d, …)local construction is off by the DST delta when the target date is on the other side of a DST boundary from "now". Affects real programs, not just the test.Found while triaging PR #4924 (the test failure reproduces on unmodified
main; it is unrelated to that PR's changes).