timezone-data 0.1.0

no_std, no-alloc parser for embedded IANA TZif timezone data: transitions, zone types, POSIX TZ rules, leap seconds, and zone metadata.
Documentation
  • Coverage
  • 100%
    54 out of 54 items documented1 out of 4 items with examples
  • Size
  • Source code size: 494.27 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 942.38 kB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 3s Average build duration of successful builds.
  • all releases: 3s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • KarpelesLab/timezone-data-rs
    0 0 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • MagicalTux

timezone-data

A #![no_std], allocation-free Rust crate that parses IANA TZif timezone files and exposes the raw timezone data most libraries keep private: transitions, zone types, POSIX TZ rules, leap seconds, and per-zone metadata.

Timezone data is compiled from the official IANA source and embedded in the crate as an uncompressed zip archive, so there is no dependency on the host system's timezone files — and no external crate dependencies at all.

This is a Rust port of the Go package gotz.

Highlights

  • no_std + no alloc. Everything borrows into the embedded &'static bytes and decodes lazily through iterators. Nothing is heap-allocated.
  • Zero dependencies.
  • Complete IANA database embedded (600 entries, including the zone1970.tab and iso3166.tab metadata tables).

Usage

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; [Zone::raw_data] also returns the original TZif bytes for feeding into another parser.

API overview

Item Description
load(name) -> Result<Zone, Error> Load a zone by IANA name (""/"UTC" → UTC).
load_insensitive(name) Load with case-insensitive fallback.
parse(name, data) Parse arbitrary TZif bytes.
names() Iterate every embedded entry 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.

Updating the embedded data

zoneinfo.zip is committed to the repository. To refresh it from a new IANA release, compile the tzdata with zic and repackage it with no compression (STORE) — the embedded reader does not implement inflate. The original gotz repository's update.sh / mkzip.go produce a compatible archive; copy the resulting zoneinfo.zip into this crate's root and rebuild.

License

MIT. Timezone data is in the public domain (IANA).