fix(expression): honour TZ when resolving the local timezone - #511
Closed
phenixrizen wants to merge 4 commits into
Closed
fix(expression): honour TZ when resolving the local timezone#511phenixrizen wants to merge 4 commits into
phenixrizen wants to merge 4 commits into
Conversation
phenixrizen
force-pushed
the
fix/local-timezone-ignores-tz
branch
from
August 27, 2026 11:47
458d0ec to
ecc18a0
Compare
This repository is a maintained fork of gorules/zen. Nothing said so, and the inherited README carried upstream's "we can't accept code contributions" policy, which is the opposite of this fork's. Adds what a fork needs and inherited none of: CONTRIBUTING.md, SECURITY.md, CODEOWNERS, a pull request template, issue forms, and a code of conduct. Guards every publish job against running on a fork. The inherited workflows push to crates.io, npm, PyPI, NuGet, and the gorules/zen-go repository under upstream's package names, and release-please cuts the tags that drive them. A fork must build and test but never publish, so each is now conditioned on the canonical repository. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
phenixrizen
force-pushed
the
fix/local-timezone-ignores-tz
branch
from
August 27, 2026 11:55
ecc18a0 to
2d7a48a
Compare
4 tasks
phenixrizen
force-pushed
the
fix/local-timezone-ignores-tz
branch
from
August 27, 2026 12:02
2d7a48a to
215f41b
Compare
MIT requires retaining the original copyright notice, so the upstream line stays and a second line is added for this fork's modifications. Also renames the reference-data environment variable to ZEN_CATALOG_DIR. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
phenixrizen
force-pushed
the
fix/local-timezone-ignores-tz
branch
from
August 27, 2026 12:06
215f41b to
4a743a4
Compare
If this fork is maintained, it has to be installable. It could not publish
before: every package name belonged to upstream, so the release jobs were
either guarded off or would have failed on a registry we do not own.
Renames the published artifacts and removes the guards:
crates.io zen-engine -> phenixrizen-zen-engine (and -expression,
-types, -tmpl, -macros)
npm @gorules/... -> @phenixrizen/zen-engine
PyPI zen-engine -> phenixrizen-zen-engine
NuGet GoRules.ZenEngine -> PhenixRizen.ZenEngine
Each Rust crate gains an explicit [lib] name matching its old package name,
so `use zen_engine::...` still resolves and no source file changes. Dependents
keep their familiar key and carry `package = "..."`.
Repoints the Go release job at phenixrizen/zen-go, and updates crate metadata
(authors, repository, homepage) to this fork.
README: badges, install snippets and the bindings list now name the fork's
packages. Drops upstream's platform section and marketing images, which
advertise a product this repository is not part of.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
`iana_time_zone::get_timezone()` reads the system zone from /etc/localtime and
ignores the environment, so a process started with `TZ=UTC` still computed dates
in the host's zone. Every other date implementation on Unix treats TZ as the
override, and in a container that mounts the host's /etc/localtime it is the only
way to pin the zone at all.
This also makes test_dates_csv pass off a UTC host. It sets TZ=UTC itself, which
until now did nothing: on a machine in America/Chicago, `d('2023-10-15')`
evaluated to 2023-10-15T00:00:00-05:00 against an expected ...Z, so the test
passed only where /etc/localtime already said UTC. CI runners are UTC, which is
why it has been green.
The zone is resolved once and cached, so ordering matters: standard.csv contains
date expressions too, and whichever date-touching test ran first seeded the cache
for the rest. Both now pin the zone, and the resolution is documented as
first-use-wins so a future test does not reintroduce the race.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
phenixrizen
force-pushed
the
fix/local-timezone-ignores-tz
branch
from
August 27, 2026 12:15
4a743a4 to
ffa8818
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
helper::tz()resolves the local timezone withiana_time_zone::get_timezone(), which reads the system zone from/etc/localtimeand ignores the environment. A process started withTZ=UTCtherefore still computes dates in the host's zone.On Unix,
TZis the conventional override — chrono'sLocal, Python, and Go all honour it — and in a container that mounts the host's/etc/localtimeit is the only way to pin the zone at all.How it surfaces
test_dates_csvsetsTZ=UTCitself, and that call currently does nothing. On a machine inAmerica/Chicago:Demonstrated directly:
The suite passes only where
/etc/localtimealready says UTC. GitHub runners are UTC, which is why this has stayed green.A second, latent issue
The zone is resolved once and cached in a
OnceLock, so ordering decides the result.standard.csvcontains date expressions too, andtest_standard_csvruns in parallel — whichever date-touching test ran first seeded the cache for the rest. SettingTZinside one test could not fix that on its own.The change
tz()consultsTZfirst, falling back toiana_time_zoneand then UTC.Verification
On a host in
America/Chicagowith noTZexported, the full suite now passes — 46 suites, previously 45 withtest_dates_csvfailing. Six consecutive runs ofzen-expression --test isolateto check the ordering hazard is genuinely closed. Behaviour on a UTC host is unchanged.No new dependencies; 24 lines added across two files.