Skip to content

Fix some TZ issues after sanity checking status display#19

Open
alexis-cousein wants to merge 12 commits into
mrosseel:mainfrom
alexis-cousein:fix_state_dt_tz
Open

Fix some TZ issues after sanity checking status display#19
alexis-cousein wants to merge 12 commits into
mrosseel:mainfrom
alexis-cousein:fix_state_dt_tz

Conversation

@alexis-cousein

@alexis-cousein alexis-cousein commented Jun 28, 2026

Copy link
Copy Markdown

I had noticed that when you input time/date "UTC TM" and "LCL TM" were always identical, and that when recovering time from GPS there was the expected gap between them, so I sanity checked some of the datetime timezone usage in the current code.

-The current date/time input routines are self-consistent but they store a datetime in shared_state that contains a timezone reference (to the local timezone the times were specified in), while when using the GPS everything is in UTC) .
-[bug] The status screen that displays "UTC TM" just expects the shared state to be in UTC.

Since other consumers of the shared state datetime might make the same mistake, I corrected this at both ends:
-When saving the shared state, always convert to a timezone-aware datetime that is UTC based, so that manual input time and GPS time will always behave similarly.
-Introduced a shared_state query routine utc_datetime in addition to local_datetime to avoid the ambiguous "datetime" (which just returns a valid datetime, but these can be in different timezones); the "TM UTC" visualisation now uses this.

Other changes:
-replaced pytz.timezone("UTC") by the initialized singleton pytz.utc -- more readable and faster, no need to reconstruct this object time and again.
-gps_fake now explicitly uses a UTC-timezone-stamped datetime.now(pytz.utc) , just to avoid sending "naive" datetimes around.
-catalogs.py was extracting a naive datetime.now() --expressed in the OS timezone-- and just tagged on "UTC" to make a timezone-aware datetime. This is only correct if the OS timezone is UTC, and that is unnecessarily dangerous: datetime.now(pytz.utc) is guaranteed to give you the actual time expressed in UTC, and tagged as such.
-[bug] The use of datetime.now() to get "today's date" in set_time (so that the screen for data input gets initialized to the correct date) to combine it with the time that was input is just wrong, because "today's date in UTC" might be different from the date in the target timezone (which we force before setting it), leading us to set the datetime 24 hours off in some cases. There, we need to use datetime.now(timezone) to avoid the wrong date being proposed in the datetime screen.

alexis-cousein and others added 9 commits June 28, 2026 13:43
Regression tests for SharedStateObj set_datetime / utc_datetime / local_datetime:
a naive input is interpreted as UTC, an aware-local input is normalised to UTC
in storage (so bare datetime() stays UTC), and UTC vs local read-back differ at
a non-UTC location — the status-screen bug PR brickbots#508 fixes. The clock is frozen so
datetime()'s drift term is zero and the assertions are exact.
…bots#508

ADR-0018 + Positioning CONTEXT.md glossary: shared_state civil datetime is
stored timezone-aware in UTC, normalised at the set_datetime() boundary, and
read via utc_datetime()/local_datetime(); distinguish civil datetime (the
astronomical epoch) from measurement epoch (time.time() fix-age). Captures the
GPS LST->LKT rename and the no-naive-local-persisted-data finding.
Docstrings on datetime/utc_datetime/local_datetime/set_datetime stating the
ADR-0018 contract: set_datetime is the single normalising write boundary,
callers pass tz-aware datetimes, and the stored value is always UTC-aware.
…orce DTZ

Add PiFinder/timez.py as the single sanctioned source of datetimes
(utc_now / local_now / utc_from_timestamp / parse / naive / utc) and enable
ruff's DTZ (flake8-datetimez) family repo-wide, exempting only timez.py. Every
bare datetime.now() / datetime(...) / strptime() / fromtimestamp() now routes
through timez, so 'local or UTC?' is explicit at the call site and a naive value
cannot silently reach the astronomy/ephemeris path. Also fixes a latent relabel
bug in the comets.py freshness check (a file mtime read naive-local and stamped
UTC -> now the true UTC instant via timez.utc_from_timestamp). See ADR-0018.
Civil-datetime UTC contract: docs, regression test, and timez/DTZ funnel
@alexis-cousein alexis-cousein force-pushed the fix_state_dt_tz branch 2 times, most recently from 5e02fd7 to c72f470 Compare June 29, 2026 15:00
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.

2 participants