Thanks to visit codestin.com
Credit goes to Github.com

Skip to content

TimeZone implementations for rust-chrono from the IANA database

License

Notifications You must be signed in to change notification settings

dickermoshe/chrono-tz

 
 

Repository files navigation

Chrono-TZ

Chrono-TZ GitHub Actions Chrono-TZ on crates.io Chrono-TZ on docs.rs Chat

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 and parse-zoneinfo.

Documentation

Documentation is hosted on docs.rs

Examples

Create a time in one timezone and convert it to UTC

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

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.

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.

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

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

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

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

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:

[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:

[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 Generated Timezone Table

Chrono-tz by default generates timezone data for all entries in the IANA database from the years 1800 to 2100. If you are only interested in a subset, you can reduce the size of the generated database in two ways:

  • Select only the timezone names you care about.
  • Limit the generated transition data to a bounded timestamp range.

Both options are controlled via environment variables and should be set in your top-level build.

Limiting the Table to Zones of Interest

Enable the filter-by-regex feature and set CHRONO_TZ_TIMEZONE_FILTER to a regular expression matching the timezone names you want:

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.

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".

Limiting the Table to a Timestamp Range

If you only care about timezone behavior within a bounded period, enable filter-by-range and set CHRONO_TZ_TIME_RANGE to a Rust-style timestamp range in Unix seconds:

# Only keep data from 2020-01-01 to 2030-01-01 UTC (Exclusive)
CHRONO_TZ_TIME_RANGE="1577836800..1893456000" cargo build

You may also omit the start or end of the range to only keep data before or after a certain time.

# Only keep data from 2020-01-01 UTC onwards
CHRONO_TZ_TIME_RANGE="1577836800.." cargo build

# Only keep data up to 2020-01-01 UTC
CHRONO_TZ_TIME_RANGE="..1577836800" cargo build

For timestamps outside the configured range, chrono-tz will use the time zone in effect at the nearest point within the configured range. For example, if your range ends on January 1, 2030, then a date in July 2035 will use which ever was in effect on January 1, 2030.

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

About

TimeZone implementations for rust-chrono from the IANA database

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Rust 100.0%