A #![no_std], allocation-free Rust crate that exposes IANA timezone data most
libraries keep private: transitions, zone types, POSIX TZ rules, leap seconds,
and per-zone metadata.
Every zone from the official IANA source
is pre-parsed at build time into static Rust objects and embedded in the
crate, so there is no dependency on the host system's timezone files, nothing is
parsed at runtime, and there are no external crate dependencies at all. A
lookup is a binary search over &'static data.
This is a Rust port of the Go package gotz.
no_std+ noalloc. Accessors return slices that point straight at&'staticdata. Nothing is heap-allocated.- Nothing parsed at runtime, no build script. Each zone is materialised as
static
ZoneType/Transitionarrays + a const POSIX rule;load()just binary-searches a static table. - Zero dependencies.
- Complete IANA database embedded (598 zones, plus the
zone1970.tab/iso3166.tabmetadata tables).
use timezone_data::load;
let z = load("America/New_York")?;
// Inspect zone types (EST, EDT, ...).
for zt in z.types() {
println!("{} offset={} dst={}", zt.abbrev, zt.offset, zt.is_dst);
}
// Iterate historical transitions.
for t in z.transitions() {
let zt = z.type_at(t.type_idx);
println!("{} -> {}", t.when, zt.abbrev);
}
// Look up the active zone at a specific Unix timestamp.
let zt = z.lookup(1_700_000_000);
println!("zone: {} (UTC offset {})", zt.abbrev, zt.offset);
// Get the POSIX TZ rule for future transitions.
if let Some(rule) = z.extend() {
let (start, end) = rule.transitions_for_year(2025).unwrap();
println!("DST starts: {start}, ends: {end}");
}
// Country and coordinates metadata.
if let Some(m) = z.meta() {
if let Some(c) = m.countries().next() {
println!("country: {} ({})", c.name, c.code);
}
println!("location: {}, {}", m.lat, m.lon);
}
# Ok::<(), timezone_data::Error>(())Times are expressed as i64 Unix seconds — the crate is timezone-library
agnostic. If you need a chrono/time value, convert at the boundary.
| Item | Description |
|---|---|
load(name) -> Result<Zone, Error> |
Load a zone by IANA name (""/"UTC" → UTC). |
load_insensitive(name) |
Load with case-insensitive fallback. |
names() |
Iterate every IANA zone name. |
Zone::types() / type_at(i) |
Local time types (abbrev, offset, DST flag). |
Zone::transitions() |
Stored transition records. |
Zone::leap_seconds() |
Leap-second records. |
Zone::lookup(unix) |
Zone type in effect at an instant. |
Zone::transitions_for_range(start, end) |
Stored + POSIX-generated transitions in [start, end). |
Zone::extend() / extend_raw() |
Parsed / raw POSIX TZ footer. |
Zone::meta() |
Country + coordinate metadata. |
parse_posix_tz(s) |
Parse a POSIX TZ string directly. |
zoneinfo.zip is committed to the repository purely as the data source for the
generator; it is not part of the published crate. The generated table
(src/generated.rs) and the metadata tables (src/zone1970.tab,
src/iso3166.tab) are committed and are what gets shipped.
To refresh from a new IANA release:
- Compile the tzdata with
zicand repackage it as a STORE (uncompressed) zip — the generator does not implement inflate. The originalgotzrepository'supdate.sh/mkzip.goproduce a compatible archive. - Replace
zoneinfo.zipin this crate's root. - Run
cargo run --manifest-path xtask/Cargo.tomlto regeneratesrc/generated.rsand the.tabfiles, then commit the result.
CI re-runs the generator and fails if the committed output is stale, so a release always ships the current data.
MIT. Timezone data is in the public domain (IANA).