Skip to content

Commit

Permalink
Merge branch 'main' into fset-builder
Browse files Browse the repository at this point in the history
  • Loading branch information
sffc committed Dec 21, 2024
2 parents f43d1a8 + 8c064d0 commit 2ba04a9
Show file tree
Hide file tree
Showing 8 changed files with 859 additions and 197 deletions.
104 changes: 104 additions & 0 deletions components/datetime/src/neo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,22 @@ define_preferences!(
/// The user's preferred numbering system.
///
/// Corresponds to the `-u-nu` in Unicode Locale Identifier.
///
/// To get the resolved numbering system, you can inspect the data provider.
/// See the [`icu_decimal::provider`] module for an example.
numbering_system: NumberingSystem,
/// The user's preferred hour cycle.
///
/// Corresponds to the `-u-hc` in Unicode Locale Identifier.
///
/// To get the resolved hour cycle, you can inspect the formatting pattern.
/// See [`DateTimePattern`](crate::pattern::DateTimePattern) for an example.
hour_cycle: HourCycle,
/// The user's preferred calendar system
///
/// Corresponds to the `-u-ca` in Unicode Locale Identifier.
///
/// To get the resolved calendar system, use [`DateTimeFormatter::calendar_kind()`].
calendar_algorithm: CalendarAlgorithm
}
);
Expand Down Expand Up @@ -704,6 +712,55 @@ impl<C: CldrCalendar, FSet: DateTimeMarkers> FixedCalendarDateTimeFormatter<C, F
calendar: calendar.to_any(),
}
}

/// Maps a [`FixedCalendarDateTimeFormatter`] of a specific `FSet` to a more general `FSet`.
///
/// For example, this can transform a formatter for [`YMD`] to one for [`DateFieldSet`].
///
/// [`YMD`]: crate::fieldsets::YMD
/// [`DateFieldSet`]: crate::fieldsets::enums::DateFieldSet
///
/// # Examples
///
/// ```
/// use icu::calendar::Gregorian;
/// use icu::calendar::DateTime;
/// use icu::datetime::FixedCalendarDateTimeFormatter;
/// use icu::datetime::fieldsets::{YMD, enums::DateFieldSet};
/// use icu::locale::locale;
/// use writeable::assert_writeable_eq;
///
/// let specific_formatter = FixedCalendarDateTimeFormatter::try_new(
/// locale!("fr").into(),
/// YMD::medium(),
/// )
/// .unwrap();
///
/// // Test that the specific formatter works:
/// let datetime = DateTime::try_new_gregorian(2024, 12, 20, 14, 30, 0).unwrap();
/// assert_writeable_eq!(
/// specific_formatter.format(&datetime),
/// "20 déc. 2024"
/// );
///
/// // Make a more general formatter:
/// let general_formatter = specific_formatter.with_fset::<DateFieldSet>();
///
/// // Test that it still works:
/// assert_writeable_eq!(
/// general_formatter.format(&datetime),
/// "20 déc. 2024"
/// );
/// ```
pub fn with_fset<FSet2: DateTimeNamesFrom<FSet>>(
self,
) -> FixedCalendarDateTimeFormatter<C, FSet2> {
FixedCalendarDateTimeFormatter {
selection: self.selection,
names: self.names.with_fset(),
_calendar: PhantomData,
}
}
}

impl<FSet: DateTimeMarkers> DateTimeFormatter<FSet> {
Expand Down Expand Up @@ -772,6 +829,53 @@ impl<FSet: DateTimeMarkers> DateTimeFormatter<FSet> {
})
}

/// Maps a [`DateTimeFormatter`] of a specific `FSet` to a more general `FSet`.
///
/// For example, this can transform a formatter for [`YMD`] to one for [`DateFieldSet`].
///
/// [`YMD`]: crate::fieldsets::YMD
/// [`DateFieldSet`]: crate::fieldsets::enums::DateFieldSet
///
/// # Examples
///
/// ```
/// use icu::calendar::Gregorian;
/// use icu::calendar::DateTime;
/// use icu::datetime::DateTimeFormatter;
/// use icu::datetime::fieldsets::{YMD, enums::DateFieldSet};
/// use icu::locale::locale;
/// use writeable::assert_writeable_eq;
///
/// let specific_formatter = DateTimeFormatter::try_new(
/// locale!("fr").into(),
/// YMD::medium(),
/// )
/// .unwrap();
///
/// // Test that the specific formatter works:
/// let datetime = DateTime::try_new_gregorian(2024, 12, 20, 14, 30, 0).unwrap();
/// assert_writeable_eq!(
/// specific_formatter.format_any_calendar(&datetime),
/// "20 déc. 2024"
/// );
///
/// // Make a more general formatter:
/// let general_formatter = specific_formatter.with_fset::<DateFieldSet>();
///
/// // Test that it still works:
/// assert_writeable_eq!(
/// general_formatter.format_any_calendar(&datetime),
/// "20 déc. 2024"
/// );
/// ```
pub fn with_fset<FSet2: DateTimeNamesFrom<FSet>>(self) -> DateTimeFormatter<FSet2> {
DateTimeFormatter {
selection: self.selection,
names: self.names.with_fset(),
calendar: self.calendar,
}
}

/// Returns the calendar system used in this formatter.
///
/// # Examples
Expand Down
197 changes: 152 additions & 45 deletions components/datetime/src/pattern/names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,41 +228,30 @@ pub struct TypedDateTimeNames<
}

pub(crate) struct RawDateTimeNames<FSet: DateTimeNamesMarker> {
year_names:
<FSet::YearNames as DateTimeNamesHolderTrait<YearNamesV1Marker>>::Container<FieldLength>,
month_names: <FSet::MonthNames as DateTimeNamesHolderTrait<MonthNamesV1Marker>>::Container<(
fields::Month,
FieldLength,
)>,
weekday_names:
<FSet::WeekdayNames as DateTimeNamesHolderTrait<WeekdayNamesV1Marker>>::Container<(
fields::Weekday,
FieldLength,
)>,
year_names: <FSet::YearNames as NamesContainer<YearNamesV1Marker, FieldLength>>::Container,
month_names: <FSet::MonthNames as NamesContainer<
MonthNamesV1Marker,
(fields::Month, FieldLength),
>>::Container,
weekday_names: <FSet::WeekdayNames as NamesContainer<
WeekdayNamesV1Marker,
(fields::Weekday, FieldLength),
>>::Container,
dayperiod_names:
<FSet::DayPeriodNames as DateTimeNamesHolderTrait<DayPeriodNamesV1Marker>>::Container<
FieldLength,
>,
<FSet::DayPeriodNames as NamesContainer<DayPeriodNamesV1Marker, FieldLength>>::Container,
zone_essentials:
<FSet::ZoneEssentials as DateTimeNamesHolderTrait<tz::EssentialsV1Marker>>::Container<()>,
locations_root:
<FSet::ZoneLocations as DateTimeNamesHolderTrait<tz::LocationsV1Marker>>::Container<()>,
locations:
<FSet::ZoneLocations as DateTimeNamesHolderTrait<tz::LocationsV1Marker>>::Container<()>,
mz_generic_long: <FSet::ZoneGenericLong as DateTimeNamesHolderTrait<
tz::MzGenericLongV1Marker,
>>::Container<()>,
mz_generic_short: <FSet::ZoneGenericShort as DateTimeNamesHolderTrait<
tz::MzGenericShortV1Marker,
>>::Container<()>,
mz_specific_long: <FSet::ZoneSpecificLong as DateTimeNamesHolderTrait<
tz::MzSpecificLongV1Marker,
>>::Container<()>,
mz_specific_short: <FSet::ZoneSpecificShort as DateTimeNamesHolderTrait<
tz::MzSpecificShortV1Marker,
>>::Container<()>,
mz_periods:
<FSet::MetazoneLookup as DateTimeNamesHolderTrait<tz::MzPeriodV1Marker>>::Container<()>,
<FSet::ZoneEssentials as NamesContainer<tz::EssentialsV1Marker, ()>>::Container,
locations_root: <FSet::ZoneLocations as NamesContainer<tz::LocationsV1Marker, ()>>::Container,
locations: <FSet::ZoneLocations as NamesContainer<tz::LocationsV1Marker, ()>>::Container,
mz_generic_long:
<FSet::ZoneGenericLong as NamesContainer<tz::MzGenericLongV1Marker, ()>>::Container,
mz_generic_short:
<FSet::ZoneGenericShort as NamesContainer<tz::MzGenericShortV1Marker, ()>>::Container,
mz_specific_long:
<FSet::ZoneSpecificLong as NamesContainer<tz::MzSpecificLongV1Marker, ()>>::Container,
mz_specific_short:
<FSet::ZoneSpecificShort as NamesContainer<tz::MzSpecificShortV1Marker, ()>>::Container,
mz_periods: <FSet::MetazoneLookup as NamesContainer<tz::MzPeriodV1Marker, ()>>::Container,
// TODO(#4340): Make the FixedDecimalFormatter optional
fixed_decimal_formatter: Option<FixedDecimalFormatter>,
_marker: PhantomData<FSet>,
Expand All @@ -287,6 +276,27 @@ impl<FSet: DateTimeNamesMarker> fmt::Debug for RawDateTimeNames<FSet> {
}
}

impl<FSet: DateTimeNamesMarker> RawDateTimeNames<FSet> {
pub(crate) fn with_fset<FSet2: DateTimeNamesFrom<FSet>>(self) -> RawDateTimeNames<FSet2> {
RawDateTimeNames {
year_names: FSet2::map_year_names(self.year_names),
month_names: FSet2::map_month_names(self.month_names),
weekday_names: FSet2::map_weekday_names(self.weekday_names),
dayperiod_names: FSet2::map_day_period_names(self.dayperiod_names),
zone_essentials: FSet2::map_zone_essentials(self.zone_essentials),
locations_root: FSet2::map_zone_locations(self.locations_root),
locations: FSet2::map_zone_locations(self.locations),
mz_generic_long: FSet2::map_zone_generic_long(self.mz_generic_long),
mz_generic_short: FSet2::map_zone_generic_short(self.mz_generic_short),
mz_specific_long: FSet2::map_zone_specific_long(self.mz_specific_long),
mz_specific_short: FSet2::map_zone_specific_short(self.mz_specific_short),
mz_periods: FSet2::map_metazone_lookup(self.mz_periods),
fixed_decimal_formatter: self.fixed_decimal_formatter,
_marker: PhantomData,
}
}
}

#[derive(Debug, Copy, Clone)]
pub(crate) struct RawDateTimeNamesBorrowed<'l> {
year_names: OptionalNames<FieldLength, &'l YearNamesV1<'l>>,
Expand Down Expand Up @@ -1310,23 +1320,120 @@ impl<C: CldrCalendar, FSet: DateTimeNamesMarker> TypedDateTimeNames<C, FSet> {
self.inner.as_borrowed(),
))
}

/// Maps a [`TypedDateTimeNames`] of a specific `FSet` to a more general `FSet`.
///
/// For example, this can transform a formatter for [`DateFieldSet`] to one for
/// [`CompositeDateTimeFieldSet`].
///
/// [`DateFieldSet`]: crate::fieldsets::enums::DateFieldSet
/// [`CompositeDateTimeFieldSet`]: crate::fieldsets::enums::CompositeDateTimeFieldSet
///
/// # Examples
///
/// ```
/// use icu::calendar::Gregorian;
/// use icu::calendar::DateTime;
/// use icu::datetime::pattern::TypedDateTimeNames;
/// use icu::datetime::fields::FieldLength;
/// use icu::datetime::fields;
/// use icu::datetime::fieldsets::enums::{DateFieldSet, CompositeDateTimeFieldSet};
/// use icu::datetime::pattern::DateTimePattern;
/// use icu::locale::locale;
/// use writeable::assert_try_writeable_eq;
///
/// // Create an instance that can format abbreviated month names:
/// let mut names: TypedDateTimeNames<Gregorian, DateFieldSet> =
/// TypedDateTimeNames::try_new(locale!("uk").into()).unwrap();
/// names
/// .include_month_names(fields::Month::Format, FieldLength::Three)
/// .unwrap();
///
/// // Test it with a pattern:
/// let pattern_str = "MMM d y";
/// let pattern: DateTimePattern = pattern_str.parse().unwrap();
/// let datetime = DateTime::try_new_gregorian(2023, 11, 20, 12, 35, 3).unwrap();
/// assert_try_writeable_eq!(names.with_pattern_unchecked(&pattern).format(&datetime), "лист. 20 2023");
///
/// // Convert the field set to `CompositeDateTimeFieldSet`:
/// let composite_names = names.with_fset::<CompositeDateTimeFieldSet>();
///
/// // It should still work:
/// assert_try_writeable_eq!(composite_names.with_pattern_unchecked(&pattern).format(&datetime), "лист. 20 2023");
/// ```
///
/// Converting into a narrower type is not supported:
///
/// ```compile_fail,E0277
/// use icu::calendar::Gregorian;
/// use icu::datetime::pattern::TypedDateTimeNames;
/// use icu::datetime::fieldsets::enums::{DateFieldSet, CompositeDateTimeFieldSet};
///
/// let composite_names: TypedDateTimeNames<Gregorian, CompositeDateTimeFieldSet> = todo!();
///
/// // error[E0277]: the trait bound `(): From<DataPayloadWithVariables<DayPeriodNamesV1Marker, FieldLength>>` is not satisfied
/// let narrow_names = composite_names.with_fset::<DateFieldSet>();
/// ```
pub fn with_fset<FSet2: DateTimeNamesFrom<FSet>>(self) -> TypedDateTimeNames<C, FSet2> {
TypedDateTimeNames {
prefs: self.prefs,
inner: self.inner.with_fset(),
_calendar: PhantomData,
}
}
}

impl<FSet: DateTimeNamesMarker> RawDateTimeNames<FSet> {
pub(crate) fn new_without_number_formatting() -> Self {
Self {
year_names: <FSet::YearNames as DateTimeNamesHolderTrait<YearNamesV1Marker>>::Container::<_>::new_empty(),
month_names: <FSet::MonthNames as DateTimeNamesHolderTrait<MonthNamesV1Marker>>::Container::<_>::new_empty(),
weekday_names: <FSet::WeekdayNames as DateTimeNamesHolderTrait<WeekdayNamesV1Marker>>::Container::<_>::new_empty(),
dayperiod_names: <FSet::DayPeriodNames as DateTimeNamesHolderTrait<DayPeriodNamesV1Marker>>::Container::<_>::new_empty(),
zone_essentials: <FSet::ZoneEssentials as DateTimeNamesHolderTrait<tz::EssentialsV1Marker>>::Container::<_>::new_empty(),
locations_root: <FSet::ZoneLocations as DateTimeNamesHolderTrait<tz::LocationsV1Marker>>::Container::<_>::new_empty(),
locations: <FSet::ZoneLocations as DateTimeNamesHolderTrait<tz::LocationsV1Marker>>::Container::<_>::new_empty(),
mz_generic_long: <FSet::ZoneGenericLong as DateTimeNamesHolderTrait<tz::MzGenericLongV1Marker>>::Container::<_>::new_empty(),
mz_generic_short: <FSet::ZoneGenericShort as DateTimeNamesHolderTrait<tz::MzGenericShortV1Marker>>::Container::<_>::new_empty(),
mz_specific_long: <FSet::ZoneSpecificLong as DateTimeNamesHolderTrait<tz::MzSpecificLongV1Marker>>::Container::<_>::new_empty(),
mz_specific_short: <FSet::ZoneSpecificShort as DateTimeNamesHolderTrait<tz::MzSpecificShortV1Marker>>::Container::<_>::new_empty(),
mz_periods: <FSet::MetazoneLookup as DateTimeNamesHolderTrait<tz::MzPeriodV1Marker>>::Container::<_>::new_empty(),
year_names: <FSet::YearNames as NamesContainer<
YearNamesV1Marker,
FieldLength,
>>::Container::new_empty(),
month_names: <FSet::MonthNames as NamesContainer<
MonthNamesV1Marker,
(fields::Month, FieldLength),
>>::Container::new_empty(),
weekday_names: <FSet::WeekdayNames as NamesContainer<
WeekdayNamesV1Marker,
(fields::Weekday, FieldLength),
>>::Container::new_empty(),
dayperiod_names: <FSet::DayPeriodNames as NamesContainer<
DayPeriodNamesV1Marker,
FieldLength,
>>::Container::new_empty(),
zone_essentials: <FSet::ZoneEssentials as NamesContainer<
tz::EssentialsV1Marker,
(),
>>::Container::new_empty(),
locations_root: <FSet::ZoneLocations as NamesContainer<
tz::LocationsV1Marker,
(),
>>::Container::new_empty(),
locations: <FSet::ZoneLocations as NamesContainer<
tz::LocationsV1Marker,
(),
>>::Container::new_empty(),
mz_generic_long: <FSet::ZoneGenericLong as NamesContainer<
tz::MzGenericLongV1Marker,
(),
>>::Container::new_empty(),
mz_generic_short: <FSet::ZoneGenericShort as NamesContainer<
tz::MzGenericShortV1Marker,
(),
>>::Container::new_empty(),
mz_specific_long: <FSet::ZoneSpecificLong as NamesContainer<
tz::MzSpecificLongV1Marker,
(),
>>::Container::new_empty(),
mz_specific_short: <FSet::ZoneSpecificShort as NamesContainer<
tz::MzSpecificShortV1Marker,
(),
>>::Container::new_empty(),
mz_periods: <FSet::MetazoneLookup as NamesContainer<
tz::MzPeriodV1Marker,
(),
>>::Container::new_empty(),
fixed_decimal_formatter: None,
_marker: PhantomData,
}
Expand Down
3 changes: 2 additions & 1 deletion components/datetime/src/scaffold/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,11 @@ pub use get_field::GetField;

pub use names_storage::DataPayloadWithVariables;
pub use names_storage::DataPayloadWithVariablesBorrowed;
pub use names_storage::DateTimeNamesHolderTrait;
pub use names_storage::DateTimeNamesFrom;
pub use names_storage::DateTimeNamesMarker;
pub use names_storage::MaybePayload;
pub use names_storage::MaybePayloadError;
pub use names_storage::NamesContainer;
pub(crate) use names_storage::OptionalNames;

/// Trait marking other traits that are considered unstable and should not generally be
Expand Down
Loading

0 comments on commit 2ba04a9

Please sign in to comment.