diff --git a/components/timezone/README.md b/components/timezone/README.md index 8dd4688b425..d7631e80c05 100644 --- a/components/timezone/README.md +++ b/components/timezone/README.md @@ -6,7 +6,7 @@ Types for resolving and manipulating time zones. ## Fields -In ICU4X, a [formattable time zone](TimeZoneInfo) consists of four different fields: +In ICU4X, a [formattable time zone](TimeZoneInfo) consists of up to four different fields: 1. The time zone ID 2. The offset from UTC @@ -58,11 +58,10 @@ use icu::timezone::TimeZoneIdMapper; use tinystr::{tinystr, TinyAsciiStr}; // Create a time zone for America/Chicago at UTC-6: -let mut time_zone = TimeZoneInfo { - time_zone_id: TimeZoneIdMapper::new().iana_to_bcp47("America/Chicago"), - offset: Some("-0600".parse().unwrap()), - ..TimeZoneInfo::unknown() -}; +let mut time_zone = TimeZoneInfo::from_id_and_offset( + TimeZoneIdMapper::new().iana_to_bcp47("America/Chicago"), + "-0600".parse().unwrap(), +); // Alternatively, set it directly from the BCP-47 ID assert_eq!(time_zone.time_zone_id, TimeZoneBcp47Id(tinystr!(8, "uschi"))); diff --git a/components/timezone/src/lib.rs b/components/timezone/src/lib.rs index 1d691073d4c..a105c833d90 100644 --- a/components/timezone/src/lib.rs +++ b/components/timezone/src/lib.rs @@ -6,7 +6,7 @@ //! //! # Fields //! -//! In ICU4X, a [formattable time zone](TimeZoneInfo) consists of four different fields: +//! In ICU4X, a [formattable time zone](TimeZoneInfo) consists of up to four different fields: //! //! 1. The time zone ID //! 2. The offset from UTC @@ -58,11 +58,10 @@ //! use tinystr::{tinystr, TinyAsciiStr}; //! //! // Create a time zone for America/Chicago at UTC-6: -//! let mut time_zone = TimeZoneInfo { -//! time_zone_id: TimeZoneIdMapper::new().iana_to_bcp47("America/Chicago"), -//! offset: Some("-0600".parse().unwrap()), -//! ..TimeZoneInfo::unknown() -//! }; +//! let mut time_zone = TimeZoneInfo::from_id_and_offset( +//! TimeZoneIdMapper::new().iana_to_bcp47("America/Chicago"), +//! "-0600".parse().unwrap(), +//! ); //! //! // Alternatively, set it directly from the BCP-47 ID //! assert_eq!(time_zone.time_zone_id, TimeZoneBcp47Id(tinystr!(8, "uschi"))); diff --git a/components/timezone/src/windows_tz.rs b/components/timezone/src/windows_tz.rs index 28cb1ef91d2..d635ea2efdd 100644 --- a/components/timezone/src/windows_tz.rs +++ b/components/timezone/src/windows_tz.rs @@ -2,10 +2,11 @@ // called LICENSE at the top level of the ICU4X source tree // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). -use core::fmt::{self, Write}; +use core::fmt::Write; use icu_provider::{ - prelude::icu_locale_core::subtags::Region, DataError, DataPayload, DataProvider, + prelude::icu_locale_core::subtags::{region, Region}, + DataError, DataPayload, DataProvider, }; use crate::{ @@ -32,7 +33,7 @@ use crate::{ /// /// As such, a [`Region`] may be provided to further specify a desired territory/region when /// querying a BCP-47 identifier. If no region is provided or the specificity is not required, -/// then the territory will default to the M49 World Code, 001. +/// then the territory will default to the M.49 World Code, `001`. #[derive(Debug)] pub struct WindowsTimeZoneMapper { data: DataPayload, @@ -99,104 +100,63 @@ impl WindowsTimeZoneMapperBorrowed<'_> { } } - /// Returns the BCP-47 id for a provided windows time zone string with a case sensitive query. + /// Returns the BCP-47 ID for a provided Windows time zone and [`Region`] with a case sensitive query. /// - /// This method will return the canonical identifier for an area as no - /// territory/geo name was provided, so the mapper will use default the default M49 World code ("001"). + /// If no region is provided or the specificity is not required, + /// then the territory will default to the M.49 World Code, `001`. /// /// ```rust - /// use icu_timezone::{WindowsTimeZoneMapperBorrowed, TimeZoneBcp47Id}; + /// use icu::timezone::{WindowsTimeZoneMapper, TimeZoneBcp47Id}; + /// use icu::locale::subtags::region; /// use tinystr::tinystr; /// - /// let windows_tz_mapper = WindowsTimeZoneMapperBorrowed::new(); + /// let win_tz_mapper = WindowsTimeZoneMapper::new(); /// - /// let bcp47_id = windows_tz_mapper.windows_tz_to_bcp47_id("Central Standard Time").unwrap(); - /// assert_eq!(bcp47_id, Some(TimeZoneBcp47Id(tinystr!(8, "uschi")))); - /// ``` - pub fn windows_tz_to_bcp47_id( - &self, - windows_tz: &str, - ) -> Result, fmt::Error> { - self.windows_tz_to_bcp47_id_with_region(windows_tz, None) - } - - /// Returns the IANA identifier(s) for a provided windows zone bytes and an - /// optional geo_name bytes representing a [`Region`]. If not provided, - /// geo_name will be set to the default of "001", the M49 world code. - /// - /// If a `Region` is provided, then the returned is not guaranteed to - /// be a single identifier. The value may be a space delimited list of IANA - /// identifiers for the designated region. - /// - /// ```rust - /// use icu_timezone::{WindowsTimeZoneMapperBorrowed, TimeZoneBcp47Id}; - /// use icu_provider::prelude::icu_locale_core::subtags::Region; - /// use tinystr::tinystr; - /// - /// let win_tz_mapper = WindowsTimeZoneMapperBorrowed::new(); - /// - /// let region = None; - /// let bcp47_id = win_tz_mapper.windows_tz_to_bcp47_id_with_region("Central Standard Time", region).unwrap(); + /// let bcp47_id = win_tz_mapper.windows_tz_to_bcp47_id("Central Standard Time", None); /// assert_eq!(bcp47_id, Some(TimeZoneBcp47Id(tinystr!(8, "uschi")))); /// - /// let region = Some(Region::try_from_str("US").unwrap()); - /// let bcp47_id = win_tz_mapper.windows_tz_to_bcp47_id_with_region("Central Standard Time", region).unwrap(); + /// let bcp47_id = win_tz_mapper.windows_tz_to_bcp47_id("Central Standard Time", Some(region!("US"))); /// assert_eq!(bcp47_id, Some(TimeZoneBcp47Id(tinystr!(8, "uschi")))); /// - /// let region = Some(Region::try_from_str("CA").unwrap()); - /// let bcp47_id = win_tz_mapper.windows_tz_to_bcp47_id_with_region("Central Standard Time", region).unwrap(); + /// let bcp47_id = win_tz_mapper.windows_tz_to_bcp47_id("Central Standard Time", Some(region!("CA"))); /// assert_eq!(bcp47_id, Some(TimeZoneBcp47Id(tinystr!(8, "cawnp")))); /// ``` - pub fn windows_tz_to_bcp47_id_with_region( - &self, - windows_tz: &str, - region: Option, - ) -> Result, fmt::Error> { - Ok(self - .windows_tz_lookup(windows_tz, region)? - .and_then(|index| self.data.bcp47_ids.get(index))) - } - - /// Look up the index of a windows time zone with a provided windows time zone and region. - fn windows_tz_lookup( + pub fn windows_tz_to_bcp47_id( &self, windows_tz: &str, region: Option, - ) -> Result, fmt::Error> { + ) -> Option { let mut cursor = self.data.map.cursor(); - cursor.write_str(windows_tz)?; + // Returns None if input is non-ASCII + cursor.write_str(windows_tz).ok()?; cursor.step(b'/'); - match region { - Some(region) => cursor.write_str(region.as_str())?, - None => cursor.write_str("001")?, - }; - Ok(cursor.take_value()) + cursor + .write_str(region.unwrap_or(region!("001")).as_str()) + // region is valid ASCII, but we can do this instead of unwrap + .ok()?; + self.data.bcp47_ids.get(cursor.take_value()?) } } #[cfg(test)] mod tests { + use super::*; use tinystr::tinystr; - use crate::TimeZoneBcp47Id; - - use super::WindowsTimeZoneMapperBorrowed; - #[test] fn basic_windows_tz_lookup() { - let win_map = WindowsTimeZoneMapperBorrowed::new(); + let win_map = WindowsTimeZoneMapper::new(); - let result = win_map - .windows_tz_to_bcp47_id("Central Standard Time") - .unwrap(); + let result = win_map.windows_tz_to_bcp47_id("Central Standard Time", None); assert_eq!(result, Some(TimeZoneBcp47Id(tinystr!(8, "uschi")))); - let result = win_map - .windows_tz_to_bcp47_id("Eastern Standard Time") - .unwrap(); + let result = win_map.windows_tz_to_bcp47_id("Eastern Standard Time", None); assert_eq!(result, Some(TimeZoneBcp47Id(tinystr!(8, "usnyc")))); - let result = win_map.windows_tz_to_bcp47_id("GMT Standard Time").unwrap(); + let result = win_map.windows_tz_to_bcp47_id("Eastern Standard Time", Some(region!("CA"))); + assert_eq!(result, Some(TimeZoneBcp47Id(tinystr!(8, "cator")))); + + let result = win_map.windows_tz_to_bcp47_id("GMT Standard Time", None); assert_eq!(result, Some(TimeZoneBcp47Id(tinystr!(8, "gblon")))); } } diff --git a/ffi/capi/tests/missing_apis.txt b/ffi/capi/tests/missing_apis.txt index 196f3914b77..ab2a2504afb 100644 --- a/ffi/capi/tests/missing_apis.txt +++ b/ffi/capi/tests/missing_apis.txt @@ -371,7 +371,6 @@ icu::timezone::WindowsTimeZoneMapper::new#FnInStruct icu::timezone::WindowsTimeZoneMapperBorrowed#Struct icu::timezone::WindowsTimeZoneMapperBorrowed::new#FnInStruct icu::timezone::WindowsTimeZoneMapperBorrowed::windows_tz_to_bcp47_id#FnInStruct -icu::timezone::WindowsTimeZoneMapperBorrowed::windows_tz_to_bcp47_id_with_region#FnInStruct icu::timezone::ZoneOffsetCalculator#Struct icu::timezone::ZoneOffsetCalculator::compute_offsets_from_time_zone#FnInStruct icu::timezone::ZoneOffsetCalculator::new#FnInStruct