diff --git a/components/datetime/src/combo.rs b/components/datetime/src/combo.rs index 7e1ecda95f5..5b60efb8328 100644 --- a/components/datetime/src/combo.rs +++ b/components/datetime/src/combo.rs @@ -19,7 +19,7 @@ use icu_provider::marker::NeverMarker; /// use icu::datetime::fieldset::{Combo, E, HM, L}; /// use icu::datetime::DateTimeFormatter; /// use icu::locale::locale; -/// use icu::timezone::CustomZonedDateTime; +/// use icu::timezone::IxdtfParser; /// use writeable::assert_try_writeable_eq; /// /// let formatter = DateTimeFormatter::try_new( @@ -28,7 +28,7 @@ use icu_provider::marker::NeverMarker; /// ) /// .unwrap(); /// -/// let zdt = CustomZonedDateTime::try_location_only_from_str( +/// let zdt = IxdtfParser::new().try_location_only_from_str( /// "2024-10-18T15:44[America/Los_Angeles]", /// ) /// .unwrap(); @@ -46,7 +46,7 @@ use icu_provider::marker::NeverMarker; /// use icu::datetime::fieldset::{Combo, E, HM, L}; /// use icu::datetime::FixedCalendarDateTimeFormatter; /// use icu::locale::locale; -/// use icu::timezone::CustomZonedDateTime; +/// use icu::timezone::IxdtfParser; /// use writeable::assert_try_writeable_eq; /// /// let formatter = FixedCalendarDateTimeFormatter::try_new( @@ -55,7 +55,7 @@ use icu_provider::marker::NeverMarker; /// ) /// .unwrap(); /// -/// let zdt = CustomZonedDateTime::try_location_only_iso_from_str( +/// let zdt = IxdtfParser::new().try_location_only_iso_from_str( /// "2024-10-18T15:44[America/Los_Angeles]", /// ) /// .unwrap() diff --git a/components/datetime/src/fieldset.rs b/components/datetime/src/fieldset.rs index 26a70e3f161..17b7fe740e0 100644 --- a/components/datetime/src/fieldset.rs +++ b/components/datetime/src/fieldset.rs @@ -582,7 +582,7 @@ macro_rules! impl_zone_marker { /// /// ``` /// use icu::calendar::{Date, Time}; - /// use icu::timezone::{CustomZonedDateTime, TimeZoneBcp47Id, TimeZoneInfo, UtcOffset, ZoneVariant}; + /// use icu::timezone::{TimeZoneBcp47Id, TimeZoneInfo, UtcOffset, ZoneVariant}; /// use icu::calendar::Gregorian; /// use icu::datetime::FixedCalendarDateTimeFormatter; #[doc = concat!("use icu::datetime::fieldset::", stringify!($type), ";")] @@ -738,7 +738,7 @@ macro_rules! impl_zoneddatetime_marker { /// /// ``` /// use icu::calendar::{Date, Time}; - /// use icu::timezone::{TimeZoneInfo, CustomZonedDateTime}; + /// use icu::timezone::{TimeZoneInfo, IxdtfParser}; /// use icu::datetime::DateTimeFormatter; #[doc = concat!("use icu::datetime::fieldset::", stringify!($type), ";")] /// use icu::locale::locale; @@ -750,7 +750,7 @@ macro_rules! impl_zoneddatetime_marker { /// ) /// .unwrap(); /// - /// let mut dtz = CustomZonedDateTime::try_from_str("2024-05-17T15:47:50+01:00[Europe/London]").unwrap(); + /// let mut dtz = IxdtfParser::new().try_from_str("2024-05-17T15:47:50+01:00[Europe/London]").unwrap(); /// /// assert_try_writeable_eq!( /// fmt.convert_and_format(&dtz), @@ -762,7 +762,7 @@ macro_rules! impl_zoneddatetime_marker { /// /// ``` /// use icu::calendar::{Date, Time}; - /// use icu::timezone::{TimeZoneInfo, CustomZonedDateTime}; + /// use icu::timezone::{TimeZoneInfo, IxdtfParser}; /// use icu::calendar::Gregorian; /// use icu::datetime::FixedCalendarDateTimeFormatter; #[doc = concat!("use icu::datetime::fieldset::", stringify!($type), ";")] @@ -775,7 +775,7 @@ macro_rules! impl_zoneddatetime_marker { /// ) /// .unwrap(); /// - /// let mut dtz = CustomZonedDateTime::try_from_str("2024-05-17T15:47:50+01:00[Europe/London]") + /// let mut dtz = IxdtfParser::new().try_from_str("2024-05-17T15:47:50+01:00[Europe/London]") /// .unwrap() /// .to_calendar(Gregorian); /// @@ -981,7 +981,7 @@ impl_zone_marker!( /// /// ``` /// use icu::calendar::{Date, Time}; - /// use icu::timezone::{CustomZonedDateTime, TimeZoneBcp47Id, TimeZoneInfo, UtcOffset, ZoneVariant}; + /// use icu::timezone::{IxdtfParser, TimeZoneBcp47Id, TimeZoneInfo, UtcOffset, ZoneVariant}; /// use icu::calendar::Gregorian; /// use icu::datetime::FixedCalendarDateTimeFormatter; /// use icu::datetime::fieldset::Z; @@ -1056,7 +1056,7 @@ impl_zone_marker!( /// /// ``` /// use icu::calendar::{Date, Time}; - /// use icu::timezone::{TimeZoneInfo, CustomZonedDateTime}; + /// use icu::timezone::{TimeZoneInfo, IxdtfParser}; /// use icu::calendar::Gregorian; /// use icu::datetime::DateTimeFormatter; /// use icu::datetime::fieldset::MD; @@ -1079,7 +1079,7 @@ impl_zone_marker!( /// ) /// .unwrap(); /// - /// let dtz = CustomZonedDateTime::try_from_str("2024-09-17T15:47:50-05:00[America/Chicago]").unwrap(); + /// let dtz = IxdtfParser::new().try_from_str("2024-09-17T15:47:50-05:00[America/Chicago]").unwrap(); /// /// assert_try_writeable_eq!( /// fmt.convert_and_format(&dtz), @@ -1206,7 +1206,7 @@ impl_zone_marker!( /// /// ``` /// use icu::calendar::{Date, Time}; - /// use icu::timezone::{CustomZonedDateTime, TimeZoneBcp47Id, TimeZoneInfo, UtcOffset, ZoneVariant}; + /// use icu::timezone::{IxdtfParser, TimeZoneBcp47Id, TimeZoneInfo, UtcOffset, ZoneVariant}; /// use icu::calendar::Gregorian; /// use icu::datetime::FixedCalendarDateTimeFormatter; /// use icu::datetime::fieldset::V; @@ -1278,7 +1278,7 @@ impl_zone_marker!( /// /// ``` /// use icu::calendar::{Date, Time}; - /// use icu::timezone::{TimeZoneInfo, CustomZonedDateTime}; + /// use icu::timezone::{TimeZoneInfo, IxdtfParser}; /// use icu::calendar::Gregorian; /// use icu::datetime::DateTimeFormatter; /// use icu::datetime::fieldset::MD; @@ -1301,7 +1301,7 @@ impl_zone_marker!( /// ) /// .unwrap(); /// - /// let dtz = CustomZonedDateTime::try_from_str("2024-09-17T15:47:50-05:00[America/Chicago]").unwrap(); + /// let dtz = IxdtfParser::new().try_from_str("2024-09-17T15:47:50-05:00[America/Chicago]").unwrap(); /// /// assert_try_writeable_eq!( /// fmt.convert_and_format(&dtz), diff --git a/components/datetime/src/format/neo.rs b/components/datetime/src/format/neo.rs index bcefed45295..63f05e2f46f 100644 --- a/components/datetime/src/format/neo.rs +++ b/components/datetime/src/format/neo.rs @@ -326,7 +326,7 @@ size_test!( /// use icu::datetime::neo_pattern::DateTimePattern; /// use icu::datetime::neo_skeleton::NeoSkeleton; /// use icu::locale::locale; -/// use icu::timezone::{TimeZoneInfo, CustomZonedDateTime}; +/// use icu::timezone::{TimeZoneInfo, IxdtfParser}; /// use writeable::{Part, assert_try_writeable_parts_eq}; /// /// // Create an instance that can format all fields (NeoSkeleton): @@ -340,7 +340,7 @@ size_test!( /// // The pattern string contains lots of symbols including "E", "MMM", and "a", /// // but we did not load any data! /// -/// let mut dtz = CustomZonedDateTime::try_from_str("2023-11-20T11:35:03+00:00[Europe/London]").unwrap().to_calendar(Gregorian); +/// let mut dtz = IxdtfParser::new().try_from_str("2023-11-20T11:35:03+00:00[Europe/London]").unwrap().to_calendar(Gregorian); /// /// // Missing data is filled in on a best-effort basis, and an error is signaled. /// assert_try_writeable_parts_eq!( @@ -967,15 +967,15 @@ impl TypedDateTimeNames { /// use icu::datetime::neo_skeleton::NeoTimeZoneSkeleton; /// use icu::datetime::TypedDateTimeNames; /// use icu::locale::locale; - /// use icu::timezone::CustomZonedDateTime; + /// use icu::timezone::IxdtfParser; /// use writeable::assert_try_writeable_eq; /// - /// let mut zone_london_winter = CustomZonedDateTime::try_from_str( + /// let mut zone_london_winter = IxdtfParser::new().try_from_str( /// "2024-01-01T00:00:00+00:00[Europe/London]", /// ) /// .unwrap() /// .zone; - /// let mut zone_london_summer = CustomZonedDateTime::try_from_str( + /// let mut zone_london_summer = IxdtfParser::new().try_from_str( /// "2024-07-01T00:00:00+01:00[Europe/London]", /// ) /// .unwrap() @@ -1070,10 +1070,10 @@ impl TypedDateTimeNames { /// use icu::datetime::neo_skeleton::NeoTimeZoneSkeleton; /// use icu::datetime::TypedDateTimeNames; /// use icu::locale::locale; - /// use icu::timezone::CustomZonedDateTime; + /// use icu::timezone::IxdtfParser; /// use writeable::assert_try_writeable_eq; /// - /// let mut zone_london_winter = CustomZonedDateTime::try_from_str( + /// let mut zone_london_winter = IxdtfParser::new().try_from_str( /// "2024-01-01T00:00:00+00:00[Europe/London]", /// ) /// .unwrap() @@ -1137,15 +1137,15 @@ impl TypedDateTimeNames { /// use icu::datetime::neo_skeleton::NeoTimeZoneSkeleton; /// use icu::datetime::TypedDateTimeNames; /// use icu::locale::locale; - /// use icu::timezone::CustomZonedDateTime; + /// use icu::timezone::IxdtfParser; /// use writeable::assert_try_writeable_eq; /// - /// let mut zone_london_winter = CustomZonedDateTime::try_from_str( + /// let mut zone_london_winter = IxdtfParser::new().try_from_str( /// "2024-01-01T00:00:00+00:00[Europe/London]", /// ) /// .unwrap() /// .zone; - /// let mut zone_london_summer = CustomZonedDateTime::try_from_str( + /// let mut zone_london_summer = IxdtfParser::new().try_from_str( /// "2024-07-01T00:00:00+01:00[Europe/London]", /// ) /// .unwrap() @@ -1213,15 +1213,15 @@ impl TypedDateTimeNames { /// use icu::datetime::neo_skeleton::NeoTimeZoneSkeleton; /// use icu::datetime::TypedDateTimeNames; /// use icu::locale::locale; - /// use icu::timezone::CustomZonedDateTime; + /// use icu::timezone::IxdtfParser; /// use writeable::assert_try_writeable_eq; /// - /// let mut zone_london_winter = CustomZonedDateTime::try_from_str( + /// let mut zone_london_winter = IxdtfParser::new().try_from_str( /// "2024-01-01T00:00:00+00:00[Europe/London]", /// ) /// .unwrap() /// .zone; - /// let mut zone_london_summer = CustomZonedDateTime::try_from_str( + /// let mut zone_london_summer = IxdtfParser::new().try_from_str( /// "2024-07-01T00:00:00+01:00[Europe/London]", /// ) /// .unwrap() @@ -1289,15 +1289,15 @@ impl TypedDateTimeNames { /// use icu::datetime::neo_skeleton::NeoTimeZoneSkeleton; /// use icu::datetime::TypedDateTimeNames; /// use icu::locale::locale; - /// use icu::timezone::CustomZonedDateTime; + /// use icu::timezone::IxdtfParser; /// use writeable::assert_try_writeable_eq; /// - /// let mut zone_london_winter = CustomZonedDateTime::try_from_str( + /// let mut zone_london_winter = IxdtfParser::new().try_from_str( /// "2024-01-01T00:00:00+00:00[Europe/London]", /// ) /// .unwrap() /// .zone; - /// let mut zone_london_summer = CustomZonedDateTime::try_from_str( + /// let mut zone_london_summer = IxdtfParser::new().try_from_str( /// "2024-07-01T00:00:00+01:00[Europe/London]", /// ) /// .unwrap() @@ -1365,15 +1365,15 @@ impl TypedDateTimeNames { /// use icu::datetime::neo_skeleton::NeoTimeZoneSkeleton; /// use icu::datetime::TypedDateTimeNames; /// use icu::locale::locale; - /// use icu::timezone::CustomZonedDateTime; + /// use icu::timezone::IxdtfParser; /// use writeable::assert_try_writeable_eq; /// - /// let mut zone_london_winter = CustomZonedDateTime::try_from_str( + /// let mut zone_london_winter = IxdtfParser::new().try_from_str( /// "2024-01-01T00:00:00+00:00[Europe/London]", /// ) /// .unwrap() /// .zone; - /// let mut zone_london_summer = CustomZonedDateTime::try_from_str( + /// let mut zone_london_summer = IxdtfParser::new().try_from_str( /// "2024-07-01T00:00:00+01:00[Europe/London]", /// ) /// .unwrap() @@ -2393,15 +2393,15 @@ where /// use icu::datetime::neo_skeleton::NeoTimeZoneSkeleton; /// use icu::datetime::TypedDateTimeNames; /// use icu::locale::locale; - /// use icu::timezone::CustomZonedDateTime; + /// use icu::timezone::IxdtfParser; /// use writeable::assert_try_writeable_eq; /// - /// let mut london_winter = CustomZonedDateTime::try_from_str( + /// let mut london_winter = IxdtfParser::new().try_from_str( /// "2024-01-01T00:00:00+00:00[Europe/London]", /// ) /// .unwrap() /// .to_calendar(Gregorian); - /// let mut london_summer = CustomZonedDateTime::try_from_str( + /// let mut london_summer = IxdtfParser::new().try_from_str( /// "2024-07-01T00:00:00+01:00[Europe/London]", /// ) /// .unwrap() diff --git a/components/datetime/tests/mock.rs b/components/datetime/tests/mock.rs index 66448ff9361..fdedb065190 100644 --- a/components/datetime/tests/mock.rs +++ b/components/datetime/tests/mock.rs @@ -5,7 +5,7 @@ //! Some useful parsing functions for tests. use icu_calendar::{DateTime, Gregorian}; -use icu_timezone::{models, CustomZonedDateTime, TimeZoneInfo, ZoneVariant}; +use icu_timezone::{models, CustomZonedDateTime, IxdtfParser, TimeZoneInfo, ZoneVariant}; /// Temporary function for parsing a `DateTime` /// @@ -58,10 +58,10 @@ pub fn parse_gregorian_from_str(input: &str) -> DateTime { pub fn parse_zoned_gregorian_from_str( input: &str, ) -> CustomZonedDateTime> { - let iso_zdt = match CustomZonedDateTime::try_iso_from_str(input) { + let iso_zdt = match IxdtfParser::new().try_iso_from_str(input) { Ok(zdt) => zdt, Err(icu_timezone::ParseError::MismatchedTimeZoneFields) => { - match CustomZonedDateTime::try_loose_iso_from_str(input) { + match IxdtfParser::new().try_loose_iso_from_str(input) { Ok(zdt) => { CustomZonedDateTime { date: zdt.date, diff --git a/components/timezone/src/ixdtf.rs b/components/timezone/src/ixdtf.rs index d19adb7cbb5..5bd6e6e4b58 100644 --- a/components/timezone/src/ixdtf.rs +++ b/components/timezone/src/ixdtf.rs @@ -3,18 +3,19 @@ // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). use crate::{ - time_zone::models, CustomZonedDateTime, InvalidOffsetError, TimeZoneBcp47Id, TimeZoneIdMapper, - TimeZoneInfo, UtcOffset, ZoneOffsetCalculator, ZoneVariant, + provider::{names::IanaToBcp47MapV3Marker, ZoneOffsetPeriodV1Marker}, + time_zone::models, + CustomZonedDateTime, InvalidOffsetError, TimeZoneBcp47Id, TimeZoneIdMapper, + TimeZoneIdMapperBorrowed, TimeZoneInfo, UtcOffset, ZoneOffsetCalculator, ZoneVariant, }; -use alloc::str::FromStr; -use icu_calendar::{AnyCalendar, Date, DateError, DateTime, Iso, RangeError, Time}; +#[cfg(feature = "compiled_data")] +use icu_calendar::AnyCalendar; +use icu_calendar::{Date, DateError, DateTime, Iso, RangeError, Time}; +use icu_provider::prelude::*; use ixdtf::{ - parsers::{ - records::{ - DateRecord, IxdtfParseRecord, TimeRecord, TimeZoneAnnotation, TimeZoneRecord, - UtcOffsetRecord, UtcOffsetRecordOrZ, - }, - IxdtfParser, + parsers::records::{ + DateRecord, IxdtfParseRecord, TimeRecord, TimeZoneAnnotation, TimeZoneRecord, + UtcOffsetRecord, UtcOffsetRecordOrZ, }, ParseError as IxdtfParseError, }; @@ -45,17 +46,17 @@ pub enum ParseError { /// /// # Example /// ``` - /// use icu::timezone::{CustomZonedDateTime, ParseError}; + /// use icu::timezone::{IxdtfParser, ParseError}; /// /// // This timestamp is in UTC, and requires a time zone calculation in order to display a Zurich time. /// assert_eq!( - /// CustomZonedDateTime::try_loose_iso_from_str("2024-08-12T12:32:00Z[Europe/Zurich]").unwrap_err(), + /// IxdtfParser::new().try_loose_iso_from_str("2024-08-12T12:32:00Z[Europe/Zurich]").unwrap_err(), /// ParseError::RequiresCalculation, /// ); /// /// // These timestamps are in local time - /// CustomZonedDateTime::try_loose_iso_from_str("2024-08-12T14:32:00+02:00[Europe/Zurich]").unwrap(); - /// CustomZonedDateTime::try_loose_iso_from_str("2024-08-12T14:32:00[Europe/Zurich]").unwrap(); + /// IxdtfParser::new().try_loose_iso_from_str("2024-08-12T14:32:00+02:00[Europe/Zurich]").unwrap(); + /// IxdtfParser::new().try_loose_iso_from_str("2024-08-12T14:32:00[Europe/Zurich]").unwrap(); /// ``` RequiresCalculation, } @@ -96,6 +97,47 @@ impl UtcOffset { } } +#[derive(Debug)] +/// ✨ *Enabled with the `ixdtf` Cargo feature.* +pub struct IxdtfParser { + mapper: TimeZoneIdMapper, + offsets: ZoneOffsetCalculator, +} + +impl IxdtfParser { + /// Creates a new `IxdtfParser` from compiled data. + #[cfg(feature = "compiled_data")] + #[allow(clippy::new_without_default)] + pub fn new() -> Self { + Self { + mapper: TimeZoneIdMapper::new().static_to_owned(), + offsets: ZoneOffsetCalculator::new(), + } + } + + icu_provider::gen_any_buffer_data_constructors!( + () -> error: DataError, + functions: [ + new: skip, + try_new_with_any_provider, + try_new_with_buffer_provider, + try_new_unstable, + Self + ] + ); + + #[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::new)] + pub fn try_new_unstable

(provider: &P) -> Result + where + P: ?Sized + DataProvider + DataProvider, + { + Ok(Self { + mapper: TimeZoneIdMapper::try_new_unstable(provider)?, + offsets: ZoneOffsetCalculator::try_new_unstable(provider)?, + }) + } +} + struct Intermediate<'a> { offset: Option, iana_identifier: Option<&'a [u8]>, @@ -200,14 +242,17 @@ impl<'a> Intermediate<'a> { UtcOffset::try_from_utc_offset_record(offset) } - fn location_only(self) -> Result, ParseError> { + fn location_only( + self, + mapper: TimeZoneIdMapperBorrowed<'_>, + ) -> Result, ParseError> { let None = self.offset else { return Err(ParseError::MismatchedTimeZoneFields); }; let Some(iana_identifier) = self.iana_identifier else { return Err(ParseError::MismatchedTimeZoneFields); }; - let time_zone_id = TimeZoneIdMapper::new().iana_bytes_to_bcp47(iana_identifier); + let time_zone_id = mapper.iana_bytes_to_bcp47(iana_identifier); let iso = DateTime::::try_new_iso( self.date.year, self.date.month, @@ -219,13 +264,16 @@ impl<'a> Intermediate<'a> { Ok(time_zone_id.with_offset(None).at_time((iso.date, iso.time))) } - fn loose(self) -> Result, ParseError> { + fn loose( + self, + mapper: TimeZoneIdMapperBorrowed<'_>, + ) -> Result, ParseError> { let offset = match self.offset { Some(offset) => Some(UtcOffset::try_from_utc_offset_record(offset)?), None => None, }; let time_zone_id = match self.iana_identifier { - Some(iana_identifier) => TimeZoneIdMapper::new().iana_bytes_to_bcp47(iana_identifier), + Some(iana_identifier) => mapper.iana_bytes_to_bcp47(iana_identifier), None => TimeZoneBcp47Id::unknown(), }; let iso = DateTime::::try_new_iso( @@ -241,14 +289,18 @@ impl<'a> Intermediate<'a> { .at_time((iso.date, iso.time))) } - fn full(self) -> Result, ParseError> { + fn full( + self, + mapper: TimeZoneIdMapperBorrowed<'_>, + zone_offset_calculator: &ZoneOffsetCalculator, + ) -> Result, ParseError> { let Some(offset) = self.offset else { return Err(ParseError::MismatchedTimeZoneFields); }; let Some(iana_identifier) = self.iana_identifier else { return Err(ParseError::MismatchedTimeZoneFields); }; - let time_zone_id = TimeZoneIdMapper::new().iana_bytes_to_bcp47(iana_identifier); + let time_zone_id = mapper.iana_bytes_to_bcp47(iana_identifier); let iso = DateTime::::try_new_iso( self.date.year, self.date.month, @@ -258,7 +310,6 @@ impl<'a> Intermediate<'a> { self.time.second, )?; let offset = UtcOffset::try_from_utc_offset_record(offset)?; - let zone_offset_calculator = ZoneOffsetCalculator::new(); let zone_variant = match zone_offset_calculator.compute_offsets_from_time_zone(time_zone_id, &iso) { Some((std_offset, dst_offset)) => { @@ -283,99 +334,93 @@ impl<'a> Intermediate<'a> { } } -// ==== TimeZoneInfo methods and traits ==== - -// ==== CustomZonedDateTime methods and traits ==== - -impl CustomZonedDateTime { +impl IxdtfParser { /// Create a [`CustomZonedDateTime`] in ISO-8601 calendar from an IXDTF syntax string. /// /// This function is "strict": the string should have only an offset and no named time zone. - /// - /// ✨ *Enabled with the `compiled_data` and `ixdtf` Cargo features.* - pub fn try_offset_only_iso_from_str(ixdtf_str: &str) -> Result { - Self::try_offset_only_iso_from_utf8(ixdtf_str.as_bytes()) + pub fn try_offset_only_iso_from_str( + &self, + ixdtf_str: &str, + ) -> Result, ParseError> { + self.try_offset_only_iso_from_utf8(ixdtf_str.as_bytes()) } - /// Create a [`CustomZonedDateTime`] in ISO-8601 calendar from IXDTF syntax utf8 bytes. + /// Create a [`CustomZonedDateTime`] in ISO-8601 calendar from IXDTF syntax UTF-8 bytes. /// /// This function is "strict": the string should have only an offset and no named time zone. - /// - /// ✨ *Enabled with the `compiled_data` and `ixdtf` Cargo features.* - pub fn try_offset_only_iso_from_utf8(ixdtf_str: &[u8]) -> Result { - let ixdtf_record = IxdtfParser::from_utf8(ixdtf_str).parse()?; + pub fn try_offset_only_iso_from_utf8( + &self, + ixdtf_str: &[u8], + ) -> Result, ParseError> { + let ixdtf_record = ixdtf::parsers::IxdtfParser::from_utf8(ixdtf_str).parse()?; let intermediate = Intermediate::try_from_ixdtf_record(&ixdtf_record)?; let time_zone = intermediate.offset_only()?; - Self::try_iso_from_ixdtf_record(&ixdtf_record, time_zone) + self.try_iso_from_ixdtf_record(&ixdtf_record, time_zone) } -} -impl CustomZonedDateTime> { /// Create a [`CustomZonedDateTime`] in ISO-8601 calendar from an IXDTF syntax string. /// /// This function is "strict": the string should have only a named time zone and no offset. - /// - /// ✨ *Enabled with the `compiled_data` and `ixdtf` Cargo features.* - pub fn try_location_only_iso_from_str(ixdtf_str: &str) -> Result { - Self::try_location_only_iso_from_utf8(ixdtf_str.as_bytes()) + pub fn try_location_only_iso_from_str( + &self, + ixdtf_str: &str, + ) -> Result>, ParseError> { + self.try_location_only_iso_from_utf8(ixdtf_str.as_bytes()) } - /// Create a [`CustomZonedDateTime`] in ISO-8601 calendar from IXDTF syntax utf8 bytes. + /// Create a [`CustomZonedDateTime`] in ISO-8601 calendar from IXDTF syntax UTF-8 bytes. /// /// This function is "strict": the string should have only a named time zone and no offset. - /// - /// ✨ *Enabled with the `compiled_data` and `ixdtf` Cargo features.* - pub fn try_location_only_iso_from_utf8(ixdtf_str: &[u8]) -> Result { - let ixdtf_record = IxdtfParser::from_utf8(ixdtf_str).parse()?; + pub fn try_location_only_iso_from_utf8( + &self, + ixdtf_str: &[u8], + ) -> Result>, ParseError> { + let ixdtf_record = ixdtf::parsers::IxdtfParser::from_utf8(ixdtf_str).parse()?; let intermediate = Intermediate::try_from_ixdtf_record(&ixdtf_record)?; - let time_zone = intermediate.location_only()?; - Self::try_iso_from_ixdtf_record(&ixdtf_record, time_zone) + let time_zone = intermediate.location_only(self.mapper.as_borrowed())?; + self.try_iso_from_ixdtf_record(&ixdtf_record, time_zone) } -} -impl CustomZonedDateTime> { /// Create a [`CustomZonedDateTime`] in ISO-8601 calendar from an IXDTF syntax string. /// /// This function is "loose": the string can have an offset, and named time zone, both, or /// neither. If the named time zone is missing, it is returned as Etc/Unknown. /// /// The zone variant is _not_ calculated with this function. If you need it, use - /// [`CustomZonedDateTime::try_iso_from_str`]. - /// - /// ✨ *Enabled with the `compiled_data` and `ixdtf` Cargo features.* - pub fn try_loose_iso_from_str(ixdtf_str: &str) -> Result { - Self::try_loose_iso_from_utf8(ixdtf_str.as_bytes()) + /// [`Self::try_iso_from_str`]. + pub fn try_loose_iso_from_str( + &self, + ixdtf_str: &str, + ) -> Result>, ParseError> { + self.try_loose_iso_from_utf8(ixdtf_str.as_bytes()) } - /// Create a [`CustomZonedDateTime`] in ISO-8601 calendar from IXDTF syntax utf8 bytes. + /// Create a [`CustomZonedDateTime`] in ISO-8601 calendar from IXDTF syntax UTF-8 bytes. /// /// This function is "loose": the string can have an offset, and named time zone, both, or /// neither. If the named time zone is missing, it is returned as Etc/Unknown. /// /// The zone variant is _not_ calculated with this function. If you need it, use - /// [`CustomZonedDateTime::try_iso_from_utf8`]. - /// - /// ✨ *Enabled with the `compiled_data` and `ixdtf` Cargo features.* - pub fn try_loose_iso_from_utf8(ixdtf_str: &[u8]) -> Result { - let ixdtf_record = IxdtfParser::from_utf8(ixdtf_str).parse()?; + /// [`Self::try_iso_from_utf8`]. + pub fn try_loose_iso_from_utf8( + &self, + ixdtf_str: &[u8], + ) -> Result>, ParseError> { + let ixdtf_record = ixdtf::parsers::IxdtfParser::from_utf8(ixdtf_str).parse()?; let intermediate = Intermediate::try_from_ixdtf_record(&ixdtf_record)?; - let time_zone = intermediate.loose()?; - Self::try_iso_from_ixdtf_record(&ixdtf_record, time_zone) + let time_zone = intermediate.loose(self.mapper.as_borrowed())?; + self.try_iso_from_ixdtf_record(&ixdtf_record, time_zone) } -} -impl CustomZonedDateTime> { /// Create a [`CustomZonedDateTime`] in ISO-8601 calendar from an IXDTF syntax string. /// /// The string should have both an offset and a named time zone. /// - /// ✨ *Enabled with the `compiled_data` and `ixdtf` Cargo features.* - /// /// ``` - /// use icu_timezone::{CustomZonedDateTime, TimeZoneInfo, UtcOffset, TimeZoneBcp47Id, ZoneVariant}; + /// use icu_timezone::{IxdtfParser, TimeZoneInfo, UtcOffset, TimeZoneBcp47Id, ZoneVariant}; /// use tinystr::tinystr; /// - /// let zoneddatetime = CustomZonedDateTime::try_iso_from_str("2024-08-08T12:08:19-05:00[America/Chicago]").unwrap(); + /// let zoneddatetime = IxdtfParser::new().try_iso_from_str("2024-08-08T12:08:19-05:00[America/Chicago]").unwrap(); /// /// assert_eq!(zoneddatetime.date.year().extended_year, 2024); /// assert_eq!( @@ -395,132 +440,112 @@ impl CustomZonedDateTime> { /// ``` /// /// For more information on date, time, and time zone parsing, - /// see [`CustomZonedDateTime::try_from_str`]. - pub fn try_iso_from_str(ixdtf_str: &str) -> Result { - Self::try_iso_from_utf8(ixdtf_str.as_bytes()) + /// see [`Self::try_from_str`]. + pub fn try_iso_from_str( + &self, + ixdtf_str: &str, + ) -> Result>, ParseError> { + self.try_iso_from_utf8(ixdtf_str.as_bytes()) } - /// Create a [`CustomZonedDateTime`] in ISO-8601 calendar from IXDTF syntax utf8 bytes. + /// Create a [`CustomZonedDateTime`] in ISO-8601 calendar from IXDTF syntax UTF-8 bytes. /// /// The string should have both an offset and a named time zone. /// - /// ✨ *Enabled with the `compiled_data` and `ixdtf` Cargo features.* - /// /// See [`Self::try_iso_from_str`]. - pub fn try_iso_from_utf8(ixdtf_str: &[u8]) -> Result { - let ixdtf_record = IxdtfParser::from_utf8(ixdtf_str).parse()?; + pub fn try_iso_from_utf8( + &self, + ixdtf_str: &[u8], + ) -> Result>, ParseError> { + let ixdtf_record = ixdtf::parsers::IxdtfParser::from_utf8(ixdtf_str).parse()?; let intermediate = Intermediate::try_from_ixdtf_record(&ixdtf_record)?; - let time_zone = intermediate.full()?; - Self::try_iso_from_ixdtf_record(&ixdtf_record, time_zone) + let time_zone = intermediate.full(self.mapper.as_borrowed(), &self.offsets)?; + self.try_iso_from_ixdtf_record(&ixdtf_record, time_zone) } -} -impl CustomZonedDateTime { - fn try_iso_from_ixdtf_record( - ixdtf_record: &IxdtfParseRecord, - zone: Z, - ) -> Result { - let date_record = ixdtf_record.date.ok_or(ParseError::MissingFields)?; - let date = Date::try_new_iso(date_record.year, date_record.month, date_record.day)?; - let time_record = ixdtf_record.time.ok_or(ParseError::MissingFields)?; - let time = Time::try_new( - time_record.hour, - time_record.minute, - time_record.second, - time_record.nanosecond, - )?; - - Ok(Self { date, time, zone }) - } -} - -impl FromStr for CustomZonedDateTime> { - type Err = ParseError; - - #[inline] - fn from_str(s: &str) -> Result { - Self::try_iso_from_str(s) - } -} - -impl CustomZonedDateTime { /// Create a [`CustomZonedDateTime`] in any calendar from an IXDTF syntax string. /// /// This function is "strict": the string should have only an offset and no named time zone. - /// - /// ✨ *Enabled with the `compiled_data` and `ixdtf` Cargo features.* - pub fn try_offset_only_from_str(ixdtf_str: &str) -> Result { - Self::try_offset_only_from_utf8(ixdtf_str.as_bytes()) + #[cfg(feature = "compiled_data")] + pub fn try_offset_only_from_str( + &self, + ixdtf_str: &str, + ) -> Result, ParseError> { + self.try_offset_only_from_utf8(ixdtf_str.as_bytes()) } - /// Create a [`CustomZonedDateTime`] in any calendar from IXDTF syntax utf8 bytes. + /// Create a [`CustomZonedDateTime`] in any calendar from IXDTF syntax UTF-8 bytes. /// /// This function is "strict": the string should have only an offset and no named time zone. - /// - /// ✨ *Enabled with the `compiled_data` and `ixdtf` Cargo features.* - pub fn try_offset_only_from_utf8(ixdtf_str: &[u8]) -> Result { - let ixdtf_record = IxdtfParser::from_utf8(ixdtf_str).parse()?; + #[cfg(feature = "compiled_data")] + pub fn try_offset_only_from_utf8( + &self, + ixdtf_str: &[u8], + ) -> Result, ParseError> { + let ixdtf_record = ixdtf::parsers::IxdtfParser::from_utf8(ixdtf_str).parse()?; let intermediate = Intermediate::try_from_ixdtf_record(&ixdtf_record)?; let time_zone = intermediate.offset_only()?; - Self::try_from_ixdtf_record(&ixdtf_record, time_zone) + self.try_from_ixdtf_record(&ixdtf_record, time_zone) } -} -impl CustomZonedDateTime> { /// Create a [`CustomZonedDateTime`] in any calendar from an IXDTF syntax string. /// /// This function is "strict": the string should have only a named time zone and no offset. - /// - /// ✨ *Enabled with the `compiled_data` and `ixdtf` Cargo features.* - pub fn try_location_only_from_str(ixdtf_str: &str) -> Result { - Self::try_location_only_from_utf8(ixdtf_str.as_bytes()) + #[cfg(feature = "compiled_data")] + pub fn try_location_only_from_str( + &self, + ixdtf_str: &str, + ) -> Result>, ParseError> { + self.try_location_only_from_utf8(ixdtf_str.as_bytes()) } - /// Create a [`CustomZonedDateTime`] in any calendar from IXDTF syntax utf8 bytes. + /// Create a [`CustomZonedDateTime`] in any calendar from IXDTF syntax UTF-8 bytes. /// /// This function is "strict": the string should have only a named time zone and no offset. - /// - /// ✨ *Enabled with the `compiled_data` and `ixdtf` Cargo features.* - pub fn try_location_only_from_utf8(ixdtf_str: &[u8]) -> Result { - let ixdtf_record = IxdtfParser::from_utf8(ixdtf_str).parse()?; + #[cfg(feature = "compiled_data")] + pub fn try_location_only_from_utf8( + &self, + ixdtf_str: &[u8], + ) -> Result>, ParseError> { + let ixdtf_record = ixdtf::parsers::IxdtfParser::from_utf8(ixdtf_str).parse()?; let intermediate = Intermediate::try_from_ixdtf_record(&ixdtf_record)?; - let time_zone = intermediate.location_only()?; - Self::try_from_ixdtf_record(&ixdtf_record, time_zone) + let time_zone = intermediate.location_only(self.mapper.as_borrowed())?; + self.try_from_ixdtf_record(&ixdtf_record, time_zone) } -} -impl CustomZonedDateTime> { /// Create a [`CustomZonedDateTime`] in any calendar from an IXDTF syntax string. /// /// This function is "loose": the string can have an offset, and named time zone, both, or /// neither. If the named time zone is missing, it is returned as Etc/Unknown. /// /// The zone variant is _not_ calculated with this function. If you need it, use - /// [`CustomZonedDateTime::try_from_str`]. - /// - /// ✨ *Enabled with the `compiled_data` and `ixdtf` Cargo features.* - pub fn try_loose_from_str(ixdtf_str: &str) -> Result { - Self::try_loose_from_utf8(ixdtf_str.as_bytes()) + /// [`Self::try_from_str`]. + #[cfg(feature = "compiled_data")] + pub fn try_loose_from_str( + &self, + ixdtf_str: &str, + ) -> Result>, ParseError> { + self.try_loose_from_utf8(ixdtf_str.as_bytes()) } - /// Create a [`CustomZonedDateTime`] in any calendar from IXDTF syntax utf8 bytes. + /// Create a [`CustomZonedDateTime`] in any calendar from IXDTF syntax UTF-8 bytes. /// /// This function is "loose": the string can have an offset, and named time zone, both, or /// neither. If the named time zone is missing, it is returned as Etc/Unknown. /// /// The zone variant is _not_ calculated with this function. If you need it, use - /// [`CustomZonedDateTime::try_from_utf8`]. - /// - /// ✨ *Enabled with the `compiled_data` and `ixdtf` Cargo features.* - pub fn try_loose_from_utf8(ixdtf_str: &[u8]) -> Result { - let ixdtf_record = IxdtfParser::from_utf8(ixdtf_str).parse()?; + /// [`Self::try_from_utf8`]. + #[cfg(feature = "compiled_data")] + pub fn try_loose_from_utf8( + &self, + ixdtf_str: &[u8], + ) -> Result>, ParseError> { + let ixdtf_record = ixdtf::parsers::IxdtfParser::from_utf8(ixdtf_str).parse()?; let intermediate = Intermediate::try_from_ixdtf_record(&ixdtf_record)?; - let time_zone = intermediate.loose()?; - Self::try_from_ixdtf_record(&ixdtf_record, time_zone) + let time_zone = intermediate.loose(self.mapper.as_borrowed())?; + self.try_from_ixdtf_record(&ixdtf_record, time_zone) } -} -impl CustomZonedDateTime> { /// Create a [`CustomZonedDateTime`] in any calendar from an IXDTF syntax string. /// /// The string should have both an offset and a named time zone. @@ -530,17 +555,15 @@ impl CustomZonedDateTime> { /// This is a convenience constructor that uses compiled data. For custom data providers, /// use [`ixdtf`] and/or the other primitives in this crate such as [`TimeZoneIdMapper`]. /// - /// ✨ *Enabled with the `compiled_data` and `ixdtf` Cargo features.* - /// /// # Examples /// /// Basic usage: /// /// ``` - /// use icu_timezone::{CustomZonedDateTime, TimeZoneInfo, UtcOffset, TimeZoneBcp47Id, ZoneVariant}; + /// use icu_timezone::{IxdtfParser, TimeZoneInfo, UtcOffset, TimeZoneBcp47Id, ZoneVariant}; /// use tinystr::tinystr; /// - /// let zoneddatetime = CustomZonedDateTime::try_from_str("2024-08-08T12:08:19-05:00[America/Chicago][u-ca=hebrew]").unwrap(); + /// let zoneddatetime = IxdtfParser::new().try_from_str("2024-08-08T12:08:19-05:00[America/Chicago][u-ca=hebrew]").unwrap(); /// /// assert_eq!(zoneddatetime.date.year().extended_year, 5784); /// assert_eq!( @@ -570,9 +593,9 @@ impl CustomZonedDateTime> { /// DateTime string. /// /// ``` - /// use icu_timezone::{TimeZoneInfo, CustomZonedDateTime, UtcOffset}; + /// use icu_timezone::{TimeZoneInfo, IxdtfParser, UtcOffset}; /// - /// let tz_from_offset = CustomZonedDateTime::try_offset_only_from_str("2024-08-08T12:08:19-05:00").unwrap(); + /// let tz_from_offset = IxdtfParser::new().try_offset_only_from_str("2024-08-08T12:08:19-05:00").unwrap(); /// /// assert_eq!(tz_from_offset.zone, UtcOffset::try_from_seconds(-18000).unwrap()); /// ``` @@ -582,11 +605,11 @@ impl CustomZonedDateTime> { /// Below is an example of a time zone being provided by a time zone annotation. /// /// ``` - /// use icu_timezone::{TimeZoneInfo, CustomZonedDateTime, UtcOffset, TimeZoneBcp47Id, ZoneVariant}; + /// use icu_timezone::{TimeZoneInfo, IxdtfParser, UtcOffset, TimeZoneBcp47Id, ZoneVariant}; /// use tinystr::tinystr; /// - /// let tz_from_offset_annotation = CustomZonedDateTime::try_offset_only_from_str("2024-08-08T12:08:19[-05:00]").unwrap(); - /// let tz_from_iana_annotation = CustomZonedDateTime::try_location_only_from_str("2024-08-08T12:08:19[America/Chicago]").unwrap(); + /// let tz_from_offset_annotation = IxdtfParser::new().try_offset_only_from_str("2024-08-08T12:08:19[-05:00]").unwrap(); + /// let tz_from_iana_annotation = IxdtfParser::new().try_location_only_from_str("2024-08-08T12:08:19[America/Chicago]").unwrap(); /// /// assert_eq!(tz_from_offset_annotation.zone, UtcOffset::try_from_seconds(-18000).unwrap()); /// @@ -606,10 +629,10 @@ impl CustomZonedDateTime> { /// In cases where the DateTime UTC Offset is provided and the IANA identifier, some validity checks are performed. /// /// ``` - /// use icu_timezone::{TimeZoneInfo, CustomZonedDateTime, UtcOffset, TimeZoneBcp47Id, ZoneVariant, ParseError}; + /// use icu_timezone::{TimeZoneInfo, IxdtfParser, UtcOffset, TimeZoneBcp47Id, ZoneVariant, ParseError}; /// use tinystr::tinystr; /// - /// let consistent_tz_from_both = CustomZonedDateTime::try_from_str("2024-08-08T12:08:19-05:00[America/Chicago]").unwrap(); + /// let consistent_tz_from_both = IxdtfParser::new().try_from_str("2024-08-08T12:08:19-05:00[America/Chicago]").unwrap(); /// /// /// assert_eq!(consistent_tz_from_both.zone.time_zone_id, TimeZoneBcp47Id(tinystr!(8, "uschi"))); @@ -619,13 +642,13 @@ impl CustomZonedDateTime> { /// /// // We know that America/Los_Angeles never used a -05:00 offset at any time of the year 2024 /// assert_eq!( - /// CustomZonedDateTime::try_from_str("2024-08-08T12:08:19-05:00[America/Los_Angeles]").unwrap_err(), + /// IxdtfParser::new().try_from_str("2024-08-08T12:08:19-05:00[America/Los_Angeles]").unwrap_err(), /// ParseError::InvalidOffsetError /// ); /// /// // We don't know that America/Los_Angeles didn't use standard time (-08:00) in August /// assert!( - /// CustomZonedDateTime::try_from_str("2024-08-08T12:08:19-08:00[America/Los_Angeles]").is_ok() + /// IxdtfParser::new().try_from_str("2024-08-08T12:08:19-08:00[America/Los_Angeles]").is_ok() /// ); /// ``` /// @@ -634,40 +657,49 @@ impl CustomZonedDateTime> { /// These annotations must always be consistent as they should be either the same value or are inconsistent. /// /// ``` - /// use icu_timezone::{ParseError, TimeZoneInfo, CustomZonedDateTime, UtcOffset, TimeZoneBcp47Id}; + /// use icu_timezone::{ParseError, TimeZoneInfo, IxdtfParser, UtcOffset, TimeZoneBcp47Id}; /// use tinystr::tinystr; /// - /// let consistent_tz_from_both = CustomZonedDateTime::try_offset_only_from_str("2024-08-08T12:08:19-05:00[-05:00]").unwrap(); + /// let consistent_tz_from_both = IxdtfParser::new().try_offset_only_from_str("2024-08-08T12:08:19-05:00[-05:00]").unwrap(); /// /// assert_eq!(consistent_tz_from_both.zone, UtcOffset::try_from_seconds(-18000).unwrap()); /// /// - /// let inconsistent_tz_from_both = CustomZonedDateTime::try_offset_only_from_str("2024-08-08T12:08:19-05:00[+05:00]"); + /// let inconsistent_tz_from_both = IxdtfParser::new().try_offset_only_from_str("2024-08-08T12:08:19-05:00[+05:00]"); /// /// assert!(matches!(inconsistent_tz_from_both, Err(ParseError::InconsistentTimeZoneOffsets))); /// ``` - pub fn try_from_str(ixdtf_str: &str) -> Result { - Self::try_from_utf8(ixdtf_str.as_bytes()) + #[cfg(feature = "compiled_data")] + pub fn try_from_str( + &self, + ixdtf_str: &str, + ) -> Result>, ParseError> { + self.try_from_utf8(ixdtf_str.as_bytes()) } - /// Create a [`CustomZonedDateTime`] in any calendar from IXDTF syntax utf8 bytes. + /// Create a [`CustomZonedDateTime`] in any calendar from IXDTF syntax UTF-8 bytes. /// /// The string should have both an offset and a named time zone. /// - /// ✨ *Enabled with the `compiled_data` and `ixdtf` Cargo features.* - /// /// See [`Self::try_from_str`]. - pub fn try_from_utf8(ixdtf_str: &[u8]) -> Result { - let ixdtf_record = IxdtfParser::from_utf8(ixdtf_str).parse()?; + #[cfg(feature = "compiled_data")] + pub fn try_from_utf8( + &self, + ixdtf_str: &[u8], + ) -> Result>, ParseError> { + let ixdtf_record = ixdtf::parsers::IxdtfParser::from_utf8(ixdtf_str).parse()?; let intermediate = Intermediate::try_from_ixdtf_record(&ixdtf_record)?; - let time_zone = intermediate.full()?; - Self::try_from_ixdtf_record(&ixdtf_record, time_zone) + let time_zone = intermediate.full(self.mapper.as_borrowed(), &self.offsets)?; + self.try_from_ixdtf_record(&ixdtf_record, time_zone) } -} -impl CustomZonedDateTime { - fn try_from_ixdtf_record(ixdtf_record: &IxdtfParseRecord, zone: Z) -> Result { - let iso_zdt = CustomZonedDateTime::::try_iso_from_ixdtf_record(ixdtf_record, zone)?; + #[cfg(feature = "compiled_data")] + fn try_from_ixdtf_record( + &self, + ixdtf_record: &IxdtfParseRecord, + zone: Z, + ) -> Result, ParseError> { + let iso_zdt = self.try_iso_from_ixdtf_record(ixdtf_record, zone)?; // Find the calendar (based off icu_calendar's AnyCalendar try_from) let calendar_id = ixdtf_record.calendar.unwrap_or(b"iso"); @@ -675,20 +707,29 @@ impl CustomZonedDateTime { .ok_or(ParseError::UnknownCalendar)?; let calendar = AnyCalendar::new(calendar_kind); - Ok(Self { + Ok(CustomZonedDateTime { date: iso_zdt.date.to_any().to_calendar(calendar), time: iso_zdt.time, zone: iso_zdt.zone, }) } -} -impl FromStr for CustomZonedDateTime> { - type Err = ParseError; + fn try_iso_from_ixdtf_record( + &self, + ixdtf_record: &IxdtfParseRecord, + zone: Z, + ) -> Result, ParseError> { + let date_record = ixdtf_record.date.ok_or(ParseError::MissingFields)?; + let date = Date::try_new_iso(date_record.year, date_record.month, date_record.day)?; + let time_record = ixdtf_record.time.ok_or(ParseError::MissingFields)?; + let time = Time::try_new( + time_record.hour, + time_record.minute, + time_record.second, + time_record.nanosecond, + )?; - #[inline] - fn from_str(s: &str) -> Result { - Self::try_from_str(s) + Ok(CustomZonedDateTime { date, time, zone }) } } @@ -700,35 +741,37 @@ mod test { #[test] fn max_possible_ixdtf_utc_offset() { assert_eq!( - CustomZonedDateTime::try_offset_only_iso_from_str( - "2024-08-08T12:08:19+23:59:60.999999999" - ) - .unwrap_err(), + IxdtfParser::new() + .try_offset_only_iso_from_str("2024-08-08T12:08:19+23:59:60.999999999") + .unwrap_err(), ParseError::InvalidOffsetError ); } #[test] fn zone_calculations() { - CustomZonedDateTime::try_offset_only_iso_from_str("2024-08-08T12:08:19Z").unwrap(); + IxdtfParser::new() + .try_offset_only_iso_from_str("2024-08-08T12:08:19Z") + .unwrap(); assert_eq!( - CustomZonedDateTime::try_offset_only_iso_from_str("2024-08-08T12:08:19Z[+08:00]") + IxdtfParser::new() + .try_offset_only_iso_from_str("2024-08-08T12:08:19Z[+08:00]") .unwrap_err(), ParseError::RequiresCalculation ); assert_eq!( - CustomZonedDateTime::try_offset_only_iso_from_str( - "2024-08-08T12:08:19Z[Europe/Zurich]" - ) - .unwrap_err(), + IxdtfParser::new() + .try_offset_only_iso_from_str("2024-08-08T12:08:19Z[Europe/Zurich]") + .unwrap_err(), ParseError::RequiresCalculation ); } #[test] fn future_zone() { - let result = - CustomZonedDateTime::try_loose_from_str("2024-08-08T12:08:19[Future/Zone]").unwrap(); + let result = IxdtfParser::new() + .try_loose_from_str("2024-08-08T12:08:19[Future/Zone]") + .unwrap(); assert_eq!(result.zone.time_zone_id, TimeZoneBcp47Id::unknown()); assert_eq!(result.zone.offset, None); } diff --git a/components/timezone/src/lib.rs b/components/timezone/src/lib.rs index a105c833d90..aabee796035 100644 --- a/components/timezone/src/lib.rs +++ b/components/timezone/src/lib.rs @@ -95,8 +95,10 @@ mod windows_tz; mod zone_offset; mod zoned_datetime; -#[cfg(all(feature = "ixdtf", feature = "compiled_data"))] +#[cfg(feature = "ixdtf")] mod ixdtf; +#[cfg(feature = "ixdtf")] +pub use self::ixdtf::IxdtfParser; pub use error::InvalidOffsetError; pub use ids::{ diff --git a/ffi/capi/tests/missing_apis.txt b/ffi/capi/tests/missing_apis.txt index ab2a2504afb..c088ca500da 100644 --- a/ffi/capi/tests/missing_apis.txt +++ b/ffi/capi/tests/missing_apis.txt @@ -339,25 +339,26 @@ icu::properties::props::GeneralCategoryOutOfBoundsError#Struct icu::segmenter::SentenceBreakOptions#Struct icu::segmenter::WordBreakOptions#Struct icu::timezone::CustomZonedDateTime#Struct -icu::timezone::CustomZonedDateTime::from_str#FnInStruct icu::timezone::CustomZonedDateTime::to_calendar#FnInStruct icu::timezone::CustomZonedDateTime::to_iso#FnInStruct -icu::timezone::CustomZonedDateTime::try_from_str#FnInStruct -icu::timezone::CustomZonedDateTime::try_from_utf8#FnInStruct -icu::timezone::CustomZonedDateTime::try_iso_from_str#FnInStruct -icu::timezone::CustomZonedDateTime::try_iso_from_utf8#FnInStruct -icu::timezone::CustomZonedDateTime::try_location_only_from_str#FnInStruct -icu::timezone::CustomZonedDateTime::try_location_only_from_utf8#FnInStruct -icu::timezone::CustomZonedDateTime::try_location_only_iso_from_str#FnInStruct -icu::timezone::CustomZonedDateTime::try_location_only_iso_from_utf8#FnInStruct -icu::timezone::CustomZonedDateTime::try_loose_from_str#FnInStruct -icu::timezone::CustomZonedDateTime::try_loose_from_utf8#FnInStruct -icu::timezone::CustomZonedDateTime::try_loose_iso_from_str#FnInStruct -icu::timezone::CustomZonedDateTime::try_loose_iso_from_utf8#FnInStruct -icu::timezone::CustomZonedDateTime::try_offset_only_from_str#FnInStruct -icu::timezone::CustomZonedDateTime::try_offset_only_from_utf8#FnInStruct -icu::timezone::CustomZonedDateTime::try_offset_only_iso_from_str#FnInStruct -icu::timezone::CustomZonedDateTime::try_offset_only_iso_from_utf8#FnInStruct +icu::timezone::IxdtfParser#Struct +icu::timezone::IxdtfParser::new#FnInStruct +icu::timezone::IxdtfParser::try_from_str#FnInStruct +icu::timezone::IxdtfParser::try_from_utf8#FnInStruct +icu::timezone::IxdtfParser::try_iso_from_str#FnInStruct +icu::timezone::IxdtfParser::try_iso_from_utf8#FnInStruct +icu::timezone::IxdtfParser::try_location_only_from_str#FnInStruct +icu::timezone::IxdtfParser::try_location_only_from_utf8#FnInStruct +icu::timezone::IxdtfParser::try_location_only_iso_from_str#FnInStruct +icu::timezone::IxdtfParser::try_location_only_iso_from_utf8#FnInStruct +icu::timezone::IxdtfParser::try_loose_from_str#FnInStruct +icu::timezone::IxdtfParser::try_loose_from_utf8#FnInStruct +icu::timezone::IxdtfParser::try_loose_iso_from_str#FnInStruct +icu::timezone::IxdtfParser::try_loose_iso_from_utf8#FnInStruct +icu::timezone::IxdtfParser::try_offset_only_from_str#FnInStruct +icu::timezone::IxdtfParser::try_offset_only_from_utf8#FnInStruct +icu::timezone::IxdtfParser::try_offset_only_iso_from_str#FnInStruct +icu::timezone::IxdtfParser::try_offset_only_iso_from_utf8#FnInStruct icu::timezone::ParseError#Enum icu::timezone::TimeZoneBcp47Id::into_option#FnInStruct icu::timezone::TimeZoneBcp47Id::with_offset#FnInStruct