From ec06c101c0bc5554690d4e2a2f46a0ea8b29ea2b Mon Sep 17 00:00:00 2001 From: Paul Dicker Date: Mon, 9 Sep 2024 11:59:08 +0200 Subject: [PATCH 1/4] Test numeric time zone names --- chrono-tz/src/lib.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/chrono-tz/src/lib.rs b/chrono-tz/src/lib.rs index 75bdfd3..578c9a1 100644 --- a/chrono-tz/src/lib.rs +++ b/chrono-tz/src/lib.rs @@ -148,7 +148,10 @@ pub use crate::IANA_TZDB_VERSION; #[cfg(test)] mod tests { + use super::Africa::Addis_Ababa; use super::America::Danmarkshavn; + use super::America::Scoresbysund; + use super::Antarctica::Casey; use super::Asia::Dhaka; use super::Australia::Adelaide; use super::Europe::Berlin; @@ -496,4 +499,19 @@ mod tests { assert_eq!(4, numbers.len()); assert!(IANA_TZDB_VERSION.ends_with(|c: char| c.is_ascii_lowercase())); } + + #[test] + fn test_numeric_names() { + let dt = Scoresbysund + .with_ymd_and_hms(2024, 05, 01, 0, 0, 0) + .unwrap(); + assert_eq!(format!("{}", dt.offset()), "-01"); + assert_eq!(format!("{:?}", dt.offset()), "-01"); + let dt = Casey.with_ymd_and_hms(2022, 11, 01, 0, 0, 0).unwrap(); + assert_eq!(format!("{}", dt.offset()), "+11"); + assert_eq!(format!("{:?}", dt.offset()), "+11"); + let dt = Addis_Ababa.with_ymd_and_hms(1937, 02, 01, 0, 0, 0).unwrap(); + assert_eq!(format!("{}", dt.offset()), "+0245"); + assert_eq!(format!("{:?}", dt.offset()), "+0245"); + } } From ad078e33dad1ca4c43396eef6b1f31c4b721695e Mon Sep 17 00:00:00 2001 From: Paul Dicker Date: Mon, 9 Sep 2024 11:04:11 +0200 Subject: [PATCH 2/4] Make timezone name optional --- chrono-tz-build/src/lib.rs | 16 +++++++++--- chrono-tz/src/timezone_impl.rs | 41 ++++++++++++++++++++++++------ chrono-tz/src/timezones.rs.example | 40 ++++++++++++++--------------- 3 files changed, 65 insertions(+), 32 deletions(-) diff --git a/chrono-tz-build/src/lib.rs b/chrono-tz-build/src/lib.rs index 0552f03..dd30575 100644 --- a/chrono-tz-build/src/lib.rs +++ b/chrono-tz-build/src/lib.rs @@ -41,14 +41,18 @@ fn format_rest(rest: Vec<(i64, FixedTimespan)>) -> String { }, ) in rest { + let timespan_name = match name.as_ref() { + "%z" => None, + name => Some(name), + }; ret.push_str(&format!( " ({start}, FixedTimespan {{ \ - utc_offset: {utc}, dst_offset: {dst}, name: \"{name}\" \ + utc_offset: {utc}, dst_offset: {dst}, name: {name:?} \ }}),\n", start = start, utc = utc_offset, dst = dst_offset, - name = name, + name = timespan_name, )); } ret.push_str(" ]"); @@ -230,6 +234,10 @@ impl FromStr for Tz {{ for zone in &zones { let timespans = table.timespans(zone).unwrap(); let zone_name = convert_bad_chars(zone); + let timespan_name = match timespans.first.name.as_ref() { + "%z" => None, + name => Some(name), + }; writeln!( timezone_file, " Tz::{zone} => {{ @@ -238,7 +246,7 @@ impl FromStr for Tz {{ first: FixedTimespan {{ utc_offset: {utc}, dst_offset: {dst}, - name: \"{name}\", + name: {name:?}, }}, rest: REST }} @@ -247,7 +255,7 @@ impl FromStr for Tz {{ rest = format_rest(timespans.rest), utc = timespans.first.utc_offset, dst = timespans.first.dst_offset, - name = timespans.first.name, + name = timespan_name, )?; } write!( diff --git a/chrono-tz/src/timezone_impl.rs b/chrono-tz/src/timezone_impl.rs index 77d60d6..490c78d 100644 --- a/chrono-tz/src/timezone_impl.rs +++ b/chrono-tz/src/timezone_impl.rs @@ -1,5 +1,5 @@ use core::cmp::Ordering; -use core::fmt::{Debug, Display, Error, Formatter}; +use core::fmt::{Debug, Display, Error, Formatter, Write}; use chrono::{ Duration, FixedOffset, LocalResult, NaiveDate, NaiveDateTime, NaiveTime, Offset, TimeZone, @@ -26,7 +26,7 @@ pub struct FixedTimespan { /// The additional offset from UTC for this timespan; typically for daylight saving time pub dst_offset: i32, /// The name of this timezone, for example the difference between `EDT`/`EST` - pub name: &'static str, + pub name: Option<&'static str>, } impl Offset for FixedTimespan { @@ -37,13 +37,38 @@ impl Offset for FixedTimespan { impl Display for FixedTimespan { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { - write!(f, "{}", self.name) + if let Some(name) = self.name { + return write!(f, "{}", name); + } + let offset = self.utc_offset + self.dst_offset; + let (sign, off) = if offset < 0 { + ('-', -offset) + } else { + ('+', offset) + }; + + let minutes = off / 60; + let secs = (off % 60) as u8; + let mins = (minutes % 60) as u8; + let hours = (minutes / 60) as u8; + + assert!( + secs == 0, + "numeric names are not used if the offset has fractional minutes" + ); + + f.write_char(sign)?; + write!(f, "{:02}", hours)?; + if mins != 0 { + write!(f, "{:02}", mins)?; + } + Ok(()) } } impl Debug for FixedTimespan { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { - write!(f, "{}", self.name) + Display::fmt(self, f) } } @@ -104,13 +129,13 @@ pub trait OffsetComponents { /// let london_time = London.ymd(2016, 2, 10).and_hms(12, 0, 0); /// assert_eq!(london_time.offset().tz_id(), "Europe/London"); /// // London is normally on GMT -/// assert_eq!(london_time.offset().abbreviation(), "GMT"); +/// assert_eq!(london_time.offset().abbreviation(), Some("GMT")); /// /// let london_summer_time = London.ymd(2016, 5, 10).and_hms(12, 0, 0); /// // The TZ ID remains constant year round /// assert_eq!(london_summer_time.offset().tz_id(), "Europe/London"); /// // During the summer, this becomes British Summer Time -/// assert_eq!(london_summer_time.offset().abbreviation(), "BST"); +/// assert_eq!(london_summer_time.offset().abbreviation(), Some("BST")); /// # } /// ``` pub trait OffsetName { @@ -121,7 +146,7 @@ pub trait OffsetName { /// This takes into account any special offsets that may be in effect. /// For example, at a given instant, the time zone with ID *America/New_York* /// may be either *EST* or *EDT*. - fn abbreviation(&self) -> &str; + fn abbreviation(&self) -> Option<&str>; } impl TzOffset { @@ -155,7 +180,7 @@ impl OffsetName for TzOffset { self.tz.name() } - fn abbreviation(&self) -> &str { + fn abbreviation(&self) -> Option<&str> { self.offset.name } } diff --git a/chrono-tz/src/timezones.rs.example b/chrono-tz/src/timezones.rs.example index 1104124..afb427a 100644 --- a/chrono-tz/src/timezones.rs.example +++ b/chrono-tz/src/timezones.rs.example @@ -39,15 +39,15 @@ impl TimeSpans for Tz { match *self { Tz::America__New_York => { const REST: &'static [(i64, FixedTimespan)] = &[ - (-2717650800, FixedTimespan { utc_offset: -18000, dst_offset: 0, name: "EST" }), - (-1633280400, FixedTimespan { utc_offset: -18000, dst_offset: 3600, name: "EDT" }), - (-1615140000, FixedTimespan { utc_offset: -18000, dst_offset: 0, name: "EST" }), + (-2717650800, FixedTimespan { utc_offset: -18000, dst_offset: 0, name: Some("EST") }), + (-1633280400, FixedTimespan { utc_offset: -18000, dst_offset: 3600, name: Some("EDT") }), + (-1615140000, FixedTimespan { utc_offset: -18000, dst_offset: 0, name: Some("EST") }), ]; FixedTimespanSet { first: FixedTimespan { utc_offset: -17762, dst_offset: 0, - name: "LMT", + name: Some("LMT"), }, rest: REST } @@ -55,15 +55,15 @@ impl TimeSpans for Tz { Tz::America__Toronto => { const REST: &'static [(i64, FixedTimespan)] = &[ - (-2366736148, FixedTimespan { utc_offset: -18000, dst_offset: 0, name: "EST" }), - (-1632070800, FixedTimespan { utc_offset: -18000, dst_offset: 3600, name: "EDT" }), - (-1615140000, FixedTimespan { utc_offset: -18000, dst_offset: 0, name: "EST" }), + (-2366736148, FixedTimespan { utc_offset: -18000, dst_offset: 0, name: Some("EST") }), + (-1632070800, FixedTimespan { utc_offset: -18000, dst_offset: 3600, name: Some("EDT") }), + (-1615140000, FixedTimespan { utc_offset: -18000, dst_offset: 0, name: Some("EST") }), ]; FixedTimespanSet { first: FixedTimespan { utc_offset: -19052, dst_offset: 0, - name: "LMT", + name: Some("LMT"), }, rest: REST } @@ -71,15 +71,15 @@ impl TimeSpans for Tz { Tz::Europe__London => { const REST: &'static [(i64, FixedTimespan)] = &[ - (-3852662325, FixedTimespan { utc_offset: 0, dst_offset: 0, name: "GMT" }), - (-1691964000, FixedTimespan { utc_offset: 0, dst_offset: 3600, name: "BST" }), - (-1680472800, FixedTimespan { utc_offset: 0, dst_offset: 0, name: "GMT" }), + (-3852662325, FixedTimespan { utc_offset: 0, dst_offset: 0, name: Some("GMT") }), + (-1691964000, FixedTimespan { utc_offset: 0, dst_offset: 3600, name: Some("BST") }), + (-1680472800, FixedTimespan { utc_offset: 0, dst_offset: 0, name: Some("GMT") }), ]; FixedTimespanSet { first: FixedTimespan { utc_offset: -75, dst_offset: 0, - name: "LMT", + name: Some("LMT"), }, rest: REST } @@ -87,15 +87,15 @@ impl TimeSpans for Tz { Tz::Europe__Moscow => { const REST: &'static [(i64, FixedTimespan)] = &[ - (-2840149817, FixedTimespan { utc_offset: 9017, dst_offset: 0, name: "MMT" }), - (-1688265017, FixedTimespan { utc_offset: 9079, dst_offset: 0, name: "MMT" }), - (-1656819079, FixedTimespan { utc_offset: 9079, dst_offset: 3600, name: "MST" }), + (-2840149817, FixedTimespan { utc_offset: 9017, dst_offset: 0, name: Some("MMT") }), + (-1688265017, FixedTimespan { utc_offset: 9079, dst_offset: 0, name: Some("MMT") }), + (-1656819079, FixedTimespan { utc_offset: 9079, dst_offset: 3600, name: Some("MST") }), ]; FixedTimespanSet { first: FixedTimespan { utc_offset: 9017, dst_offset: 0, - name: "LMT", + name: Some("LMT"), }, rest: REST } @@ -103,15 +103,15 @@ impl TimeSpans for Tz { Tz::Europe__Rome => { const REST: &'static [(i64, FixedTimespan)] = &[ - (-3259097396, FixedTimespan { utc_offset: 2996, dst_offset: 0, name: "RMT" }), - (-2403564596, FixedTimespan { utc_offset: 3600, dst_offset: 0, name: "CET" }), - (-1690851600, FixedTimespan { utc_offset: 3600, dst_offset: 3600, name: "CEST" }), + (-3259097396, FixedTimespan { utc_offset: 2996, dst_offset: 0, name: Some("RMT") }), + (-2403564596, FixedTimespan { utc_offset: 3600, dst_offset: 0, name: Some("CET") }), + (-1690851600, FixedTimespan { utc_offset: 3600, dst_offset: 3600, name: Some("CEST") }), ]; FixedTimespanSet { first: FixedTimespan { utc_offset: 2996, dst_offset: 0, - name: "LMT", + name: Some("LMT"), }, rest: REST } From ebaaf075712f5f82fc7a9d6f0fc8f8d569db7904 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Sat, 7 Sep 2024 09:52:22 +0200 Subject: [PATCH 3/4] Update tz submodule to 2024b --- chrono-tz/tz | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chrono-tz/tz b/chrono-tz/tz index 380c07c..6903dde 160000 --- a/chrono-tz/tz +++ b/chrono-tz/tz @@ -1 +1 @@ -Subproject commit 380c07cef01c71c1f93e9709d9f8c79b91cff063 +Subproject commit 6903dde39ed637adaafc352c4b6993739253f058 From a07204f87e42c728588843238dae2d8a1bee3cee Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Sat, 7 Sep 2024 09:52:55 +0200 Subject: [PATCH 4/4] Bump version number to 0.10.0 --- chrono-tz/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chrono-tz/Cargo.toml b/chrono-tz/Cargo.toml index d554593..d80d92f 100644 --- a/chrono-tz/Cargo.toml +++ b/chrono-tz/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chrono-tz" -version = "0.9.0" +version = "0.10.0" edition = "2021" rust-version = "1.60" build = "build.rs"