What is Chrono-TZ
mainTimeZone trait for the chrono crate. It uses the IANA database and parse-zoneinfo to generate timezone data via a build script, allowing you to work with specific geographic timezones in your Rust applications.repository·main·Indexed 42 days ago
https://github.com/chronotope/chrono-tzRust library providing IANA timezone implementations for the chrono crate. It allows developers to perform timezone-aware datetime arithmetic, convert between timezones, and handle DST gaps and overlaps using the IANA database. Version 0.11.0 supports no_std environments and provides features to filter the timezone table via regex to reduce binary size.
TimeZone trait for the chrono crate. It uses the IANA database and parse-zoneinfo to generate timezone data via a build script, allowing you to work with specific geographic timezones in your Rust applications.parse-zoneinfo is a Rust library for reading the text format of the IANA zoneinfo database. It is a fork of zoneinfo_parse and is used by chrono-tz to process time zone changes and offsets.
cargo add parse-zoneinfoTo use chrono-tz in a no_std environment, disable default features for both chrono and chrono-tz in your Cargo.toml.
For resource-constrained environments like microcontrollers, it is highly recommended to enable Link Time Optimization (LTO) and set an appropriate opt-level to prevent the generated database from overflowing program space.
[dependencies]
chrono = { version = "0.4", default-features = false }
chrono-tz = { version = "0.5", default-features = false }[profile.dev]
opt-level = 2
lto = true
[profile.release]
lto = trueBy default, chrono-tz includes all timezones from the IANA database. To reduce binary size, you can enable the filter-by-regex feature and provide a regular expression via the CHRONO_TZ_TIMEZONE_FILTER environment variable during your build.
Example: To only include London and all US-based zones:
CHRONO_TZ_TIMEZONE_FILTER="(Europe/London|US/.*)" cargo build
CHRONO_TZ_TIMEZONE_FILTER="(Europe/London|US/.*)" cargo buildWhen converting local times to UTC, you may encounter gaps (non-existent times due to DST forward jumps) or overlaps (ambiguous times due to DST backward jumps).
GapInfo::new(&datetime, &timezone) to find the start and end of a gap..earliest() and .latest() on the result of a local time conversion to resolve ambiguous times.// Example of resolving ambiguous time
use chrono::TimeZone;
use chrono_tz::Europe::London;
let ambiguous = London.with_ymd_and_hms(2016, 10, 30, 1, 0, 0);
let earliest = ambiguous.earliest().unwrap();
let latest = ambiguous.latest().unwrap();In chrono-tz, timezones are composed of multiple FixedTimespans that change over time (e.g., EST and EDT for US::Eastern).
FixedTimespan: Represents a specific offset from UTC and its associated name (e.g., offset: -18000, name: "EST").TzOffset: A combination of a timezone (Tz) and a FixedTimespan. It implements chrono::Offset, allowing it to be used with the chrono crate to provide a FixedOffset via the .fix() method.The TableBuilder is used to coalesce parsed line data into a single Table structure. It handles the relationships between zones, rulesets, and links (e.g., when one zone links to another).
To use it, create a new builder, iterate through your parsed Line objects using add_line, and finally call build() to obtain the Table.
Note: The builder enforces data integrity, such as ensuring rulesets exist before they are referenced by zones and preventing duplicate zone or link definitions.
use parse_zoneinfo::line::{Line, Zone, Link};
use parse_zoneinfo::table::TableBuilder;
let mut builder = TableBuilder::new();
let zone = "Zone Pacific/Auckland 11:39:04 - LMT 1868 Nov 2";
let link = "Link Pacific/Auckland Antarctica/McMurdo";
for line in [zone, link] {
builder.add_line(Line::new(&line)?).unwrap();
}
let table = builder.build();
assert!(table.get_zoneset("Pacific/Auckland").is_some());
assert!(table.get_zoneset("Antarctica/McMurdo").is_some());
assert!(table.get_zoneset("UTC").is_none());
# Ok::<(), parse_zoneinfo::line::Error>(())You can convert a string representing a timezone (e.g., "Antarctica/South_Pole") into a Tz object using the FromStr trait via .parse().
use chrono::TimeZone;
use chrono_tz::Tz;
use chrono_tz::UTC;
let tz: Tz = "Antarctica/South_Pole".parse().unwrap();
let dt = tz.ymd(2016, 10, 22).and_hms(12, 0, 0);
let utc = dt.with_timezone(&UTC);
assert_eq!(utc.to_string(), "2016-10-21 23:00:00 UTC");Use the .from_local_datetime() method on a timezone object to convert a NaiveDateTime into a timezone-aware datetime.
use chrono::{TimeZone, NaiveDate};
use chrono_tz::Africa::Johannesburg;
let naive_dt = NaiveDate::from_ymd(2038, 1, 19).and_hms(3, 14, 08);
let tz_aware = Johannesburg.from_local_datetime(&naive_dt).unwrap();
assert_eq!(tz_aware.to_string(), "2038-01-19 03:14:08 SAST");You can create a time in a specific timezone (e.g., chrono_tz::US::Pacific) and convert it to UTC or another timezone using the .with_timezone() method.
use chrono::{TimeZone, Utc};
use chrono_tz::US::Pacific;
let pacific_time = Pacific.ymd(1990, 5, 6).and_hms(12, 30, 45);
let utc_time = pacific_time.with_timezone(&Utc);
assert_eq!(utc_time, Utc.ymd(1990, 5, 6).and_hms(19, 30, 45));To inspect the raw offsets (standard UTC offset and Daylight Savings Time offset) at a specific time, import the OffsetComponents trait and use the .offset() method.
use chrono::{Duration, TimeZone};
use chrono_tz::Europe::London;
use chrono_tz::OffsetComponents;
let london_time = London.ymd(2016, 5, 10).and_hms(12, 0, 0);
// London typically has zero offset from UTC, but has a 1h adjustment forward
// when summer time is in effect.
assert_eq!(london_time.offset().base_utc_offset(), Duration::hours(0));
assert_eq!(london_time.offset().dst_offset(), Duration::hours(1));You can iterate over all available timezone variants using the TZ_VARIANTS array.
use chrono_tz::{TZ_VARIANTS, Tz};
assert!(TZ_VARIANTS.iter().any(|v| *v == Tz::UTC));