# Chrono-TZ [![Chrono-TZ GitHub Actions][gh-image]][gh-checks] [![Chrono-TZ on crates.io][cratesio-image]][cratesio] [![Chrono-TZ on docs.rs][docsrs-image]][docsrs] [![Chat][discord-image]][discord] [gh-image]: https://github.com/chronotope/chrono-tz/actions/workflows/rust.yml/badge.svg [gh-checks]: https://github.com/chronotope/chrono-tz/actions/workflows/rust.yml [cratesio-image]: https://img.shields.io/crates/v/chrono-tz.svg [cratesio]: https://crates.io/crates/chrono-tz [docsrs-image]: https://docs.rs/chrono-tz/badge.svg [docsrs]: https://docs.rs/chrono-tz [discord-image]: https://img.shields.io/discord/976380008299917365?logo=discord [discord]: https://discord.gg/sXpav4PS7M `Chrono-TZ` is a library that provides implementors of the [`TimeZone`] trait for [chrono]. The impls are generated by a build script using the [`IANA database`][iana] and [`parse-zoneinfo`]. [chrono]: https://crates.io/crates/chrono [`TimeZone`]: https://docs.rs/chrono/latest/chrono/trait.TimeZone.html [iana]: http://www.iana.org/time-zones [`parse-zoneinfo`]: https://crates.io/crates/parse-zoneinfo ## Documentation Documentation is hosted on [docs.rs][docsrs] [docsrs]: https://docs.rs/chrono-tz ## Examples Create a time in one timezone and convert it to UTC ```rust 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)); ``` Create a naive datetime and convert it to a timezone-aware datetime ```rust 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"); ``` London and New York change their clocks on different days in March so only have a 4-hour difference on certain days. ```rust use chrono::TimeZone; use chrono_tz::Europe::London; use chrono_tz::America::New_York; let london_time = London.ymd(2016, 3, 18).and_hms(3, 0, 0); let ny_time = london_time.with_timezone(&New_York); assert_eq!(ny_time, New_York.ymd(2016, 3, 17).and_hms(23, 0, 0)); ``` You can get the raw offsets as well if you want to see the standard UTC offset as well as any special offsets in effect (such as DST) at a given time. Note that you need to import the `OffsetComponents` trait. ```rust 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)); ``` Adding 24 hours across a daylight savings change causes a change in local time ```rust use chrono::{TimeZone, Duration}; use chrono_tz::Europe::London; let dt = London.ymd(2016, 10, 29).and_hms(12, 0, 0); let later = dt + Duration::hours(24); assert_eq!(later, London.ymd(2016, 10, 30).and_hms(11, 0, 0)); ``` And of course you can always convert a local time to a unix timestamp ```rust use chrono::TimeZone; use chrono_tz::Asia::Kolkata; let dt = Kolkata.ymd(2000, 1, 1).and_hms(0, 0, 0); let timestamp = dt.timestamp(); assert_eq!(timestamp, 946665000); ``` Pretty-printing a string will use the correct abbreviation for the timezone ```rust use chrono::TimeZone; use chrono_tz::Europe::London; let dt = London.ymd(2016, 5, 10).and_hms(12, 0, 0); assert_eq!(dt.to_string(), "2016-05-10 12:00:00 BST"); assert_eq!(dt.to_rfc3339(), "2016-05-10T12:00:00+01:00"); ``` You can convert a timezone string to a timezone using the FromStr trait ```rust 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"); ``` ## `no_std` Support To use this library without depending on the Rust standard library, put this in your `Cargo.toml`: ```toml [dependencies] chrono = { version = "0.4", default-features = false } chrono-tz = { version = "0.5", default-features = false } ``` If you are using this library in an environment with limited program space, such as a microcontroller, take note that you will also likely need to enable optimizations and Link Time Optimization: ```toml [profile.dev] opt-level = 2 lto = true [profile.release] lto = true ``` Otherwise, the additional binary size added by this library may overflow available program space and trigger a linker error. ## Limiting the Timezone Table to Zones of Interest `Chrono-tz` by default generates timezones for all entries in the [IANA database][]. If you are interested in only a few timezones you can use enable the `filter-by-regex` feature and set an environment variable to select them. The environment variable is called `CHRONO_TZ_TIMEZONE_FILTER` and is a regular expression. It should be specified in your top-level build: ```sh CHRONO_TZ_TIMEZONE_FILTER="(Europe/London|US/.*)" cargo build ``` This can significantly reduce the size of the generated database, depending on how many timezones you are interested in. Wikipedia has an [article listing the timezone names][wiki-list]. The filtering applied is liberal; if you use a pattern such as "US/.*" then `chrono-tz` will include all the zones that are linked, such as "America/Denver", not just "US/Mountain". [IANA database]: http://www.iana.org/time-zones [wiki-list]: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones ## Developing `chrono-tz` uses git submodules, so in order to build locally you will need to run `git submodule init` and `git submodule update`. ## Future Improvements - Handle leap seconds - Handle Julian to Gregorian calendar transitions - Load tzdata always from latest version - Dynamic tzdata loading