Skip to content

infinityabundance/tzselect-rs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

tzselect-rs

A faithful, memory-safe Rust port of upstream tzselect.ksh from the IANA time zone database — the interactive program that helps a user pick a TZ value by continent → country → region, by geographic coordinates (-c), by a proleptic POSIX TZ string, or by current local time.

TZDIR=/usr/share/zoneinfo tzselect-rs          # interactive (stderr/stdin); TZ on stdout
echo -e '8\n3\n1' | tzselect-rs                # scriptable, like upstream tzselect
tzselect-rs -c +4852+00220                     # nearest zones to a coordinate
tzselect-rs --help / --version

Upstream tzselect.ksh is an interactive Korn/Bash script wrapping several POSIX-awk programs. tzselect-rs ports all of it to native Rust — the menu select loop, the country/region/TZ derivation, the great-circle coordinate distance ranking, and the POSIX-TZ-string grammar (hand-parsed, so there are no runtime dependencies). Like the upstream it shells out to date for the current-time displays.

Claim boundary

tzselect-rs does not define timezone policy or choose a timezone for the user. It ports the interactive selection behaviour of upstream tzselect.ksh into Rust, using the same tzdb table surfaces (iso3166.tab, zone1970.tab), and verifies representative prompt/output paths against the upstream shell oracle. It is the user-selection layer of the Rust tzdb toolchain, beside zic-rs and the producer/QA crates (ziguard-rs, zishrink-rs, checktab-rs, checklinks-rs, checknow-rs, leapseconds-rs); it does not enter libc localtime/strftime runtime territory.

Parity contract

tzselect.ksh is interactive, so the oracle is a driven shell process and the claim is prompt/output-sequence parity. The deterministic oracle is LC_ALL=C.UTF-8 COLUMNS=1 tzselect — single-column select, raw-UTF-8 country names, bytewise sort. Against it, tzselect-rs is byte-identical on stderr (the prompts/menus), stdout (the chosen TZ), and exit status.

Classified (not byte-compared), exactly as upstream allows:

  • the two live-clock lines Selected time is now: / Universal Time is now: and the interactive time/now local-time menus — time-dependent;
  • the read tz EOF case — upstream tzselect.ksh infinite-loops on EOF during TZ-string entry (a shell while … read with no || exit); tzselect-rs exits cleanly (a deliberate, classified safer divergence);
  • wide-terminal multi-column select layout and non-UTF-8-locale iconv transliteration — shell/terminal/locale rendering details.

Evidence

  • Exhaustive enumeration: all 525 continent → country → region leaf paths (every menu choice in zone1970.tab) are byte-identical to the oracle (stderr + stdout + exit).
  • Differential sweep: 1402 / 0 random scripted navigation paths match (continent/country/region, coord, TZ-string, bad-input re-prompts, EOF), with 85 time-dependent and 38 read-EOF-hang cases cleanly classified. Receipt: reports/oracle/.
  • Kani: the menu-index guard is proven sound (items[n-1] always in bounds).
  • Fuzz: cargo +nightly fuzzposix_tz 31M execs, driver 574k execs, 0 crashes. Receipt: reports/fuzz/.

Build & test

cargo build --release
cargo test                                  # mock-host golden regression + posix_tz
cargo clippy --all-targets -- -D warnings
cargo kani --harness menu_index_guard_is_sound
bash lab/oracle/sweep.py 1000               # the oracle differential sweep (needs the 2026b lab)

License

Apache-2.0. The upstream tzselect.ksh and the tzdb tables are public domain; this Rust port is an independent reimplementation.

About

Faithful, memory-safe Rust port of upstream tzselect.ksh — the interactive IANA tzdb timezone selector. Byte-identical prompt/output parity vs the shell oracle.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors