diff --git a/components/datetime/src/builder.rs b/components/datetime/src/builder.rs new file mode 100644 index 00000000000..bd3cbb622b1 --- /dev/null +++ b/components/datetime/src/builder.rs @@ -0,0 +1,362 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! Builder APIs for [dynamic field sets](crate::fieldsets::enums). +//! +//! These APIs are designed for when the field set is not known at compile time. This could +//! happen if: +//! +//! 1. The field set is sent over the network or read from a data file +//! 2. Implementing another interface with different types +//! +//! If the field set is known at compile time, use the static fieldset APIs instead of the +//! builder exported in this module. +//! +//! All examples below will show both ways to build a field set. +//! +//! # Examples +//! +//! ``` +//! use icu::datetime::fieldsets; +//! use icu::datetime::fieldsets::builder::*; +//! use icu::datetime::fieldsets::enums::*; +//! use icu::datetime::options::*; +//! +//! // Year, Month, Day +//! // Medium length +//! // Always display the era +//! +//! let static_field_set = fieldsets::YMD::medium() +//! .with_year_style(YearStyle::Always); +//! +//! let mut builder = FieldSetBuilder::default(); +//! builder.date_fields = Some(DateFields::YMD); +//! builder.length = Some(Length::Medium); +//! builder.year_style = Some(YearStyle::Always); +//! let dynamic_field_set = builder.build_date().unwrap(); +//! +//! assert_eq!( +//! dynamic_field_set, +//! DateFieldSet::YMD(static_field_set), +//! ); +//! +//! // Weekday and Time of day +//! // Medium length, implicit in the builder +//! // Display time to the minute +//! +//! let static_field_set = fieldsets::ET::medium() +//! .with_time_precision(TimePrecision::MinuteExact); +//! +//! let mut builder = FieldSetBuilder::default(); +//! builder.date_fields = Some(DateFields::E); +//! builder.time_precision = Some(TimePrecision::MinuteExact); +//! let dynamic_field_set = builder.build_date_and_time().unwrap(); +//! +//! assert_eq!( +//! dynamic_field_set, +//! DateAndTimeFieldSet::ET(static_field_set), +//! ); +//! +//! // Time and Time Zone +//! // Short length +//! // Long specific non-location time zone +//! // Display time to the millisecond +//! // Render for column alignment +//! +//! let static_field_set = fieldsets::T::short() +//! .with_time_precision(TimePrecision::SecondExact(FractionalSecondDigits::F3)) +//! .with_alignment(Alignment::Column) +//! .with_zone_specific_long(); +//! +//! let mut builder = FieldSetBuilder::default(); +//! builder.length = Some(Length::Short); +//! builder.time_precision = Some(TimePrecision::SecondExact(FractionalSecondDigits::F3)); +//! builder.alignment = Some(Alignment::Column); +//! builder.zone_style = Some(ZoneStyle::Z); +//! let dynamic_field_set = builder.build_composite().unwrap(); +//! +//! assert_eq!( +//! dynamic_field_set, +//! CompositeFieldSet::TimeZone(static_field_set.into_enums()), +//! ); +//! ``` + +use crate::fieldsets::{self, enums::*, Combo}; +use crate::options::*; + +/// An enumeration over all possible date and calendar period field sets +/// without options. +/// +/// This is a builder enum. See [`builder`](crate::fieldsets::builder). +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum DateFields { + /// The day of the month, as in + /// “on the 1st”. + D, + /// The month and day of the month, as in + /// “January 1st”. + MD, + /// The year, month, and day of the month, as in + /// “January 1st, 2000”. + YMD, + /// The day of the month and day of the week, as in + /// “Saturday 1st”. + DE, + /// The month, day of the month, and day of the week, as in + /// “Saturday, January 1st”. + MDE, + /// The year, month, day of the month, and day of the week, as in + /// “Saturday, January 1st, 2000”. + YMDE, + /// The day of the week alone, as in + /// “Saturday”. + E, + /// A standalone month, as in + /// “January”. + M, + /// A month and year, as in + /// “January 2000”. + YM, + /// A year, as in + /// “2000”. + Y, +} + +/// An enumeration over all possible time zone styles. +/// +/// This is a builder enum. See [`builder`](crate::fieldsets::builder). +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum ZoneStyle { + /// The long specific non-location format, as in + /// “Pacific Daylight Time”. + Z, + /// The short specific non-location format, as in + /// “PDT”. + Zs, + /// The long offset format, as in + /// “GMT−8:00”. + O, + /// The short offset format, as in + /// “GMT−8”. + Os, + /// The long generic non-location format, as in + /// “Pacific Time”. + V, + /// The short generic non-location format, as in + /// “PT”. + Vs, + /// The location format, as in + /// “Los Angeles time”. + L, +} + +/// An error that occurs when creating a [field set](crate::fieldsets) from a builder. +#[derive(Debug, displaydoc::Display)] +#[non_exhaustive] +pub enum BuilderError { + /// The specified fields are incompatible with the desired field set + InvalidFields, + /// The specified options are incompatible with the specified field set + InvalidOptions, +} + +/// A builder for [dynamic field sets](crate::fieldsets::enums). +/// +/// This builder is useful if you do not know the field set at code compilation time. If you do, +/// the static field set APIs should yield smaller binary size. +/// +/// For examples, see the [module docs](crate::fieldsets::builder). +// Note: could be Copy but we don't want implicit moves +#[derive(Debug, Clone, PartialEq, Eq, Default)] +#[non_exhaustive] +pub struct FieldSetBuilder { + /// The length of a formatted date/time string. + /// + /// If `None`, defaults to [`Length::Medium`]. + pub length: Option, + /// The set of date fields, such as "year and month" or "weekday". + /// + /// If `None`, a date will not be displayed. + pub date_fields: Option, + /// The precision to display the time of day. + /// + /// If `None`, a time will not be displayed. + pub time_precision: Option, + /// The style to display the time zone. + /// + /// If `None`, a time zone will not be displayed. + pub zone_style: Option, + /// The alignment context, such as when displaying dates in a table. + /// + /// This option may be specified only if the field set can honor it. + pub alignment: Option, + /// How to display the year and era. + /// + /// This option may be specified only if the year is included in [`Self::date_fields`]. + pub year_style: Option, +} + +// This is the default length when the builder is used. This could have been defined in the macro +// that generates the `take_from_builder` fns, but it would be easily lost. +pub(crate) const DEFAULT_LENGTH: Length = Length::Medium; + +impl FieldSetBuilder { + /// Builds a [`DateFieldSet`]. + /// + /// An error will occur if incompatible fields or options were set in the builder. + pub fn build_date(mut self) -> Result { + let date_field_set = match self.date_fields.take() { + Some(DateFields::D) => DateFieldSet::D(fieldsets::D::take_from_builder(&mut self)), + Some(DateFields::MD) => DateFieldSet::MD(fieldsets::MD::take_from_builder(&mut self)), + Some(DateFields::YMD) => { + DateFieldSet::YMD(fieldsets::YMD::take_from_builder(&mut self)) + } + Some(DateFields::DE) => DateFieldSet::DE(fieldsets::DE::take_from_builder(&mut self)), + Some(DateFields::MDE) => { + DateFieldSet::MDE(fieldsets::MDE::take_from_builder(&mut self)) + } + Some(DateFields::YMDE) => { + DateFieldSet::YMDE(fieldsets::YMDE::take_from_builder(&mut self)) + } + Some(DateFields::E) => DateFieldSet::E(fieldsets::E::take_from_builder(&mut self)), + Some(DateFields::M) | Some(DateFields::YM) | Some(DateFields::Y) | None => { + return Err(BuilderError::InvalidFields) + } + }; + self.check_options_consumed()?; + Ok(date_field_set) + } + + /// Builds a [`TimeFieldSet`]. + /// + /// An error will occur if incompatible fields or options were set in the builder. + pub fn build_time(mut self) -> Result { + let time_field_set = TimeFieldSet::T(fieldsets::T::take_from_builder(&mut self)); + self.check_options_consumed()?; + Ok(time_field_set) + } + + fn build_zone_without_checking_options(&mut self) -> Result { + let zone_field_set = match self.zone_style.take() { + Some(ZoneStyle::Z) => ZoneFieldSet::Z(fieldsets::Z::take_from_builder(self)), + Some(ZoneStyle::Zs) => ZoneFieldSet::Zs(fieldsets::Zs::take_from_builder(self)), + Some(ZoneStyle::O) => ZoneFieldSet::O(fieldsets::O::take_from_builder(self)), + Some(ZoneStyle::Os) => ZoneFieldSet::Os(fieldsets::Os::take_from_builder(self)), + Some(ZoneStyle::V) => ZoneFieldSet::V(fieldsets::V::take_from_builder(self)), + Some(ZoneStyle::Vs) => ZoneFieldSet::Vs(fieldsets::Vs::take_from_builder(self)), + Some(ZoneStyle::L) => ZoneFieldSet::L(fieldsets::L::take_from_builder(self)), + None => return Err(BuilderError::InvalidFields), + }; + Ok(zone_field_set) + } + + /// Builds a [`ZoneFieldSet`]. + /// + /// An error will occur if incompatible fields or options were set in the builder. + pub fn build_zone(mut self) -> Result { + let zone_field_set = self.build_zone_without_checking_options()?; + self.check_options_consumed()?; + Ok(zone_field_set) + } + + /// Builds a [`DateAndTimeFieldSet`]. + /// + /// An error will occur if incompatible fields or options were set in the builder. + pub fn build_date_and_time(mut self) -> Result { + let date_and_time_field_set = match self.date_fields.take() { + Some(DateFields::D) => { + DateAndTimeFieldSet::DT(fieldsets::DT::take_from_builder(&mut self)) + } + Some(DateFields::MD) => { + DateAndTimeFieldSet::MDT(fieldsets::MDT::take_from_builder(&mut self)) + } + Some(DateFields::YMD) => { + DateAndTimeFieldSet::YMDT(fieldsets::YMDT::take_from_builder(&mut self)) + } + Some(DateFields::DE) => { + DateAndTimeFieldSet::DET(fieldsets::DET::take_from_builder(&mut self)) + } + Some(DateFields::MDE) => { + DateAndTimeFieldSet::MDET(fieldsets::MDET::take_from_builder(&mut self)) + } + Some(DateFields::YMDE) => { + DateAndTimeFieldSet::YMDET(fieldsets::YMDET::take_from_builder(&mut self)) + } + Some(DateFields::E) => { + DateAndTimeFieldSet::ET(fieldsets::ET::take_from_builder(&mut self)) + } + Some(DateFields::M) | Some(DateFields::YM) | Some(DateFields::Y) | None => { + return Err(BuilderError::InvalidFields) + } + }; + Ok(date_and_time_field_set) + } + + /// Builds a [`CompositeDateTimeFieldSet`]. + /// + /// An error will occur if incompatible fields or options were set in the builder. + pub fn build_composite_datetime(self) -> Result { + // Check for the presence of date and time, then delegate to the correct impl. + match (self.date_fields.is_some(), self.time_precision.is_some()) { + (true, false) => self.build_date().map(CompositeDateTimeFieldSet::Date), + (false, true) => self.build_time().map(CompositeDateTimeFieldSet::Time), + (true, true) => self + .build_date_and_time() + .map(CompositeDateTimeFieldSet::DateTime), + (false, false) => Err(BuilderError::InvalidFields), + } + } + + /// Builds a [`CompositeFieldSet`]. + /// + /// An error will occur if incompatible fields or options were set in the builder. + pub fn build_composite(mut self) -> Result { + // Check for the presence of date, time, and zone, then delegate to the correct impl. + match ( + self.date_fields.is_some(), + self.time_precision.is_some(), + self.zone_style.is_some(), + ) { + (true, false, false) => self.build_date().map(CompositeFieldSet::Date), + (false, true, false) => self.build_time().map(CompositeFieldSet::Time), + (true, true, false) => self.build_date_and_time().map(CompositeFieldSet::DateTime), + (false, false, true) => self.build_zone().map(CompositeFieldSet::Zone), + (true, false, true) => { + let zone_field_set = self.build_zone_without_checking_options()?; + let date_field_set = self.build_date()?; + Ok(CompositeFieldSet::DateZone(Combo::new( + date_field_set, + zone_field_set, + ))) + } + (false, true, true) => { + let zone_field_set = self.build_zone_without_checking_options()?; + let time_field_set = self.build_time()?; + Ok(CompositeFieldSet::TimeZone(Combo::new( + time_field_set, + zone_field_set, + ))) + } + (true, true, true) => { + let zone_field_set = self.build_zone_without_checking_options()?; + let date_and_time_field_set = self.build_date_and_time()?; + Ok(CompositeFieldSet::DateTimeZone(Combo::new( + date_and_time_field_set, + zone_field_set, + ))) + } + (false, false, false) => Err(BuilderError::InvalidFields), + } + } + + fn check_options_consumed(self) -> Result<(), BuilderError> { + if self != Self::default() { + Err(BuilderError::InvalidOptions) + } else { + Ok(()) + } + } +} diff --git a/components/datetime/src/dynamic.rs b/components/datetime/src/dynamic.rs index 1984fc46e7e..1dcd2c41115 100644 --- a/components/datetime/src/dynamic.rs +++ b/components/datetime/src/dynamic.rs @@ -62,6 +62,7 @@ //! assert_eq!(results, ["Jan 15, 4:00 PM", "Jan 15"]) //! ``` +use crate::fieldsets::Combo; use crate::raw::neo::RawOptions; use crate::scaffold::GetField; use crate::{fields, fieldsets}; @@ -226,9 +227,9 @@ impl CompositeDateTimeFieldSet { CompositeFieldSet::Time(v) => Some(Self::Time(v)), CompositeFieldSet::Zone(_) => None, CompositeFieldSet::DateTime(v) => Some(Self::DateTime(v)), - CompositeFieldSet::DateZone(_, _) => None, - CompositeFieldSet::TimeZone(_, _) => None, - CompositeFieldSet::DateTimeZone(_, _) => None, + CompositeFieldSet::DateZone(_) => None, + CompositeFieldSet::TimeZone(_) => None, + CompositeFieldSet::DateTimeZone(_) => None, } } @@ -267,11 +268,11 @@ pub enum CompositeFieldSet { /// Field set for a date and a time together. DateTime(DateAndTimeFieldSet), /// Field set for a date and a time zone together. - DateZone(DateFieldSet, ZoneFieldSet), + DateZone(Combo), /// Field set for a time and a time zone together. - TimeZone(TimeFieldSet, ZoneFieldSet), + TimeZone(Combo), /// Field set for a date, a time, and a time zone together. - DateTimeZone(DateAndTimeFieldSet, ZoneFieldSet), + DateTimeZone(Combo), } macro_rules! first { diff --git a/components/datetime/src/fieldsets.rs b/components/datetime/src/fieldsets.rs index 75e0842e2d8..9eb115fd807 100644 --- a/components/datetime/src/fieldsets.rs +++ b/components/datetime/src/fieldsets.rs @@ -49,6 +49,8 @@ //! assert_eq!(field_set_1, field_set_2); //! ``` +#[path = "builder.rs"] +pub mod builder; #[path = "dynamic.rs"] pub mod enums; @@ -217,8 +219,8 @@ macro_rules! impl_marker_with_options { pub time_precision: datetime_marker_helper!(@option/timeprecision, $timeprecision_yes), )? } - #[allow(dead_code)] impl $type { + #[allow(dead_code)] pub(crate) fn to_raw_options(self) -> RawOptions { RawOptions { length: yes_or!(self.length, $(Length::$length_override)?), @@ -236,6 +238,19 @@ macro_rules! impl_marker_with_options { $(time_precision: yes_to!(options.time_precision, $timeprecision_yes),)? } } + /// Builds this field set, removing the needed options from the builder. + /// If length is needed but is None, falls back to `builder::DEFAULT_LENGTH`. + #[allow(unused)] + pub(crate) fn take_from_builder( + options: &mut builder::FieldSetBuilder + ) -> Self { + Self { + $(length: yes_to!(options.length.take().unwrap_or(builder::DEFAULT_LENGTH), $sample_length),)? + $(alignment: yes_to!(options.alignment.take(), $alignment_yes),)? + $(year_style: yes_to!(options.year_style.take(), $yearstyle_yes),)? + $(time_precision: yes_to!(options.time_precision.take(), $timeprecision_yes),)? + } + } } $( impl $type { @@ -273,11 +288,20 @@ macro_rules! impl_marker_with_options { } macro_rules! impl_combo_get_field { - ($type:ident, $composite:ident, $enum:ident, $wrap:ident, $variant:ident) => { + ($type:ident, $composite:ident, $enum:ident, $variant:ident) => { impl GetField for Combo<$type, $variant> { #[inline] fn get_field(&self) -> CompositeFieldSet { - CompositeFieldSet::$composite(self.dt().to_enum(), self.z().to_enum()) + CompositeFieldSet::$composite(Combo::new(self.dt().to_enum(), self.z().to_enum())) + } + } + impl Combo<$type, $variant> { + /// Convert this specific [`Combo`] into a more general [`Combo`]. + /// Useful when adding to the field of a [`CompositeFieldSet`]. + /// + /// [`CompositeFieldSet`]: enums::CompositeFieldSet + pub fn into_enums(self) -> Combo<$enum, ZoneFieldSet> { + Combo::new(self.dt().to_enum(), self.z().to_enum()) } } }; @@ -287,8 +311,7 @@ macro_rules! impl_zone_combo_helpers { ( $type:ident, $composite:ident, - $enum:ident, - $wrap:ident + $enum:ident ) => { impl $type { /// Associates this field set with a long specific non-location format time zone, as in @@ -334,13 +357,13 @@ macro_rules! impl_zone_combo_helpers { Combo::new(self, L::new()) } } - impl_combo_get_field!($type, $composite, $enum, $wrap, Z); - impl_combo_get_field!($type, $composite, $enum, $wrap, Zs); - impl_combo_get_field!($type, $composite, $enum, $wrap, O); - impl_combo_get_field!($type, $composite, $enum, $wrap, Os); - impl_combo_get_field!($type, $composite, $enum, $wrap, V); - impl_combo_get_field!($type, $composite, $enum, $wrap, Vs); - impl_combo_get_field!($type, $composite, $enum, $wrap, L); + impl_combo_get_field!($type, $composite, $enum, Z); + impl_combo_get_field!($type, $composite, $enum, Zs); + impl_combo_get_field!($type, $composite, $enum, O); + impl_combo_get_field!($type, $composite, $enum, Os); + impl_combo_get_field!($type, $composite, $enum, V); + impl_combo_get_field!($type, $composite, $enum, Vs); + impl_combo_get_field!($type, $composite, $enum, L); }; } @@ -527,7 +550,7 @@ macro_rules! impl_date_marker { $(input_any_calendar_kind = $any_calendar_kind_yes,)? $(option_alignment = $option_alignment_yes,)? ); - impl_zone_combo_helpers!($type, DateZone, DateFieldSet, wrap); + impl_zone_combo_helpers!($type, DateZone, DateFieldSet); impl_composite!($type, Date, DateFieldSet); impl_marker_with_options!( #[doc = concat!("**“", $sample_time, "**” ⇒ ", $description, " with time")] @@ -591,7 +614,7 @@ macro_rules! impl_date_marker { $(year_style: $year_yes,)? time_precision: yes, ); - impl_zone_combo_helpers!($type_time, DateTimeZone, DateAndTimeFieldSet, wrap); + impl_zone_combo_helpers!($type_time, DateTimeZone, DateAndTimeFieldSet); impl UnstableSealed for $type_time {} impl DateTimeNamesMarker for $type_time { type YearNames = datetime_marker_helper!(@names/year, $($years_yes)?); @@ -757,7 +780,7 @@ macro_rules! impl_time_marker { alignment: yes, time_precision: yes, ); - impl_zone_combo_helpers!($type, TimeZone, TimeFieldSet, wrap); + impl_zone_combo_helpers!($type, TimeZone, TimeFieldSet); impl UnstableSealed for $type {} impl DateTimeNamesMarker for $type { type YearNames = datetime_marker_helper!(@names/year,); @@ -1539,8 +1562,8 @@ impl_zone_marker!( input_tzid = yes, ); -impl_zone_combo_helpers!(DateFieldSet, DateZone, UNREACHABLE, no_wrap); +impl_zone_combo_helpers!(DateFieldSet, DateZone, DateFieldSet); -impl_zone_combo_helpers!(TimeFieldSet, TimeZone, UNREACHABLE, no_wrap); +impl_zone_combo_helpers!(TimeFieldSet, TimeZone, TimeFieldSet); -impl_zone_combo_helpers!(DateAndTimeFieldSet, DateTimeZone, UNREACHABLE, no_wrap); +impl_zone_combo_helpers!(DateAndTimeFieldSet, DateTimeZone, DateAndTimeFieldSet); diff --git a/components/datetime/src/neo_serde.rs b/components/datetime/src/neo_serde.rs index d632617d7a0..6898e9f8752 100644 --- a/components/datetime/src/neo_serde.rs +++ b/components/datetime/src/neo_serde.rs @@ -5,7 +5,7 @@ //! Serde definitions for semantic skeleta use crate::{ - fieldsets::{self, enums::*}, + fieldsets::{self, enums::*, Combo}, options::*, raw::neo::RawOptions, }; @@ -120,22 +120,25 @@ impl From for CompositeFieldSetSerde { date_options.merge(time_options), ) } - CompositeFieldSet::DateZone(v, z) => { - let (date_serde, date_options) = FieldSetSerde::from_date_field_set(v); - let (zone_serde, _ignored_options) = FieldSetSerde::from_zone_field_set(z, false); + CompositeFieldSet::DateZone(v) => { + let (date_serde, date_options) = FieldSetSerde::from_date_field_set(v.dt()); + let (zone_serde, _ignored_options) = + FieldSetSerde::from_zone_field_set(v.z(), false); (date_serde.extend(zone_serde), date_options) } - CompositeFieldSet::TimeZone(v, z) => { - let (time_serde, time_options) = FieldSetSerde::from_time_field_set(v); - let (zone_serde, _ignored_options) = FieldSetSerde::from_zone_field_set(z, false); + CompositeFieldSet::TimeZone(v) => { + let (time_serde, time_options) = FieldSetSerde::from_time_field_set(v.dt()); + let (zone_serde, _ignored_options) = + FieldSetSerde::from_zone_field_set(v.z(), false); (time_serde.extend(zone_serde), time_options) } - CompositeFieldSet::DateTimeZone(v, z) => { + CompositeFieldSet::DateTimeZone(v) => { let (date_serde, date_options) = - FieldSetSerde::from_date_field_set(v.to_date_field_set()); + FieldSetSerde::from_date_field_set(v.dt().to_date_field_set()); let (time_serde, time_options) = - FieldSetSerde::from_time_field_set(v.to_time_field_set()); - let (zone_serde, _ignored_options) = FieldSetSerde::from_zone_field_set(z, false); + FieldSetSerde::from_time_field_set(v.dt().to_time_field_set()); + let (zone_serde, _ignored_options) = + FieldSetSerde::from_zone_field_set(v.z(), false); ( date_serde.extend(time_serde).extend(zone_serde), date_options.merge(time_options), @@ -197,7 +200,7 @@ impl TryFrom for CompositeFieldSet { .and_then(|date_field_set| { zone.to_zone_field_set(options, false) .map(|zone_field_set| { - CompositeFieldSet::DateZone(date_field_set, zone_field_set) + CompositeFieldSet::DateZone(Combo::new(date_field_set, zone_field_set)) }) }) .ok_or(Self::Error::InvalidFields), @@ -206,7 +209,7 @@ impl TryFrom for CompositeFieldSet { .and_then(|time_field_set| { zone.to_zone_field_set(options, false) .map(|zone_field_set| { - CompositeFieldSet::TimeZone(time_field_set, zone_field_set) + CompositeFieldSet::TimeZone(Combo::new(time_field_set, zone_field_set)) }) }) .ok_or(Self::Error::InvalidFields), @@ -215,13 +218,13 @@ impl TryFrom for CompositeFieldSet { .and_then(|date_field_set| { zone.to_zone_field_set(options, false) .map(|zone_field_set| { - CompositeFieldSet::DateTimeZone( + CompositeFieldSet::DateTimeZone(Combo::new( DateAndTimeFieldSet::from_date_field_set_with_raw_options( date_field_set, options, ), zone_field_set, - ) + )) }) }) .ok_or(Self::Error::InvalidFields), @@ -586,7 +589,7 @@ impl FieldSetSerde { #[test] fn test_basic() { - let skeleton = CompositeFieldSet::DateTimeZone( + let skeleton = CompositeFieldSet::DateTimeZone(Combo::new( DateAndTimeFieldSet::YMDET(fieldsets::YMDET { length: Length::Medium, alignment: Some(Alignment::Column), @@ -594,7 +597,7 @@ fn test_basic() { time_precision: Some(TimePrecision::SecondExact(FractionalSecondDigits::F3)), }), ZoneFieldSet::Vs(fieldsets::Vs::new()), - ); + )); let skeleton_serde = CompositeFieldSetSerde::from(skeleton); let json_string = serde_json::to_string(&skeleton_serde).unwrap(); diff --git a/components/datetime/src/raw/neo.rs b/components/datetime/src/raw/neo.rs index 71bc60f59cc..59bc0a2ecad 100644 --- a/components/datetime/src/raw/neo.rs +++ b/components/datetime/src/raw/neo.rs @@ -566,45 +566,45 @@ impl DateTimeZonePatternSelectionData { let glue = Self::load_glue(glue_provider, prefs, options, GlueType::DateTime)?; Ok(Self::DateTimeGlue { date, time, glue }) } - CompositeFieldSet::DateZone(field_set, zone_field_set) => { - let options = field_set.to_raw_options(); + CompositeFieldSet::DateZone(combo) => { + let options = combo.dt().to_raw_options(); let date = DatePatternSelectionData::try_new_with_skeleton( date_provider, prefs, - field_set.id_str(), + combo.dt().id_str(), options, )?; - let zone = ZonePatternSelectionData::new_with_skeleton(zone_field_set); + let zone = ZonePatternSelectionData::new_with_skeleton(combo.z()); let glue = Self::load_glue(glue_provider, prefs, options, GlueType::DateZone)?; Ok(Self::DateZoneGlue { date, zone, glue }) } - CompositeFieldSet::TimeZone(field_set, zone_field_set) => { - let options = field_set.to_raw_options(); + CompositeFieldSet::TimeZone(combo) => { + let options = combo.dt().to_raw_options(); let time = TimePatternSelectionData::try_new_with_skeleton( time_provider, prefs, - field_set, + combo.dt(), options, )?; - let zone = ZonePatternSelectionData::new_with_skeleton(zone_field_set); + let zone = ZonePatternSelectionData::new_with_skeleton(combo.z()); let glue = Self::load_glue(glue_provider, prefs, options, GlueType::TimeZone)?; Ok(Self::TimeZoneGlue { time, zone, glue }) } - CompositeFieldSet::DateTimeZone(field_set, zone_field_set) => { - let options = field_set.to_raw_options(); + CompositeFieldSet::DateTimeZone(combo) => { + let options = combo.dt().to_raw_options(); let date = DatePatternSelectionData::try_new_with_skeleton( date_provider, prefs, - field_set.to_date_field_set().id_str(), + combo.dt().to_date_field_set().id_str(), options, )?; let time = TimePatternSelectionData::try_new_with_skeleton( time_provider, prefs, - field_set.to_time_field_set(), + combo.dt().to_time_field_set(), options, )?; - let zone = ZonePatternSelectionData::new_with_skeleton(zone_field_set); + let zone = ZonePatternSelectionData::new_with_skeleton(combo.z()); let glue = Self::load_glue(glue_provider, prefs, options, GlueType::DateTimeZone)?; Ok(Self::DateTimeZoneGlue { date, diff --git a/ffi/capi/tests/missing_apis.txt b/ffi/capi/tests/missing_apis.txt index e9d5b797369..4ba7b185980 100644 --- a/ffi/capi/tests/missing_apis.txt +++ b/ffi/capi/tests/missing_apis.txt @@ -95,6 +95,7 @@ icu::datetime::Length::into_option#FnInEnum icu::datetime::MismatchedCalendarError#Struct icu::datetime::TimeFormatter#Typedef icu::datetime::fieldsets::Combo#Struct +icu::datetime::fieldsets::Combo::into_enums#FnInStruct icu::datetime::fieldsets::Combo::map_day_period_names#FnInStruct icu::datetime::fieldsets::Combo::map_metazone_lookup#FnInStruct icu::datetime::fieldsets::Combo::map_month_names#FnInStruct @@ -629,6 +630,16 @@ icu::datetime::fieldsets::Zs::map_zone_locations#FnInStruct icu::datetime::fieldsets::Zs::map_zone_specific_long#FnInStruct icu::datetime::fieldsets::Zs::map_zone_specific_short#FnInStruct icu::datetime::fieldsets::Zs::new#FnInStruct +icu::datetime::fieldsets::builder::BuilderError#Enum +icu::datetime::fieldsets::builder::DateFields#Enum +icu::datetime::fieldsets::builder::FieldSetBuilder#Struct +icu::datetime::fieldsets::builder::FieldSetBuilder::build_composite#FnInStruct +icu::datetime::fieldsets::builder::FieldSetBuilder::build_composite_datetime#FnInStruct +icu::datetime::fieldsets::builder::FieldSetBuilder::build_date#FnInStruct +icu::datetime::fieldsets::builder::FieldSetBuilder::build_date_and_time#FnInStruct +icu::datetime::fieldsets::builder::FieldSetBuilder::build_time#FnInStruct +icu::datetime::fieldsets::builder::FieldSetBuilder::build_zone#FnInStruct +icu::datetime::fieldsets::builder::ZoneStyle#Enum icu::datetime::fieldsets::enums::CalendarPeriodFieldSet#Enum icu::datetime::fieldsets::enums::CalendarPeriodFieldSet::map_day_period_names#FnInEnum icu::datetime::fieldsets::enums::CalendarPeriodFieldSet::map_metazone_lookup#FnInEnum