//go:build test package scheduling // Strict timezone/DST/midnight-boundary tests for the scheduling package's // London-date derivation. All assertions use fixed time.Date instants. import ( "testing" "time" "crussell/clock" ) // TestScheduling_DefaultHours_DST_Midnight proves ApplyScheduledDefaultHours's // "today" date (derived via LondonDateString) is the LONDON calendar date, not // the UTC date. During BST, London dates begin at 23:00 UTC the previous day: // both 2026-06-14 23:30 UTC (= 2026-06-15 00:30 BST) and 2026-06-15 00:30 UTC // (= 2026-06-15 01:30 BST) fall on London date 2026-06-15 — a naive UTC date // would report 2026-06-14 for the first instant and misdate the effective day // of a staged default-hours change. func TestScheduling_DefaultHours_DST_Midnight(t *testing.T) { t.Parallel() cases := []struct { name string utc time.Time want string }{ {"00:30 BST window", time.Date(2026, 6, 14, 23, 30, 0, 0, time.UTC), "2026-06-15"}, {"01:30 BST same day", time.Date(2026, 6, 15, 0, 30, 0, 0, time.UTC), "2026-06-15"}, {"GMT midnight is UTC midnight", time.Date(2026, 1, 14, 23, 30, 0, 0, time.UTC), "2026-01-14"}, {"GMT next day", time.Date(2026, 1, 15, 0, 30, 0, 0, time.UTC), "2026-01-15"}, {"autumn BST->GMT transition day", time.Date(2026, 10, 25, 0, 30, 0, 0, time.UTC), "2026-10-25"}, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { if got := LondonDateString(tc.utc); got != tc.want { t.Errorf("LondonDateString(%s UTC) = %q, expected London date %q", tc.utc.Format(time.RFC3339), got, tc.want) } }) } // Direct proof of the DST window: the UTC date of the first instant differs // from its London date — exactly the drift the helper must absorb. boundary := time.Date(2026, 6, 14, 23, 30, 0, 0, time.UTC) if boundary.Format("2006-01-02") == LondonDateString(boundary) { t.Fatal("test setup invariant: 2026-06-14 23:30 UTC must straddle the London midnight boundary") } // The helper must be consistent with clock.London's own wall-clock for the // same instant (the production seam ApplyScheduledDefaultHours now uses). nowish := time.Date(2026, 6, 14, 23, 45, 0, 0, time.UTC) if LondonDateString(nowish) != nowish.In(clock.London).Format("2006-01-02") { t.Errorf("LondonDateString disagrees with the direct London conversion for %s", nowish.Format(time.RFC3339)) } }