Problem
Schedule-derived line status (#26/#27) computes the service date and service windows with a naive datetime.now(), and compares them against GTFS times that are agency-local (Eastern). This silently assumes the server's local timezone is the agency timezone.
It isn't in the container: the backend image runs in UTC, so the schedule was evaluated ~4–5 hours off and out-of-service lines never dimmed (or dimmed at the wrong time).
Diagnosis (from the debugging session)
At 05:12 UTC (= 01:12 Eastern), inside the container:
- provider with naive-UTC
now → OUT: (none)
- same instant treated as Eastern →
OUT: ['RH'] (correct)
The whole backend shares this naive-local-time assumption (live-feed timestamps, staleness, and now schedule status), so the app implicitly expects to run in Eastern.
Current mitigation (already shipped)
compose.yaml pins the backend container to TZ=America/Toronto. This is a deployment config fix, not a code fix — it works but breaks again if the service is ever deployed somewhere that doesn't set TZ, or run outside compose.
Proposed code-level fix
Make the schedule logic timezone-aware regardless of server TZ:
- Introduce an agency timezone constant (
America/Toronto) via zoneinfo.
- Derive the service date and anchor service windows in agency-local time, then compare against an agency-local
now (convert datetime.now(tz=...) or the injected clock into the agency zone).
- Keep the injected-clock seam so tests stay deterministic; add a test that pins a fake
now in UTC and asserts the status matches agency-local expectations (i.e. the same instant that currently fails in UTC now resolves correctly without relying on TZ).
Acceptance criteria
Blocked by
None. Independent of the shipped mitigation.
Problem
Schedule-derived line status (#26/#27) computes the service date and service windows with a naive
datetime.now(), and compares them against GTFS times that are agency-local (Eastern). This silently assumes the server's local timezone is the agency timezone.It isn't in the container: the backend image runs in UTC, so the schedule was evaluated ~4–5 hours off and out-of-service lines never dimmed (or dimmed at the wrong time).
Diagnosis (from the debugging session)
At
05:12 UTC(=01:12Eastern), inside the container:now→OUT: (none)OUT: ['RH'](correct)The whole backend shares this naive-local-time assumption (live-feed timestamps, staleness, and now schedule status), so the app implicitly expects to run in Eastern.
Current mitigation (already shipped)
compose.yamlpins the backend container toTZ=America/Toronto. This is a deployment config fix, not a code fix — it works but breaks again if the service is ever deployed somewhere that doesn't setTZ, or run outside compose.Proposed code-level fix
Make the schedule logic timezone-aware regardless of server TZ:
America/Toronto) viazoneinfo.now(convertdatetime.now(tz=...)or the injected clock into the agency zone).nowin UTC and asserts the status matches agency-local expectations (i.e. the same instant that currently fails in UTC now resolves correctly without relying onTZ).Acceptance criteria
TZ=America/Torontoset), covered by a test.TZ=America/Torontoline incompose.yamlbecomes belt-and-suspenders rather than load-bearing (note it, optionally keep it).Blocked by
None. Independent of the shipped mitigation.