Timezone data on Windows: tzdb.system cannot work there #4
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
tzdb.systemcannot work on Windows. Every entry insearch_directoriesis a Unix path and
default_localtimeis/etc/localtime; they compilethere and fail at runtime, so a caller gets a file-not-found rather than
anything that explains itself.
Windows keeps its zone data in the registry under
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones, asTZIblobs plus
Dynamic DSTyear-keyed rules, under Windows zone names suchas
Central Standard Time. That is a different binary format with farless history than IANA, and mapping the names either way needs CLDR's
windowsZones.xml.-Dembed-tzdataalready covers Windows completely: it needs no filesystemand no allocator, and the data is the same IANA release everywhere.
Worth doing, cheapest first:
Say so in the README. It currently names Windows in a single clause
beside scratch containers and cross-compiled binaries
(
README.md:146), which undersells it: Windows is the only one of thethree where the system path cannot work at all.
Add a comptime
system.available, false on Windows, and make thesearch list empty there. A caller then gets a signal it can branch on
rather than a runtime failure on a path that never existed. The
-Dno-system-tzdatamachinery added in9c9b5b7is already this shape.Only if someone actually wants the machine's own zone on Windows:
GetDynamicTimeZoneInformation, an embedded CLDR table to reach anIANA name, then
embedded.load. That is a name lookup rather than adata source, and still requires
-Dembed-tzdatafor the data itself.I would not write a registry reader. 1 and 2 are small and make the
current situation honest; 3 is a real project and only pays off for a
program that must follow the machine's own setting.
Done in
71674f1, all three parts.1 and 2.
system.availableis false on Windows,search_directoriesis empty there, and
load,loadLocalandversionrefuse witherror.NoSystemDatabasebefore touching the filesystem rather thanproducing a file-not-found about a path that never existed. The README has
its own section now instead of the clause beside scratch containers.
3.
tzdb.windowsdoes the name lookup:GetDynamicTimeZoneInformationfor the invariantTimeZoneKeyName,CLDR's table for the IANA name,
embedded.loadfor the data. Each step ispublic on its own, and
ianaNameis a plain table lookup that works on anytarget. The registry is still not read, for the reason the issue gives.
The Win32 call is zigwin32, lazy and only when the target is Windows -- the
same shape zregex uses it in. CLDR's table is checked into the tree as
src/windowszones.zigrather than fetched: five kilobytes of names thatchange about once a year, against a dependency and a network round trip in
front of every Windows build.
zig build windowszones -Dwindowszones-xml=...regenerates it and reproduces the checked-in filebyte for byte.
What says it works. Wine, in a devShell of its own since nothing else
here needs it. CI cross-compiles the whole suite to
x86_64-windowsandruns it under Wine, so the Win32 call really happens and the name really
gets looked up. I checked the tests bite by breaking each half in turn --
reading
DaylightNameinstead of the key name, and making the table alwaysmiss -- and both failed. End to end under Wine, for each machine zone
tried:
A further test walks all 139 mappings and loads every one from the embedded
database, which is what would catch a name CLDR mapped in 2021a that IANA
has since dropped.
Two things fell out.
zig build test -Dtarget=...used to fail on theoracle steps, which link a host executable against the library; they now
take a host-built copy, which is the same code and the same answers. And
zig fmt --check .walks zigwin32's hundred thousand generated lines whenthe package cache is inside the tree, so CI excludes
zig-pkg.