184 lines
5.4 KiB
Markdown
184 lines
5.4 KiB
Markdown
# Chrono-TZ
|
|
|
|
`Chrono-TZ` is a library that provides implementors of the
|
|
[`TimeZone`][timezone] trait for [`rust-chrono`][chrono]. The
|
|
impls are generated by a build script using the [`IANA database`][iana]
|
|
and [`parse-zoneinfo`][parse_zoneinfo].
|
|
|
|
[chrono]: https://github.com/lifthrasiir/rust-chrono
|
|
[timezone]: https://lifthrasiir.github.io/rust-chrono/chrono/offset/trait.TimeZone.html
|
|
[iana]: http://www.iana.org/time-zones
|
|
[parse_zoneinfo]: https://github.com/djzin/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:
|
|
|
|
```toml
|
|
[dependencies]
|
|
chrono-tz = { version = "0.6", features = [ "filter-by-regex" ] }
|
|
```
|
|
|
|
```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
|