Skip to content

fix(localzone): name the zone by the rules the clock runs on - #1945

Open
frahlg wants to merge 1 commit into
masterfrom
fix/name-copied-localtime
Open

frahlg wants to merge 1 commit into
masterfrom
fix/name-copied-localtime

Conversation

@frahlg

@frahlg frahlg commented Oct 31, 2026 •

Copy link
Copy Markdown
Member

Problem

A tester set a car's goal to 100 % by 17:00 on Sunday. The iPhone app showed "100 % by 17:00 on Sun" and, under it, "Next: tomorrow 18:00".

The box plans a goal's clock (ready_by_min, time_of_day_min) in time.Local. When time.Local is UTC, 17:00 is 17:00 UTC, which is 18:00 in Stockholm in winter. Core's DST handling is correct. The app hid the gap: it read a box zone of "UTC" as "the box names no zone" and showed the goal on the phone's clock. It did that because Core also says UTC when it is not:

  • Debian links /etc/localtime to Etc/UTC. A container that mounts the host's file (-v /etc/localtime:/etc/localtime:ro) overwrites Etc/UTC itself, so the link, /etc/timezone and the file all say Etc/UTC while Go runs on the host's rules. This is the open P2 on fix(core): name the box's time zone instead of "Local" #1585.
  • A copied /etc/localtime with no link and no /etc/timezone fell back to UTC.

So clients cannot trust "UTC" today, and the app's guess is right only by luck.

Change

localzone.Name() returns a name only when that zone has time.Local's rules:

  • Each candidate (TZ, the link, /etc/timezone) must show the same UTC offset as time.Local at every instant from 1970 to 2038.
  • A UTC name (UTC, Etc/UTC, GMT…) also needs a clock that is UTC by Go's built-in UTC. That catches the overwritten Etc/UTC.
  • A copied /etc/localtime is named by the regular Area/City file under the zoneinfo tree with the same bytes, else the first with the same rules. Links and posix/right are skipped.
  • An unknown TZ now gives UTC, because Go runs on UTC then. Before, it named the host link's zone.

Paired with srcfl/ftw-app#136. That PR makes the app trust "UTC" from the box and say the goal's time is UTC.

Evidence

  • New tests in go/internal/localzone. TestAMountOverTheEtcUTCLinkIsNotUTC fails without the UTC check (zone = "Etc/UTC", want Europe/Stockholm). The copied-file tests fail without the zoneinfo match (zone = "UTC").

  • A real run in debian:trixie-slim with tzdata (linux/arm64 under Docker Desktop), printing the name and 16:00Z on the local clock:

    Container Before After
    no zone Etc/UTC, 16:00 UTC Etc/UTC, 16:00 UTC
    host's Stockholm file mounted Etc/UTC, 17:00 CET Europe/Berlin, 17:00 CET
    TZ=Europe/Stockholm Europe/Stockholm Europe/Stockholm
    Debian's Stockholm copied as a file UTC, 17:00 CET Europe/Stockholm, 17:00 CET

    The mounted file came from macOS's tzdata, so its bytes differ; it is named by rules, and Berlin is the first zone with Stockholm's rules since 1980. The tree walk took about 20 ms, once per process.

  • make verify passes locally.

Not in this PR

  • The shipped compose files pass no zone, so a Docker box runs on UTC. Now the box says so and the app shows it, but the owner still has to set TZ for goals on their own clock.
  • A copied file on a host with no zoneinfo tree still gives UTC.

🤖 Generated with Claude Code

A Docker box that mounts the host's /etc/localtime ran on the host's rules
but told clients it was on Etc/UTC: Debian links /etc/localtime to Etc/UTC,
so the mount overwrites that file, and /etc/timezone keeps the image's name.
Clients then read the household clock (a car's ready time, a goal's days)
an hour or two off.

Every name candidate must now have time.Local's rules from 1970 to 2038,
and a UTC name needs a clock that is UTC. A copied /etc/localtime is named
by the zoneinfo file with the same bytes, else the first with the same rules.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-31T15:44:44.112178Z f77294e PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

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.

1 participant