From e5ca66d4657d41084a359232880ef1cd8e3dfbb6 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Wed, 20 Nov 2024 14:09:02 -0800 Subject: [PATCH] DateTimeFormatterPreferences (#5842) #1317 --- README.md | 2 +- components/calendar/src/any_calendar.rs | 75 +++++- components/calendar/src/lib.rs | 2 +- components/datetime/README.md | 2 +- components/datetime/benches/datetime.rs | 2 +- components/datetime/examples/work_log.rs | 2 +- components/datetime/src/combo.rs | 6 +- components/datetime/src/dynamic.rs | 3 +- components/datetime/src/external_loaders.rs | 44 ++-- components/datetime/src/fieldsets.rs | 48 ++-- components/datetime/src/lib.rs | 3 +- components/datetime/src/neo.rs | 167 ++++++------ components/datetime/src/options/mod.rs | 20 +- components/datetime/src/pattern/formatter.rs | 17 +- components/datetime/src/pattern/names.rs | 240 ++++++++++-------- components/datetime/src/pattern/pattern.rs | 2 +- components/datetime/src/raw/neo.rs | 75 +++--- components/datetime/tests/datetime.rs | 31 ++- .../datetime/tests/resolved_components.rs | 2 +- components/datetime/tests/simple_test.rs | 35 +-- components/icu/README.md | 4 +- components/icu/examples/tui.rs | 10 +- components/icu/src/lib.rs | 4 +- ffi/capi/src/calendar.rs | 4 +- ffi/capi/src/datetime_formatter.rs | 20 +- ffi/capi/src/zoned_formatter.rs | 8 +- ffi/capi/tests/missing_apis.txt | 6 + provider/core/src/marker.rs | 10 +- provider/core/src/request.rs | 10 +- tutorials/data_management.md | 4 +- tutorials/intro.md | 2 +- tutorials/intro_interactive.md | 2 +- tutorials/rust/buffer/src/main.rs | 4 +- 33 files changed, 464 insertions(+), 402 deletions(-) diff --git a/README.md b/README.md index 64067fe685e..377c5ef66c6 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ use icu::datetime::{DateTimeFormatter, NeoSkeletonLength, fieldsets::YMDT}; use icu::locale::locale; let dtf = DateTimeFormatter::try_new( - &locale!("es").into(), + locale!("es").into(), YMDT::long() ) .expect("locale should be present in compiled data"); diff --git a/components/calendar/src/any_calendar.rs b/components/calendar/src/any_calendar.rs index b18d8ba2c8a..e847e5ea55d 100644 --- a/components/calendar/src/any_calendar.rs +++ b/components/calendar/src/any_calendar.rs @@ -21,12 +21,26 @@ use crate::roc::Roc; use crate::{types, AsCalendar, Calendar, Date, DateDuration, DateDurationUnit, DateTime, Ref}; use icu_locale_core::extensions::unicode::{key, value, Value}; +use icu_locale_core::preferences::define_preferences; +use icu_locale_core::preferences::extensions::unicode::keywords::{ + CalendarAlgorithm, IslamicCalendarAlgorithm, +}; use icu_locale_core::subtags::language; use icu_locale_core::Locale; use icu_provider::prelude::*; use core::fmt; +define_preferences!( + /// The prefs for datetime formatting. + [Copy] + AnyCalendarPreferences, + { + /// The user's preferred calendar system. + calendar_algorithm: CalendarAlgorithm + } +); + /// This is a calendar that encompasses all formattable calendars supported by this crate /// /// This allows for the construction of [`Date`] objects that have their calendar known at runtime. @@ -46,7 +60,7 @@ use core::fmt; /// /// let locale = locale!("en-u-ca-japanese"); // English with the Japanese calendar /// -/// let calendar = AnyCalendar::new_for_locale(&locale.into()); +/// let calendar = AnyCalendar::new_for_locale(locale.into()); /// let calendar = Rc::new(calendar); // Avoid cloning it each time /// // If everything is a local reference, you may use icu::calendar::Ref instead. /// @@ -748,13 +762,13 @@ impl AnyCalendar { /// /// [📚 Help choosing a constructor](icu_provider::constructors) #[cfg(feature = "compiled_data")] - pub fn new_for_locale(locale: &DataLocale) -> Self { - let kind = AnyCalendarKind::from_data_locale_with_fallback(locale); + pub fn new_for_locale(prefs: AnyCalendarPreferences) -> Self { + let kind = AnyCalendarKind::from_prefs_with_fallback(prefs); Self::new(kind) } icu_provider::gen_any_buffer_data_constructors!( - (locale) -> error: DataError, + (prefs: AnyCalendarPreferences) -> error: DataError, functions: [ new_for_locale: skip, try_new_for_locale_with_any_provider, @@ -767,7 +781,7 @@ impl AnyCalendar { #[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::new_for_locale)] pub fn try_new_for_locale_unstable

( provider: &P, - locale: &DataLocale, + prefs: AnyCalendarPreferences, ) -> Result where P: DataProvider @@ -778,7 +792,7 @@ impl AnyCalendar { + DataProvider + ?Sized, { - let kind = AnyCalendarKind::from_data_locale_with_fallback(locale); + let kind = AnyCalendarKind::from_prefs_with_fallback(prefs); Self::try_new_unstable(provider, kind) } @@ -1028,6 +1042,40 @@ impl AnyCalendarKind { } } + fn get_for_preferences_calendar(pcal: CalendarAlgorithm) -> Option { + match pcal { + CalendarAlgorithm::Buddhist => Some(Self::Buddhist), + CalendarAlgorithm::Chinese => Some(Self::Chinese), + CalendarAlgorithm::Coptic => Some(Self::Coptic), + CalendarAlgorithm::Dangi => Some(Self::Dangi), + CalendarAlgorithm::Ethioaa => Some(Self::EthiopianAmeteAlem), + CalendarAlgorithm::Ethiopic => Some(Self::Ethiopian), + CalendarAlgorithm::Gregory => Some(Self::Gregorian), + CalendarAlgorithm::Hebrew => Some(Self::Hebrew), + CalendarAlgorithm::Indian => Some(Self::Indian), + CalendarAlgorithm::Islamic(None) => Some(Self::IslamicObservational), + CalendarAlgorithm::Islamic(Some(islamic)) => match islamic { + IslamicCalendarAlgorithm::Umalqura => Some(Self::IslamicUmmAlQura), + IslamicCalendarAlgorithm::Tbla => Some(Self::IslamicTabular), + IslamicCalendarAlgorithm::Civil => Some(Self::IslamicCivil), + // Rgsa is not supported + IslamicCalendarAlgorithm::Rgsa => None, + _ => { + debug_assert!(false, "unknown calendar algorithm {pcal:?}"); + None + } + }, + CalendarAlgorithm::Iso8601 => Some(Self::Iso), + CalendarAlgorithm::Japanese => Some(Self::Japanese), + CalendarAlgorithm::Persian => Some(Self::Persian), + CalendarAlgorithm::Roc => Some(Self::Roc), + _ => { + debug_assert!(false, "unknown calendar algorithm {pcal:?}"); + None + } + } + } + fn debug_name(self) -> &'static str { match self { AnyCalendarKind::Buddhist => Buddhist.debug_name(), @@ -1062,21 +1110,22 @@ impl AnyCalendarKind { .and_then(Self::get_for_bcp47_value) } - /// Extract the calendar component from a [`DataLocale`] + /// Extract the calendar component from a [`AnyCalendarPreferences`] /// /// Returns `None` if the calendar is not specified or unknown. - fn get_for_data_locale(l: &DataLocale) -> Option { - l.get_unicode_ext(&key!("ca")) - .and_then(|v| Self::get_for_bcp47_value(&v)) + fn get_for_prefs(prefs: AnyCalendarPreferences) -> Option { + prefs + .calendar_algorithm + .and_then(Self::get_for_preferences_calendar) } // Do not make public, this will eventually need fallback // data from the provider - fn from_data_locale_with_fallback(l: &DataLocale) -> Self { - if let Some(kind) = Self::get_for_data_locale(l) { + fn from_prefs_with_fallback(prefs: AnyCalendarPreferences) -> Self { + if let Some(kind) = Self::get_for_prefs(prefs) { kind } else { - let lang = l.language; + let lang = prefs.locale_prefs.language; if lang == language!("th") { Self::Buddhist } else if lang == language!("sa") { diff --git a/components/calendar/src/lib.rs b/components/calendar/src/lib.rs index a18840f9004..dc57ea88896 100644 --- a/components/calendar/src/lib.rs +++ b/components/calendar/src/lib.rs @@ -200,7 +200,7 @@ pub mod week { #[cfg(feature = "ixdtf")] pub use crate::ixdtf::ParseError; #[doc(no_inline)] -pub use any_calendar::{AnyCalendar, AnyCalendarKind}; +pub use any_calendar::{AnyCalendar, AnyCalendarKind, AnyCalendarPreferences}; pub use calendar::Calendar; pub use date::{AsCalendar, Date, Ref}; pub use datetime::DateTime; diff --git a/components/datetime/README.md b/components/datetime/README.md index 5d13c0b8288..e4816cdc645 100644 --- a/components/datetime/README.md +++ b/components/datetime/README.md @@ -60,7 +60,7 @@ let field_set = fieldsets::YMDT::medium().hm(); // Create a formatter for Argentinian Spanish: let locale = locale!("es-AR"); -let dtf = DateTimeFormatter::try_new(&locale.into(), field_set).unwrap(); +let dtf = DateTimeFormatter::try_new(locale.into(), field_set).unwrap(); // Format something: let datetime = DateTime::try_new_iso(2025, 1, 15, 16, 9, 35).unwrap(); diff --git a/components/datetime/benches/datetime.rs b/components/datetime/benches/datetime.rs index 8741f35f620..dc080db339b 100644 --- a/components/datetime/benches/datetime.rs +++ b/components/datetime/benches/datetime.rs @@ -52,7 +52,7 @@ fn datetime_benches(c: &mut Criterion) { let dtf = { FixedCalendarDateTimeFormatter::::try_new( - &locale.into(), + locale.into(), skeleton, ) .expect("Failed to create FixedCalendarDateTimeFormatter.") diff --git a/components/datetime/examples/work_log.rs b/components/datetime/examples/work_log.rs index 9a8f7ff6672..5f8a1564495 100644 --- a/components/datetime/examples/work_log.rs +++ b/components/datetime/examples/work_log.rs @@ -27,7 +27,7 @@ const DATES_ISO: &[(i32, u8, u8, u8, u8, u8)] = &[ ]; fn main() { - let dtf = FixedCalendarDateTimeFormatter::try_new(&locale!("en").into(), YMDT::medium()) + let dtf = FixedCalendarDateTimeFormatter::try_new(locale!("en").into(), YMDT::medium()) .expect("Failed to create FixedCalendarDateTimeFormatter instance."); println!("\n====== Work Log (en) example ============"); diff --git a/components/datetime/src/combo.rs b/components/datetime/src/combo.rs index 98dff18245c..843bcbc94f5 100644 --- a/components/datetime/src/combo.rs +++ b/components/datetime/src/combo.rs @@ -34,7 +34,7 @@ use crate::{provider::neo::*, scaffold::*}; /// /// // Note: Combo type can be elided, but it is shown here for demonstration /// let formatter = DateTimeFormatter::>::try_new( -/// &locale!("en-US").into(), +/// locale!("en-US").into(), /// ET::short().hm().zone_l(), /// ) /// .unwrap(); @@ -62,7 +62,7 @@ use crate::{provider::neo::*, scaffold::*}; /// /// // Note: Combo type can be elided, but it is shown here for demonstration /// let formatter = FixedCalendarDateTimeFormatter::<_, Combo>::try_new( -/// &locale!("en-US").into(), +/// locale!("en-US").into(), /// ET::short().hm().zone_l(), /// ) /// .unwrap(); @@ -91,7 +91,7 @@ use crate::{provider::neo::*, scaffold::*}; /// /// // Note: Combo type can be elided, but it is shown here for demonstration /// let formatter = DateTimeFormatter::>::try_new( -/// &locale!("en-US").into(), +/// locale!("en-US").into(), /// DateFieldSet::YMD(YMD::long()).zone_v(), /// ) /// .unwrap(); diff --git a/components/datetime/src/dynamic.rs b/components/datetime/src/dynamic.rs index 64e9637b9a4..b423d601c40 100644 --- a/components/datetime/src/dynamic.rs +++ b/components/datetime/src/dynamic.rs @@ -45,11 +45,10 @@ //! } //! } //! -//! let locale = locale!("en-US").into(); //! let datetime = DateTime::try_new_iso(2025, 1, 15, 16, 0, 0).unwrap(); //! //! let results = [true, false].map(get_field_set).map(|field_set| { -//! DateTimeFormatter::try_new(&locale, field_set).unwrap() +//! DateTimeFormatter::try_new(locale!("en-US").into(), field_set).unwrap() //! }).map(|formatter| { //! formatter.convert_and_format(&datetime).try_write_to_string().unwrap().into_owned() //! }); diff --git a/components/datetime/src/external_loaders.rs b/components/datetime/src/external_loaders.rs index d6e213e737d..044c85b48b2 100644 --- a/components/datetime/src/external_loaders.rs +++ b/components/datetime/src/external_loaders.rs @@ -4,9 +4,9 @@ //! Internal traits and structs for loading data from other crates. -use icu_calendar::AnyCalendar; +use icu_calendar::{AnyCalendar, AnyCalendarPreferences}; use icu_decimal::options::FixedDecimalFormatterOptions; -use icu_decimal::FixedDecimalFormatter; +use icu_decimal::{FixedDecimalFormatter, FixedDecimalFormatterPreferences}; use icu_provider::prelude::*; /// Trait for loading a FixedDecimalFormatter. @@ -15,7 +15,7 @@ use icu_provider::prelude::*; pub(crate) trait FixedDecimalFormatterLoader { fn load( &self, - locale: &DataLocale, + prefs: FixedDecimalFormatterPreferences, options: FixedDecimalFormatterOptions, ) -> Result; } @@ -24,7 +24,7 @@ pub(crate) trait FixedDecimalFormatterLoader { /// /// Implemented on the provider-specific loader types in this module. pub(crate) trait AnyCalendarLoader { - fn load(&self, locale: &DataLocale) -> Result; + fn load(&self, prefs: AnyCalendarPreferences) -> Result; } /// Loader for types from other crates using compiled data. @@ -36,19 +36,18 @@ impl FixedDecimalFormatterLoader for ExternalLoaderCompiledData { #[inline] fn load( &self, - locale: &DataLocale, + prefs: FixedDecimalFormatterPreferences, options: FixedDecimalFormatterOptions, ) -> Result { - let temp_loc = locale.clone().into_locale(); - FixedDecimalFormatter::try_new(temp_loc.into(), options) + FixedDecimalFormatter::try_new(prefs, options) } } #[cfg(feature = "compiled_data")] impl AnyCalendarLoader for ExternalLoaderCompiledData { #[inline] - fn load(&self, locale: &DataLocale) -> Result { - Ok(AnyCalendar::new_for_locale(locale)) + fn load(&self, prefs: AnyCalendarPreferences) -> Result { + Ok(AnyCalendar::new_for_locale(prefs)) } } @@ -62,11 +61,10 @@ where #[inline] fn load( &self, - locale: &DataLocale, + prefs: FixedDecimalFormatterPreferences, options: FixedDecimalFormatterOptions, ) -> Result { - let temp_loc = locale.clone().into_locale(); - FixedDecimalFormatter::try_new_with_any_provider(self.0, temp_loc.into(), options) + FixedDecimalFormatter::try_new_with_any_provider(self.0, prefs, options) } } @@ -75,8 +73,8 @@ where P: ?Sized + AnyProvider, { #[inline] - fn load(&self, locale: &DataLocale) -> Result { - AnyCalendar::try_new_for_locale_with_any_provider(self.0, locale) + fn load(&self, prefs: AnyCalendarPreferences) -> Result { + AnyCalendar::try_new_for_locale_with_any_provider(self.0, prefs) } } @@ -92,11 +90,10 @@ where #[inline] fn load( &self, - locale: &DataLocale, + prefs: FixedDecimalFormatterPreferences, options: FixedDecimalFormatterOptions, ) -> Result { - let temp_loc = locale.clone().into_locale(); - FixedDecimalFormatter::try_new_with_buffer_provider(self.0, temp_loc.into(), options) + FixedDecimalFormatter::try_new_with_buffer_provider(self.0, prefs, options) } } @@ -106,8 +103,8 @@ where P: ?Sized + BufferProvider, { #[inline] - fn load(&self, locale: &DataLocale) -> Result { - AnyCalendar::try_new_for_locale_with_buffer_provider(self.0, locale) + fn load(&self, prefs: AnyCalendarPreferences) -> Result { + AnyCalendar::try_new_for_locale_with_buffer_provider(self.0, prefs) } } @@ -123,11 +120,10 @@ where #[inline] fn load( &self, - locale: &DataLocale, + prefs: FixedDecimalFormatterPreferences, options: FixedDecimalFormatterOptions, ) -> Result { - let temp_loc = locale.clone().into_locale(); - FixedDecimalFormatter::try_new_unstable(self.0, temp_loc.into(), options) + FixedDecimalFormatter::try_new_unstable(self.0, prefs, options) } } @@ -142,7 +138,7 @@ where + ?Sized, { #[inline] - fn load(&self, locale: &DataLocale) -> Result { - AnyCalendar::try_new_for_locale_unstable(self.0, locale) + fn load(&self, prefs: AnyCalendarPreferences) -> Result { + AnyCalendar::try_new_for_locale_unstable(self.0, prefs) } } diff --git a/components/datetime/src/fieldsets.rs b/components/datetime/src/fieldsets.rs index 2c45e4dd310..16ba40c0865 100644 --- a/components/datetime/src/fieldsets.rs +++ b/components/datetime/src/fieldsets.rs @@ -373,7 +373,7 @@ macro_rules! impl_date_or_calendar_period_marker { /// use icu::locale::locale; /// use writeable::assert_try_writeable_eq; #[doc = concat!("let fmt = DateTimeFormatter::<", stringify!($type), ">::try_new(")] - /// &locale!("en").into(), + /// locale!("en").into(), #[doc = concat!(" ", length_option_helper!($type, $sample_length), ",")] /// ) /// .unwrap(); @@ -396,7 +396,7 @@ macro_rules! impl_date_or_calendar_period_marker { /// use writeable::assert_try_writeable_eq; /// #[doc = concat!("let fmt = FixedCalendarDateTimeFormatter::::try_new(")] - /// &locale!("en").into(), + /// locale!("en").into(), #[doc = concat!(" ", length_option_helper!($type, $sample_length), ",")] /// ) /// .unwrap(); @@ -519,7 +519,7 @@ macro_rules! impl_date_marker { /// use writeable::assert_try_writeable_eq; /// #[doc = concat!("let fmt = DateTimeFormatter::try_new(")] - /// &locale!("en").into(), + /// locale!("en").into(), #[doc = concat!(" ", length_option_helper!($type_time, $sample_length), ",")] /// ) /// .unwrap(); @@ -542,7 +542,7 @@ macro_rules! impl_date_marker { /// use writeable::assert_try_writeable_eq; /// #[doc = concat!("let fmt = FixedCalendarDateTimeFormatter::try_new(")] - /// &locale!("en").into(), + /// locale!("en").into(), #[doc = concat!(" ", length_option_helper!($type_time, $sample_length), ",")] /// ) /// .unwrap(); @@ -705,7 +705,7 @@ macro_rules! impl_time_marker { /// use writeable::assert_try_writeable_eq; /// #[doc = concat!("let fmt = TimeFormatter::try_new(")] - /// &locale!("en").into(), + /// locale!("en").into(), #[doc = concat!(" ", length_option_helper!($type, $sample_length), ",")] /// ) /// .unwrap(); @@ -822,7 +822,7 @@ macro_rules! impl_zone_marker { /// use writeable::assert_try_writeable_eq; /// #[doc = concat!("let fmt = TimeFormatter::try_new(")] - /// &locale!("en").into(), + /// locale!("en").into(), #[doc = concat!(" ", length_option_helper!($type, $sample_length), ",")] /// ) /// .unwrap(); @@ -914,7 +914,7 @@ macro_rules! impl_zoneddatetime_marker { /// use writeable::assert_try_writeable_eq; /// #[doc = concat!("let fmt = DateTimeFormatter::try_new(")] - /// &locale!("en-GB").into(), + /// locale!("en-GB").into(), #[doc = concat!(" ", length_option_helper!($type, $sample_length), ",")] /// ) /// .unwrap(); @@ -939,7 +939,7 @@ macro_rules! impl_zoneddatetime_marker { /// use writeable::assert_try_writeable_eq; /// #[doc = concat!("let fmt = FixedCalendarDateTimeFormatter::::try_new(")] - /// &locale!("en-GB").into(), + /// locale!("en-GB").into(), #[doc = concat!(" ", length_option_helper!($type, $sample_length), ",")] /// ) /// .unwrap(); @@ -1111,7 +1111,7 @@ impl_time_marker!( /// // but we can set overrides. /// /// let formatter = TimeFormatter::try_new( - /// &locale!("en-US-u-hc-h12").into(), + /// locale!("en-US-u-hc-h12").into(), /// T::short().hm(), /// ) /// .unwrap(); @@ -1121,7 +1121,7 @@ impl_time_marker!( /// ); /// /// let formatter = TimeFormatter::try_new( - /// &locale!("en-US-u-hc-h23").into(), + /// locale!("en-US-u-hc-h23").into(), /// T::short().hm(), /// ) /// .unwrap(); @@ -1131,7 +1131,7 @@ impl_time_marker!( /// ); /// /// let formatter = TimeFormatter::try_new( - /// &locale!("fr-FR-u-hc-h12").into(), + /// locale!("fr-FR-u-hc-h12").into(), /// T::short().hm(), /// ) /// .unwrap(); @@ -1141,7 +1141,7 @@ impl_time_marker!( /// ); /// /// let formatter = TimeFormatter::try_new( - /// &locale!("fr-FR-u-hc-h23").into(), + /// locale!("fr-FR-u-hc-h23").into(), /// T::short().hm(), /// ) /// .unwrap(); @@ -1161,7 +1161,7 @@ impl_time_marker!( /// use writeable::assert_try_writeable_eq; /// /// let formatter = TimeFormatter::try_new( - /// &locale!("und-u-hc-h11").into(), + /// locale!("und-u-hc-h11").into(), /// T::short().hm(), /// ) /// .unwrap(); @@ -1172,7 +1172,7 @@ impl_time_marker!( /// ); /// /// let formatter = TimeFormatter::try_new( - /// &locale!("und-u-hc-h24").into(), + /// locale!("und-u-hc-h24").into(), /// T::short().hm(), /// ) /// .unwrap(); @@ -1214,7 +1214,7 @@ impl_zone_marker!( /// .with_zone_variant(ZoneVariant::Standard); /// /// let fmt = FixedCalendarDateTimeFormatter::::try_new( - /// &locale!("en").into(), + /// locale!("en").into(), /// Z::short(), /// ) /// .unwrap(); @@ -1225,7 +1225,7 @@ impl_zone_marker!( /// ); /// /// let fmt = FixedCalendarDateTimeFormatter::::try_new( - /// &locale!("en").into(), + /// locale!("en").into(), /// Z::long(), /// ) /// .unwrap(); @@ -1254,7 +1254,7 @@ impl_zone_marker!( /// let time_zone_at_time = time_zone_basic.at_time((datetime.date.to_iso(), datetime.time)); /// /// let formatter = FixedCalendarDateTimeFormatter::try_new( - /// &locale!("en-US").into(), + /// locale!("en-US").into(), /// Z::medium(), /// ) /// .unwrap(); @@ -1299,7 +1299,7 @@ impl_zone_marker!( /// let time_zone_at_time = time_zone_basic.at_time((datetime.date.to_iso(), datetime.time)); /// /// let formatter = FixedCalendarDateTimeFormatter::try_new( - /// &locale!("en-US").into(), + /// locale!("en-US").into(), /// Combo::::medium(), /// ) /// .unwrap(); @@ -1346,7 +1346,7 @@ impl_zone_marker!( /// let time_zone_full = time_zone_at_time.with_zone_variant(ZoneVariant::Standard); /// /// let formatter = TimeFormatter::try_new( - /// &locale!("en-US").into(), + /// locale!("en-US").into(), /// O::medium(), /// ) /// .unwrap(); @@ -1401,7 +1401,7 @@ impl_zone_marker!( /// .at_time((Date::try_new_iso(2022, 1, 29).unwrap(), Time::midnight())); /// /// let fmt = FixedCalendarDateTimeFormatter::::try_new( - /// &locale!("en").into(), + /// locale!("en").into(), /// V::short(), /// ) /// .unwrap(); @@ -1426,7 +1426,7 @@ impl_zone_marker!( /// /// // Set up the formatter /// let mut tzf = TimeFormatter::try_new( - /// &locale!("en").into(), + /// locale!("en").into(), /// V::short(), /// ) /// .unwrap(); @@ -1477,7 +1477,7 @@ impl_zone_marker!( /// let time_zone_basic = TimeZoneBcp47Id(tinystr!(8, "uschi")).without_offset(); /// /// let formatter = TimeFormatter::try_new( - /// &locale!("en-US").into(), + /// locale!("en-US").into(), /// V::medium(), /// ) /// .unwrap(); @@ -1519,7 +1519,7 @@ impl_zone_marker!( /// let time_zone_basic = TimeZoneBcp47Id(tinystr!(8, "uschi")).with_offset("-06".parse().ok());1 /// /// let formatter = FixedCalendarDateTimeFormatter::try_new( - /// &locale!("en-US").into(), + /// locale!("en-US").into(), /// Vs::medium(), /// ) /// .unwrap(); @@ -1560,7 +1560,7 @@ impl_zone_marker!( /// let utc_offset = UtcOffset::try_from_str("-06").unwrap(); /// /// let formatter = FixedCalendarDateTimeFormatter::try_new( - /// &locale!("en-US").into(), + /// locale!("en-US").into(), /// L::medium(), /// ) /// .unwrap(); diff --git a/components/datetime/src/lib.rs b/components/datetime/src/lib.rs index ba27e83cbcd..ba14bec7252 100644 --- a/components/datetime/src/lib.rs +++ b/components/datetime/src/lib.rs @@ -60,7 +60,7 @@ //! //! // Create a formatter for Argentinian Spanish: //! let locale = locale!("es-AR"); -//! let dtf = DateTimeFormatter::try_new(&locale.into(), field_set).unwrap(); +//! let dtf = DateTimeFormatter::try_new(locale.into(), field_set).unwrap(); //! //! // Format something: //! let datetime = DateTime::try_new_iso(2025, 1, 15, 16, 9, 35).unwrap(); @@ -108,6 +108,7 @@ pub(crate) mod size_test_macro; pub use error::{DateTimeFormatterLoadError, DateTimeWriteError, MismatchedCalendarError}; pub use neo::DateTimeFormatter; +pub use neo::DateTimeFormatterPreferences; pub use neo::FixedCalendarDateTimeFormatter; pub use neo::FormattedDateTime; pub use neo::TimeFormatter; diff --git a/components/datetime/src/neo.rs b/components/datetime/src/neo.rs index 56c079b496c..6fdf826e40e 100644 --- a/components/datetime/src/neo.rs +++ b/components/datetime/src/neo.rs @@ -22,18 +22,46 @@ use crate::MismatchedCalendarError; use core::fmt; use core::marker::PhantomData; use icu_calendar::any_calendar::IntoAnyCalendar; -use icu_calendar::AnyCalendar; -use icu_locale_core::preferences::extensions::unicode::keywords::HourCycle; +use icu_calendar::{AnyCalendar, AnyCalendarPreferences}; +use icu_decimal::FixedDecimalFormatterPreferences; +use icu_locale_core::preferences::extensions::unicode::keywords::{ + CalendarAlgorithm, HourCycle, NumberingSystem, +}; +use icu_locale_core::preferences::{define_preferences, prefs_convert}; use icu_provider::prelude::*; use writeable::TryWriteable; +define_preferences!( + /// The prefs for datetime formatting. + [Copy] + DateTimeFormatterPreferences, + { + /// The user's preferred numbering system + numbering_system: NumberingSystem, + /// The user's preferred hour cycle + hour_cycle: HourCycle, + /// The user's preferred calendar system + calendar_algorithm: CalendarAlgorithm + } +); + +prefs_convert!( + DateTimeFormatterPreferences, + FixedDecimalFormatterPreferences, + { numbering_system } +); + +prefs_convert!(DateTimeFormatterPreferences, AnyCalendarPreferences, { + calendar_algorithm +}); + /// Helper macro for generating any/buffer constructors in this file. macro_rules! gen_any_buffer_constructors_with_external_loader { (@runtime_fset, $fset:ident, $compiled_fn:ident, $any_fn:ident, $buffer_fn:ident, $internal_fn:ident) => { #[doc = icu_provider::gen_any_buffer_unstable_docs!(ANY, Self::$compiled_fn)] pub fn $any_fn

( provider: &P, - locale: &DataLocale, + prefs: DateTimeFormatterPreferences, field_set: $fset, ) -> Result where @@ -42,7 +70,7 @@ macro_rules! gen_any_buffer_constructors_with_external_loader { Self::$internal_fn( &provider.as_downcasting(), &ExternalLoaderAny(provider), - locale, + prefs, field_set.get_field(), ) } @@ -50,7 +78,7 @@ macro_rules! gen_any_buffer_constructors_with_external_loader { #[cfg(feature = "serde")] pub fn $buffer_fn

( provider: &P, - locale: &DataLocale, + prefs: DateTimeFormatterPreferences, field_set: $fset, ) -> Result where @@ -59,7 +87,7 @@ macro_rules! gen_any_buffer_constructors_with_external_loader { Self::$internal_fn( &provider.as_deserializing(), &ExternalLoaderBuffer(provider), - locale, + prefs, field_set.get_field(), ) } @@ -68,7 +96,7 @@ macro_rules! gen_any_buffer_constructors_with_external_loader { #[doc = icu_provider::gen_any_buffer_unstable_docs!(ANY, Self::$compiled_fn)] pub fn $any_fn

( provider: &P, - locale: &DataLocale, + prefs: DateTimeFormatterPreferences, field_set: $fset, ) -> Result where @@ -77,7 +105,7 @@ macro_rules! gen_any_buffer_constructors_with_external_loader { Self::$internal_fn( &provider.as_downcasting(), &ExternalLoaderAny(provider), - locale, + prefs, field_set.get_field(), ) } @@ -85,7 +113,7 @@ macro_rules! gen_any_buffer_constructors_with_external_loader { #[cfg(feature = "serde")] pub fn $buffer_fn

( provider: &P, - locale: &DataLocale, + prefs: DateTimeFormatterPreferences, field_set: $fset, ) -> Result where @@ -94,44 +122,13 @@ macro_rules! gen_any_buffer_constructors_with_external_loader { Self::$internal_fn( &provider.as_deserializing(), &ExternalLoaderBuffer(provider), - locale, + prefs, field_set.get_field(), ) } }; } -// impl RawOptions { -// pub(crate) fn from_field_set_and_locale(field_set: &FSet, locale: &DataLocale) -> Self -// where -// FSet: DateTimeMarkers, -// FSet: GetField, -// FSet: GetField, -// FSet: GetField, -// FSet: GetField, -// { -// // TODO: Return an error if there are more options than field set -// let hour_cycle = locale -// .get_unicode_ext(&icu_locale_core::extensions::unicode::key!("hc")) -// .as_ref() -// .and_then(HourCycle::from_locale_value); -// Self { -// length: match GetField::::get_field(field_set).into_option() { -// Some(length) => length, -// None => { -// debug_assert!(false, "unreachable"); -// NeoSkeletonLength::Medium -// } -// }, -// alignment: GetField::::get_field(field_set).into_option(), -// year_style: GetField::::get_field(field_set).into_option(), -// time_precision: GetField::::get_field(field_set) -// .into_option(), -// hour_cycle, -// } -// } -// } - size_test!(FixedCalendarDateTimeFormatter, typed_neo_year_month_day_formatter_size, 344); /// [`FixedCalendarDateTimeFormatter`] is a formatter capable of formatting dates and/or times from @@ -175,7 +172,7 @@ where /// use writeable::assert_try_writeable_eq; /// /// let formatter = FixedCalendarDateTimeFormatter::try_new( - /// &locale!("es-MX").into(), + /// locale!("es-MX").into(), /// YMD::long(), /// ) /// .unwrap(); @@ -186,14 +183,17 @@ where /// ); /// ``` #[cfg(feature = "compiled_data")] - pub fn try_new(locale: &DataLocale, field_set: FSet) -> Result + pub fn try_new( + prefs: DateTimeFormatterPreferences, + field_set: FSet, + ) -> Result where crate::provider::Baked: AllFixedCalendarFormattingDataMarkers, { Self::try_new_internal( &crate::provider::Baked, &ExternalLoaderCompiledData, - locale, + prefs, field_set.get_field(), ) } @@ -210,7 +210,7 @@ where #[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::try_new)] pub fn try_new_unstable

( provider: &P, - locale: &DataLocale, + prefs: DateTimeFormatterPreferences, field_set: FSet, ) -> Result where @@ -221,7 +221,7 @@ where Self::try_new_internal( provider, &ExternalLoaderUnstable(provider), - locale, + prefs, field_set.get_field(), ) } @@ -236,30 +236,19 @@ where fn try_new_internal( provider: &P, loader: &L, - locale: &DataLocale, + prefs: DateTimeFormatterPreferences, field_set: CompositeFieldSet, ) -> Result where P: ?Sized + AllFixedCalendarFormattingDataMarkers, L: FixedDecimalFormatterLoader, { - // TODO: Fix this when we have DateTimePreferences - let prefs = RawPreferences { - hour_cycle: locale - .get_unicode_ext(&icu_locale_core::extensions::unicode::key!("hc")) - .as_ref() - .and_then(|v| HourCycle::try_from(v).ok()) - .map(crate::fields::Hour::from_hour_cycle), - }; - // END TODO - let selection = DateTimeZonePatternSelectionData::try_new_with_skeleton( &>::DateSkeletonPatternsV1Marker::bind(provider), &::TimeSkeletonPatternsV1Marker::bind(provider), &FSet::GluePatternV1Marker::bind(provider), - locale, - field_set, prefs, + field_set, ) .map_err(DateTimeFormatterLoadError::Data)?; let mut names = RawDateTimeNames::new_without_number_formatting(); @@ -277,7 +266,7 @@ where &::SpecificShortV1Marker::bind(provider), &::MetazonePeriodV1Marker::bind(provider), loader, // fixed decimal formatter - locale, + prefs, selection.pattern_items_for_data_loading(), ) .map_err(DateTimeFormatterLoadError::Names)?; @@ -310,7 +299,7 @@ where /// /// let formatter = /// FixedCalendarDateTimeFormatter::::try_new( - /// &locale!("es-MX").into(), + /// locale!("es-MX").into(), /// YMD::long(), /// ) /// .unwrap(); @@ -330,7 +319,7 @@ where /// /// let formatter = /// FixedCalendarDateTimeFormatter::::try_new( - /// &locale!("es-MX").into(), + /// locale!("es-MX").into(), /// YMD::long(), /// ) /// .unwrap(); @@ -405,10 +394,8 @@ where /// use std::str::FromStr; /// use writeable::assert_try_writeable_eq; /// - /// let locale = locale!("en-u-ca-hebrew"); - /// /// let formatter = - /// DateTimeFormatter::try_new(&locale.into(), YMD::medium()).unwrap(); + /// DateTimeFormatter::try_new(locale!("en-u-ca-hebrew").into(), YMD::medium()).unwrap(); /// /// let datetime = DateTime::try_new_iso(2024, 5, 8, 0, 0, 0).unwrap(); /// @@ -421,14 +408,17 @@ where /// [`AnyCalendarKind`]: icu_calendar::AnyCalendarKind #[inline(never)] #[cfg(feature = "compiled_data")] - pub fn try_new(locale: &DataLocale, field_set: FSet) -> Result + pub fn try_new( + prefs: DateTimeFormatterPreferences, + field_set: FSet, + ) -> Result where crate::provider::Baked: AllAnyCalendarFormattingDataMarkers, { Self::try_new_internal( &crate::provider::Baked, &ExternalLoaderCompiledData, - locale, + prefs, field_set.get_field(), ) } @@ -445,7 +435,7 @@ where #[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::try_new)] pub fn try_new_unstable

( provider: &P, - locale: &DataLocale, + prefs: DateTimeFormatterPreferences, field_set: FSet, ) -> Result where @@ -454,7 +444,7 @@ where Self::try_new_internal( provider, &ExternalLoaderUnstable(provider), - locale, + prefs, field_set.get_field(), ) } @@ -469,33 +459,22 @@ where fn try_new_internal( provider: &P, loader: &L, - locale: &DataLocale, + prefs: DateTimeFormatterPreferences, field_set: CompositeFieldSet, ) -> Result where P: ?Sized + AllAnyCalendarFormattingDataMarkers, L: FixedDecimalFormatterLoader + AnyCalendarLoader, { - // TODO: Fix this when we have DateTimePreferences - let prefs = RawPreferences { - hour_cycle: locale - .get_unicode_ext(&icu_locale_core::extensions::unicode::key!("hc")) - .as_ref() - .and_then(|v| HourCycle::try_from(v).ok()) - .map(crate::fields::Hour::from_hour_cycle), - }; - // END TODO - - let calendar = - AnyCalendarLoader::load(loader, locale).map_err(DateTimeFormatterLoadError::Data)?; + let calendar = AnyCalendarLoader::load(loader, (&prefs).into()) + .map_err(DateTimeFormatterLoadError::Data)?; let kind = calendar.kind(); let selection = DateTimeZonePatternSelectionData::try_new_with_skeleton( &AnyCalendarProvider::<::Skel, _>::new(provider, kind), &::TimeSkeletonPatternsV1Marker::bind(provider), &FSet::GluePatternV1Marker::bind(provider), - locale, - field_set, prefs, + field_set, ) .map_err(DateTimeFormatterLoadError::Data)?; let mut names = RawDateTimeNames::new_without_number_formatting(); @@ -513,7 +492,7 @@ where &::SpecificShortV1Marker::bind(provider), &::MetazonePeriodV1Marker::bind(provider), loader, // fixed decimal formatter - locale, + prefs, selection.pattern_items_for_data_loading(), ) .map_err(DateTimeFormatterLoadError::Names)?; @@ -548,7 +527,7 @@ where /// use icu::locale::locale; /// /// let formatter = DateTimeFormatter::try_new( - /// &locale!("en-u-ca-hebrew").into(), + /// locale!("en-u-ca-hebrew").into(), /// YMD::long(), /// ) /// .unwrap(); @@ -570,7 +549,7 @@ where /// use icu::locale::locale; /// /// let formatter = DateTimeFormatter::try_new( - /// &locale!("es-MX").into(), + /// locale!("es-MX").into(), /// NeoSkeletonLength::Long.into(), /// ) /// .unwrap(); @@ -612,7 +591,7 @@ where /// use writeable::assert_try_writeable_eq; /// /// let formatter = DateTimeFormatter::try_new( - /// &locale!("en-u-ca-hebrew").into(), + /// locale!("en-u-ca-hebrew").into(), /// YMD::long(), /// ) /// .unwrap(); @@ -634,7 +613,7 @@ where /// use icu::locale::locale; /// /// let formatter = DateTimeFormatter::try_new( - /// &locale!("es-MX").into(), + /// locale!("es-MX").into(), /// NeoSkeletonLength::Long.into(), /// ) /// .unwrap(); @@ -678,7 +657,7 @@ impl FixedCalendarDateTimeFormatter DateTimeFormatter { /// use writeable::assert_try_writeable_eq; /// /// let formatter = DateTimeFormatter::try_new( - /// &locale!("en-u-ca-hebrew").into(), + /// locale!("en-u-ca-hebrew").into(), /// YMD::long(), /// ) /// .unwrap() @@ -742,7 +721,7 @@ impl DateTimeFormatter { /// use icu::locale::locale; /// /// let result = DateTimeFormatter::try_new( - /// &locale!("en-u-ca-buddhist").into(), + /// locale!("en-u-ca-buddhist").into(), /// YMD::long(), /// ) /// .unwrap() @@ -781,7 +760,7 @@ impl DateTimeFormatter { /// use icu::datetime::fieldsets::Y; /// use icu::locale::locale; /// -/// assert!(TimeFormatter::try_new(&locale!("und").into(), Y::medium()).is_err()); +/// assert!(TimeFormatter::try_new(locale!("und").into(), Y::medium()).is_err()); /// ``` /// /// Furthermore, it is a compile error in the format function: @@ -792,7 +771,7 @@ impl DateTimeFormatter { /// use icu::locale::locale; /// /// let date: icu::calendar::Date = unimplemented!(); -/// let formatter = TimeFormatter::try_new(&locale!("und").into(), Y::medium()).unwrap(); +/// let formatter = TimeFormatter::try_new(locale!("und").into(), Y::medium()).unwrap(); /// /// // error[E0271]: type mismatch resolving `::Calendar == ()` /// formatter.format(&date); diff --git a/components/datetime/src/options/mod.rs b/components/datetime/src/options/mod.rs index 6fe5c1f11ec..e4408fba033 100644 --- a/components/datetime/src/options/mod.rs +++ b/components/datetime/src/options/mod.rs @@ -27,21 +27,21 @@ use crate::neo_serde::TimePrecisionSerde; /// /// let short_formatter = /// FixedCalendarDateTimeFormatter::try_new( -/// &locale!("en-US").into(), +/// locale!("en-US").into(), /// YMD::short(), /// ) /// .unwrap(); /// /// let medium_formatter = /// FixedCalendarDateTimeFormatter::try_new( -/// &locale!("en-US").into(), +/// locale!("en-US").into(), /// YMD::medium(), /// ) /// .unwrap(); /// /// let long_formatter = /// FixedCalendarDateTimeFormatter::try_new( -/// &locale!("en-US").into(), +/// locale!("en-US").into(), /// YMD::long(), /// ) /// .unwrap(); @@ -107,14 +107,14 @@ impl IntoOption for NeoSkeletonLength { /// /// let plain_formatter = /// FixedCalendarDateTimeFormatter::::try_new( -/// &locale!("en-US").into(), +/// locale!("en-US").into(), /// YMD::short(), /// ) /// .unwrap(); /// /// let column_formatter = /// FixedCalendarDateTimeFormatter::::try_new( -/// &locale!("en-US").into(), +/// locale!("en-US").into(), /// YMD::short().with_alignment(Alignment::Column), /// ) /// .unwrap(); @@ -180,7 +180,7 @@ impl IntoOption for Alignment { /// use writeable::assert_try_writeable_eq; /// /// let formatter = FixedCalendarDateTimeFormatter::::try_new( -/// &locale!("en-US").into(), +/// locale!("en-US").into(), /// YMD::short().with_year_style(YearStyle::Auto), /// ) /// .unwrap(); @@ -207,7 +207,7 @@ impl IntoOption for Alignment { /// ); /// /// let formatter = FixedCalendarDateTimeFormatter::::try_new( -/// &locale!("en-US").into(), +/// locale!("en-US").into(), /// YMD::short().with_year_style(YearStyle::Full), /// ) /// .unwrap(); @@ -233,7 +233,7 @@ impl IntoOption for Alignment { /// ); /// /// let formatter = FixedCalendarDateTimeFormatter::::try_new( -/// &locale!("en-US").into(), +/// locale!("en-US").into(), /// YMD::short().with_year_style(YearStyle::Always), /// ) /// .unwrap(); @@ -340,7 +340,7 @@ impl IntoOption for YearStyle { /// TimePrecision::SecondExact(FractionalSecondDigits::F0), /// ].map(|time_precision| { /// FixedCalendarDateTimeFormatter::<(), _>::try_new( -/// &locale!("en-US").into(), +/// locale!("en-US").into(), /// T::short().with_time_precision(time_precision), /// ) /// .unwrap() @@ -467,7 +467,7 @@ impl IntoOption for TimePrecision { /// use writeable::assert_try_writeable_eq; /// /// let formatter = FixedCalendarDateTimeFormatter::<(), _>::try_new( -/// &locale!("en-US").into(), +/// locale!("en-US").into(), /// T::short().with_time_precision(TimePrecision::SecondExact(FractionalSecondDigits::F2)), /// ) /// .unwrap(); diff --git a/components/datetime/src/pattern/formatter.rs b/components/datetime/src/pattern/formatter.rs index 61bea4ce456..7e9c06ba155 100644 --- a/components/datetime/src/pattern/formatter.rs +++ b/components/datetime/src/pattern/formatter.rs @@ -78,7 +78,7 @@ where /// /// // Create an instance that can format wide month and era names: /// let mut names: TypedDateTimeNames = - /// TypedDateTimeNames::try_new(&locale!("en-GB").into()).unwrap(); + /// TypedDateTimeNames::try_new(locale!("en-GB").into()).unwrap(); /// names /// .include_month_names(fields::Month::Format, FieldLength::Four) /// .unwrap() @@ -117,7 +117,7 @@ where /// /// // Create an instance that can format abbreviated day periods: /// let mut names: TypedDateTimeNames = - /// TypedDateTimeNames::try_new(&locale!("en-US").into()).unwrap(); + /// TypedDateTimeNames::try_new(locale!("en-US").into()).unwrap(); /// names /// .include_day_period_names(FieldLength::Three) /// .unwrap(); @@ -173,7 +173,7 @@ where /// /// let mut names = /// TypedDateTimeNames::::try_new( - /// &locale!("en-GB").into(), + /// locale!("en-GB").into(), /// ) /// .unwrap(); /// @@ -244,8 +244,7 @@ mod tests { #[test] fn test_basic_pattern_formatting() { let locale = locale!("en").into(); - let mut names: TypedDateTimeNames = - TypedDateTimeNames::try_new(&locale).unwrap(); + let mut names: TypedDateTimeNames = TypedDateTimeNames::try_new(locale).unwrap(); names .load_month_names( &crate::provider::Baked, @@ -319,7 +318,7 @@ mod tests { expected, } = cas; let mut names: TypedDateTimeNames = - TypedDateTimeNames::try_new(&locale).unwrap(); + TypedDateTimeNames::try_new(locale).unwrap(); names .load_year_names(&crate::provider::Baked, field_length) .unwrap(); @@ -390,7 +389,7 @@ mod tests { expected, } = cas; let mut names: TypedDateTimeNames = - TypedDateTimeNames::try_new(&locale).unwrap(); + TypedDateTimeNames::try_new(locale).unwrap(); names .load_month_names(&crate::provider::Baked, field_symbol, field_length) .unwrap(); @@ -508,7 +507,7 @@ mod tests { expected, } = cas; let mut names: TypedDateTimeNames = - TypedDateTimeNames::try_new(&locale).unwrap(); + TypedDateTimeNames::try_new(locale).unwrap(); names .load_weekday_names(&crate::provider::Baked, field_symbol, field_length) .unwrap(); @@ -590,7 +589,7 @@ mod tests { expected, } = cas; let mut names: TypedDateTimeNames = - TypedDateTimeNames::try_new(&locale).unwrap(); + TypedDateTimeNames::try_new(locale).unwrap(); names .load_day_period_names(&crate::provider::Baked, field_length) .unwrap(); diff --git a/components/datetime/src/pattern/names.rs b/components/datetime/src/pattern/names.rs index 006b831b421..416dd016cd3 100644 --- a/components/datetime/src/pattern/names.rs +++ b/components/datetime/src/pattern/names.rs @@ -7,7 +7,6 @@ use super::{ GetNameForWeekdayError, GetSymbolForCyclicYearError, GetSymbolForEraError, MonthPlaceholderValue, PatternLoadError, }; -use crate::external_loaders::*; use crate::fields::{self, FieldLength, FieldSymbol}; use crate::fieldsets::enums::CompositeDateTimeFieldSet; use crate::input; @@ -16,6 +15,7 @@ use crate::provider::pattern::PatternItem; use crate::provider::time_zones::tz; use crate::scaffold::*; use crate::size_test_macro::size_test; +use crate::{external_loaders::*, DateTimeFormatterPreferences}; use core::fmt; use core::marker::PhantomData; use core::num::NonZeroU8; @@ -41,7 +41,7 @@ where size_test!( TypedDateTimeNames, typed_date_time_names_size, - 344 + 328 ); /// A low-level type that formats datetime patterns with localized names. @@ -77,7 +77,7 @@ size_test!( /// /// // Create an instance that can format abbreviated month, weekday, and day period names: /// let mut names: TypedDateTimeNames = -/// TypedDateTimeNames::try_new(&locale!("uk").into()).unwrap(); +/// TypedDateTimeNames::try_new(locale!("uk").into()).unwrap(); /// names /// .include_month_names(fields::Month::Format, FieldLength::Three) /// .unwrap() @@ -112,7 +112,7 @@ size_test!( /// /// // Create an instance that can format all fields (CompositeFieldSet): /// let mut names: TypedDateTimeNames = -/// TypedDateTimeNames::try_new(&locale!("en").into()).unwrap(); +/// TypedDateTimeNames::try_new(locale!("en").into()).unwrap(); /// /// // Create a pattern from a pattern string: /// let pattern_str = "'It is:' E MMM d y G 'at' h:mm:ssSSS a zzzz"; @@ -161,7 +161,7 @@ size_test!( /// /// // Create an instance that can format abbreviated month, weekday, and day period names: /// let mut names: TypedDateTimeNames = -/// TypedDateTimeNames::try_new(&locale!("en").into()).unwrap(); +/// TypedDateTimeNames::try_new(locale!("en").into()).unwrap(); /// /// // Create a pattern from a pattern string: /// let pattern_str = "'It is:' E MMM d y G 'at' h:mm:ssSSS a zzzz"; @@ -194,7 +194,7 @@ pub struct TypedDateTimeNames< C: CldrCalendar, FSet: DateTimeNamesMarker = CompositeDateTimeFieldSet, > { - locale: DataLocale, + prefs: DateTimeFormatterPreferences, inner: RawDateTimeNames, _calendar: PhantomData, } @@ -285,9 +285,9 @@ impl TypedDateTimeNames { /// /// [📚 Help choosing a constructor](icu_provider::constructors) #[cfg(feature = "compiled_data")] - pub fn try_new(locale: &DataLocale) -> Result { + pub fn try_new(prefs: DateTimeFormatterPreferences) -> Result { let mut names = Self { - locale: locale.clone(), + prefs, inner: RawDateTimeNames::new_without_number_formatting(), _calendar: PhantomData, }; @@ -296,12 +296,15 @@ impl TypedDateTimeNames { } #[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::try_new)] - pub fn try_new_unstable

(provider: &P, locale: &DataLocale) -> Result + pub fn try_new_unstable

( + provider: &P, + prefs: DateTimeFormatterPreferences, + ) -> Result where P: DataProvider + DataProvider + ?Sized, { let mut names = Self { - locale: locale.clone(), + prefs, inner: RawDateTimeNames::new_without_number_formatting(), _calendar: PhantomData, }; @@ -328,7 +331,7 @@ impl TypedDateTimeNames { /// /// // Create an instance that can format only date fields: /// let names: TypedDateTimeNames = - /// TypedDateTimeNames::new_without_number_formatting(&locale!("en").into()); + /// TypedDateTimeNames::new_without_number_formatting(locale!("en").into()); /// /// // Create a pattern from a pattern string: /// let pattern_str = "'It is:' y-MM-dd"; @@ -352,9 +355,9 @@ impl TypedDateTimeNames { /// ] /// ); /// ``` - pub fn new_without_number_formatting(locale: &DataLocale) -> Self { + pub fn new_without_number_formatting(prefs: DateTimeFormatterPreferences) -> Self { Self { - locale: locale.clone(), + prefs, inner: RawDateTimeNames::new_without_number_formatting(), _calendar: PhantomData, } @@ -373,7 +376,7 @@ impl TypedDateTimeNames { { self.inner.load_year_names( &C::YearNamesV1Marker::bind(provider), - &self.locale, + self.prefs, field_length, )?; Ok(self) @@ -393,7 +396,7 @@ impl TypedDateTimeNames { /// use icu::locale::locale; /// /// let mut names = - /// TypedDateTimeNames::::try_new(&locale!("und").into()) + /// TypedDateTimeNames::::try_new(locale!("und").into()) /// .unwrap(); /// /// // First length is successful: @@ -433,7 +436,7 @@ impl TypedDateTimeNames { { self.inner.load_month_names( &C::MonthNamesV1Marker::bind(provider), - &self.locale, + self.prefs, field_symbol, field_length, )?; @@ -454,7 +457,7 @@ impl TypedDateTimeNames { /// use icu::locale::locale; /// /// let mut names = - /// TypedDateTimeNames::::try_new(&locale!("und").into()) + /// TypedDateTimeNames::::try_new(locale!("und").into()) /// .unwrap(); /// let field_symbol = icu::datetime::fields::Month::Format; /// let alt_field_symbol = icu::datetime::fields::Month::StandAlone; @@ -504,7 +507,7 @@ impl TypedDateTimeNames { { let provider = DayPeriodNamesV1Marker::bind(provider); self.inner - .load_day_period_names(&provider, &self.locale, field_length)?; + .load_day_period_names(&provider, self.prefs, field_length)?; Ok(self) } @@ -522,7 +525,7 @@ impl TypedDateTimeNames { /// use icu::locale::locale; /// /// let mut names = - /// TypedDateTimeNames::::try_new(&locale!("und").into()) + /// TypedDateTimeNames::::try_new(locale!("und").into()) /// .unwrap(); /// /// // First length is successful: @@ -562,7 +565,7 @@ impl TypedDateTimeNames { { self.inner.load_weekday_names( &WeekdayNamesV1Marker::bind(provider), - &self.locale, + self.prefs, field_symbol, field_length, )?; @@ -583,7 +586,7 @@ impl TypedDateTimeNames { /// use icu::locale::locale; /// /// let mut names = - /// TypedDateTimeNames::::try_new(&locale!("und").into()) + /// TypedDateTimeNames::::try_new(locale!("und").into()) /// .unwrap(); /// let field_symbol = icu::datetime::fields::Weekday::Format; /// let alt_field_symbol = icu::datetime::fields::Weekday::StandAlone; @@ -629,7 +632,7 @@ impl TypedDateTimeNames { P: DataProvider + ?Sized, { self.inner - .load_time_zone_essentials(&tz::EssentialsV1Marker::bind(provider), &self.locale)?; + .load_time_zone_essentials(&tz::EssentialsV1Marker::bind(provider), self.prefs)?; Ok(self) } @@ -662,7 +665,7 @@ impl TypedDateTimeNames { /// /// let mut names = /// TypedDateTimeNames::::try_new( - /// &locale!("en-GB").into(), + /// locale!("en-GB").into(), /// ) /// .unwrap(); /// @@ -729,7 +732,7 @@ impl TypedDateTimeNames { P: DataProvider + ?Sized, { self.inner - .load_time_zone_location_names(&tz::LocationsV1Marker::bind(provider), &self.locale)?; + .load_time_zone_location_names(&tz::LocationsV1Marker::bind(provider), self.prefs)?; Ok(self) } @@ -760,7 +763,7 @@ impl TypedDateTimeNames { /// /// let mut names = /// TypedDateTimeNames::::try_new( - /// &locale!("en-GB").into(), + /// locale!("en-GB").into(), /// ) /// .unwrap(); /// @@ -795,7 +798,7 @@ impl TypedDateTimeNames { self.inner.load_time_zone_generic_long_names( &tz::MzGenericLongV1Marker::bind(provider), &tz::MzPeriodV1Marker::bind(provider), - &self.locale, + self.prefs, )?; Ok(self) } @@ -832,7 +835,7 @@ impl TypedDateTimeNames { /// /// let mut names = /// TypedDateTimeNames::::try_new( - /// &locale!("en-GB").into(), + /// locale!("en-GB").into(), /// ) /// .unwrap(); /// @@ -871,7 +874,7 @@ impl TypedDateTimeNames { self.inner.load_time_zone_generic_short_names( &tz::MzGenericShortV1Marker::bind(provider), &tz::MzPeriodV1Marker::bind(provider), - &self.locale, + self.prefs, )?; Ok(self) } @@ -908,7 +911,7 @@ impl TypedDateTimeNames { /// /// let mut names = /// TypedDateTimeNames::::try_new( - /// &locale!("en-GB").into(), + /// locale!("en-GB").into(), /// ) /// .unwrap(); /// @@ -947,7 +950,7 @@ impl TypedDateTimeNames { self.inner.load_time_zone_specific_long_names( &tz::MzSpecificLongV1Marker::bind(provider), &tz::MzPeriodV1Marker::bind(provider), - &self.locale, + self.prefs, )?; Ok(self) } @@ -984,7 +987,7 @@ impl TypedDateTimeNames { /// /// let mut names = /// TypedDateTimeNames::::try_new( - /// &locale!("en-GB").into(), + /// locale!("en-GB").into(), /// ) /// .unwrap(); /// @@ -1023,7 +1026,7 @@ impl TypedDateTimeNames { self.inner.load_time_zone_specific_short_names( &tz::MzSpecificShortV1Marker::bind(provider), &tz::MzPeriodV1Marker::bind(provider), - &self.locale, + self.prefs, )?; Ok(self) } @@ -1060,7 +1063,7 @@ impl TypedDateTimeNames { /// /// let mut names = /// TypedDateTimeNames::::try_new( - /// &locale!("en-GB").into(), + /// locale!("en-GB").into(), /// ) /// .unwrap(); /// @@ -1095,7 +1098,7 @@ impl TypedDateTimeNames { P: DataProvider + DataProvider + ?Sized, { self.inner - .load_fixed_decimal_formatter(&ExternalLoaderUnstable(provider), &self.locale)?; + .load_fixed_decimal_formatter(&ExternalLoaderUnstable(provider), self.prefs)?; Ok(self) } @@ -1111,10 +1114,8 @@ impl TypedDateTimeNames { /// use icu::locale::locale; /// use writeable::assert_try_writeable_eq; /// - /// let locale = &locale!("bn").into(); - /// /// let mut names = - /// TypedDateTimeNames::<(), TimeFieldSet>::try_new(&locale).unwrap(); + /// TypedDateTimeNames::<(), TimeFieldSet>::try_new(locale!("bn").into()).unwrap(); /// names.include_fixed_decimal_formatter(); /// /// // Create a pattern for the time, which is all numbers @@ -1132,7 +1133,7 @@ impl TypedDateTimeNames { #[inline] pub fn include_fixed_decimal_formatter(&mut self) -> Result<&mut Self, DataError> { self.inner - .load_fixed_decimal_formatter(&ExternalLoaderCompiledData, &self.locale)?; + .load_fixed_decimal_formatter(&ExternalLoaderCompiledData, self.prefs)?; Ok(self) } @@ -1171,7 +1172,7 @@ impl TypedDateTimeNames { + DataProvider + ?Sized, { - let locale = &self.locale; + let locale = self.prefs; self.inner.load_for_pattern( &C::YearNamesV1Marker::bind(provider), &C::MonthNamesV1Marker::bind(provider), @@ -1211,7 +1212,7 @@ impl TypedDateTimeNames { /// use writeable::assert_try_writeable_eq; /// /// let mut names = - /// TypedDateTimeNames::::try_new(&locale!("en").into()) + /// TypedDateTimeNames::::try_new(locale!("en").into()) /// .unwrap(); /// /// // Create a pattern from a pattern string: @@ -1242,7 +1243,7 @@ impl TypedDateTimeNames { + DataProvider + DataProvider, { - let locale = &self.locale; + let locale = self.prefs; self.inner.load_for_pattern( &C::YearNamesV1Marker::bind(&crate::provider::Baked), &C::MonthNamesV1Marker::bind(&crate::provider::Baked), @@ -1307,12 +1308,13 @@ impl RawDateTimeNames { pub(crate) fn load_year_names

( &mut self, provider: &P, - locale: &DataLocale, + prefs: DateTimeFormatterPreferences, field_length: FieldLength, ) -> Result<(), PatternLoadError> where P: BoundDataProvider + ?Sized, { + let locale = provider.bound_marker().make_locale(prefs.locale_prefs); let field = fields::Field { symbol: FieldSymbol::Era, length: field_length, @@ -1331,7 +1333,7 @@ impl RawDateTimeNames { _ => return Err(PatternLoadError::UnsupportedLength(field)), }, ), - locale, + &locale, ), ..Default::default() }; @@ -1345,13 +1347,14 @@ impl RawDateTimeNames { pub(crate) fn load_month_names

( &mut self, provider: &P, - locale: &DataLocale, + prefs: DateTimeFormatterPreferences, field_symbol: fields::Month, field_length: FieldLength, ) -> Result<(), PatternLoadError> where P: BoundDataProvider + ?Sized, { + let locale = provider.bound_marker().make_locale(prefs.locale_prefs); let field = fields::Field { symbol: FieldSymbol::Month(field_symbol), length: field_length, @@ -1371,7 +1374,7 @@ impl RawDateTimeNames { _ => return Err(PatternLoadError::UnsupportedLength(field)), }, ), - locale, + &locale, ), ..Default::default() }; @@ -1385,12 +1388,13 @@ impl RawDateTimeNames { pub(crate) fn load_day_period_names

( &mut self, provider: &P, - locale: &DataLocale, + prefs: DateTimeFormatterPreferences, field_length: FieldLength, ) -> Result<(), PatternLoadError> where P: BoundDataProvider + ?Sized, { + let locale = provider.bound_marker().make_locale(prefs.locale_prefs); let field = fields::Field { // Names for 'a' and 'b' are stored in the same data marker symbol: FieldSymbol::DayPeriod(fields::DayPeriod::NoonMidnight), @@ -1410,7 +1414,7 @@ impl RawDateTimeNames { _ => return Err(PatternLoadError::UnsupportedLength(field)), }, ), - locale, + &locale, ), ..Default::default() }; @@ -1424,13 +1428,14 @@ impl RawDateTimeNames { pub(crate) fn load_weekday_names

( &mut self, provider: &P, - locale: &DataLocale, + prefs: DateTimeFormatterPreferences, field_symbol: fields::Weekday, field_length: FieldLength, ) -> Result<(), PatternLoadError> where P: BoundDataProvider + ?Sized, { + let locale = provider.bound_marker().make_locale(prefs.locale_prefs); let field = fields::Field { symbol: FieldSymbol::Weekday(field_symbol), length: field_length, @@ -1461,7 +1466,7 @@ impl RawDateTimeNames { _ => return Err(PatternLoadError::UnsupportedLength(field)), }, ), - locale, + &locale, ), ..Default::default() }; @@ -1475,18 +1480,19 @@ impl RawDateTimeNames { pub(crate) fn load_time_zone_essentials

( &mut self, provider: &P, - locale: &DataLocale, + prefs: DateTimeFormatterPreferences, ) -> Result<(), PatternLoadError> where P: BoundDataProvider + ?Sized, { + let locale = provider.bound_marker().make_locale(prefs.locale_prefs); let field = fields::Field { symbol: FieldSymbol::TimeZone(fields::TimeZone::LocalizedOffset), length: FieldLength::Four, }; let variables = (); let req = DataRequest { - id: DataIdentifierBorrowed::for_locale(locale), + id: DataIdentifierBorrowed::for_locale(&locale), ..Default::default() }; self.zone_essentials @@ -1499,18 +1505,19 @@ impl RawDateTimeNames { pub(crate) fn load_time_zone_location_names

( &mut self, provider: &P, - locale: &DataLocale, + prefs: DateTimeFormatterPreferences, ) -> Result<(), PatternLoadError> where P: BoundDataProvider + ?Sized, { + let locale = provider.bound_marker().make_locale(prefs.locale_prefs); let field = fields::Field { symbol: FieldSymbol::TimeZone(fields::TimeZone::Location), length: FieldLength::Four, }; let variables = (); let req = DataRequest { - id: DataIdentifierBorrowed::for_locale(locale), + id: DataIdentifierBorrowed::for_locale(&locale), ..Default::default() }; self.locations_root @@ -1524,122 +1531,133 @@ impl RawDateTimeNames { Ok(()) } + fn load_mz_periods

( + &mut self, + provider: &P, + field: fields::Field, + ) -> Result<(), PatternLoadError> + where + P: BoundDataProvider + ?Sized, + { + let variables = (); + self.mz_periods + .load_put(provider, Default::default(), variables) + .map_err(|e| MaybePayloadError::into_load_error(e, field))? + .map_err(|e| PatternLoadError::Data(e, field))?; + Ok(()) + } + pub(crate) fn load_time_zone_generic_long_names( &mut self, - mz_generic_long_provider: &(impl BoundDataProvider + ?Sized), + provider: &(impl BoundDataProvider + ?Sized), mz_period_provider: &(impl BoundDataProvider + ?Sized), - locale: &DataLocale, + prefs: DateTimeFormatterPreferences, ) -> Result<(), PatternLoadError> { + let locale = provider.bound_marker().make_locale(prefs.locale_prefs); let field = fields::Field { symbol: FieldSymbol::TimeZone(fields::TimeZone::GenericNonLocation), length: FieldLength::Four, }; let variables = (); let req = DataRequest { - id: DataIdentifierBorrowed::for_locale(locale), + id: DataIdentifierBorrowed::for_locale(&locale), ..Default::default() }; self.mz_generic_long - .load_put(mz_generic_long_provider, req, variables) - .map_err(|e| MaybePayloadError::into_load_error(e, field))? - .map_err(|e| PatternLoadError::Data(e, field))?; - self.mz_periods - .load_put(mz_period_provider, Default::default(), variables) + .load_put(provider, req, variables) .map_err(|e| MaybePayloadError::into_load_error(e, field))? .map_err(|e| PatternLoadError::Data(e, field))?; + self.load_mz_periods(mz_period_provider, field)?; Ok(()) } pub(crate) fn load_time_zone_generic_short_names( &mut self, - mz_generic_short_provider: &(impl BoundDataProvider + ?Sized), + provider: &(impl BoundDataProvider + ?Sized), mz_period_provider: &(impl BoundDataProvider + ?Sized), - locale: &DataLocale, + prefs: DateTimeFormatterPreferences, ) -> Result<(), PatternLoadError> { + let locale = provider.bound_marker().make_locale(prefs.locale_prefs); let field = fields::Field { symbol: FieldSymbol::TimeZone(fields::TimeZone::GenericNonLocation), length: FieldLength::One, }; let variables = (); let req = DataRequest { - id: DataIdentifierBorrowed::for_locale(locale), + id: DataIdentifierBorrowed::for_locale(&locale), ..Default::default() }; self.mz_generic_short - .load_put(mz_generic_short_provider, req, variables) - .map_err(|e| MaybePayloadError::into_load_error(e, field))? - .map_err(|e| PatternLoadError::Data(e, field))?; - self.mz_periods - .load_put(mz_period_provider, Default::default(), variables) + .load_put(provider, req, variables) .map_err(|e| MaybePayloadError::into_load_error(e, field))? .map_err(|e| PatternLoadError::Data(e, field))?; + self.load_mz_periods(mz_period_provider, field)?; Ok(()) } pub(crate) fn load_time_zone_specific_long_names( &mut self, - mz_specific_long_provider: &(impl BoundDataProvider + ?Sized), + provider: &(impl BoundDataProvider + ?Sized), mz_period_provider: &(impl BoundDataProvider + ?Sized), - locale: &DataLocale, + prefs: DateTimeFormatterPreferences, ) -> Result<(), PatternLoadError> { + let locale = provider.bound_marker().make_locale(prefs.locale_prefs); let field = fields::Field { symbol: FieldSymbol::TimeZone(fields::TimeZone::SpecificNonLocation), length: FieldLength::Four, }; let variables = (); let req = DataRequest { - id: DataIdentifierBorrowed::for_locale(locale), + id: DataIdentifierBorrowed::for_locale(&locale), ..Default::default() }; self.mz_specific_long - .load_put(mz_specific_long_provider, req, variables) - .map_err(|e| MaybePayloadError::into_load_error(e, field))? - .map_err(|e| PatternLoadError::Data(e, field))?; - self.mz_periods - .load_put(mz_period_provider, Default::default(), variables) + .load_put(provider, req, variables) .map_err(|e| MaybePayloadError::into_load_error(e, field))? .map_err(|e| PatternLoadError::Data(e, field))?; + self.load_mz_periods(mz_period_provider, field)?; Ok(()) } pub(crate) fn load_time_zone_specific_short_names( &mut self, - mz_specific_short_provider: &(impl BoundDataProvider + ?Sized), + provider: &(impl BoundDataProvider + ?Sized), mz_period_provider: &(impl BoundDataProvider + ?Sized), - locale: &DataLocale, + prefs: DateTimeFormatterPreferences, ) -> Result<(), PatternLoadError> { + let locale = provider.bound_marker().make_locale(prefs.locale_prefs); let field = fields::Field { symbol: FieldSymbol::TimeZone(fields::TimeZone::SpecificNonLocation), length: FieldLength::One, }; let variables = (); let req = DataRequest { - id: DataIdentifierBorrowed::for_locale(locale), + id: DataIdentifierBorrowed::for_locale(&locale), ..Default::default() }; self.mz_specific_short - .load_put(mz_specific_short_provider, req, variables) - .map_err(|e| MaybePayloadError::into_load_error(e, field))? - .map_err(|e| PatternLoadError::Data(e, field))?; - self.mz_periods - .load_put(mz_period_provider, Default::default(), variables) + .load_put(provider, req, variables) .map_err(|e| MaybePayloadError::into_load_error(e, field))? .map_err(|e| PatternLoadError::Data(e, field))?; + self.load_mz_periods(mz_period_provider, field)?; Ok(()) } pub(crate) fn load_fixed_decimal_formatter( &mut self, loader: &impl FixedDecimalFormatterLoader, - locale: &DataLocale, + prefs: DateTimeFormatterPreferences, ) -> Result<(), DataError> { if self.fixed_decimal_formatter.is_some() { return Ok(()); } let mut options = FixedDecimalFormatterOptions::default(); options.grouping_strategy = GroupingStrategy::Never; - self.fixed_decimal_formatter = - Some(FixedDecimalFormatterLoader::load(loader, locale, options)?); + self.fixed_decimal_formatter = Some(FixedDecimalFormatterLoader::load( + loader, + (&prefs).into(), + options, + )?); Ok(()) } @@ -1662,7 +1680,7 @@ impl RawDateTimeNames { mz_specific_short_provider: &(impl BoundDataProvider + ?Sized), mz_period_provider: &(impl BoundDataProvider + ?Sized), fixed_decimal_formatter_loader: &impl FixedDecimalFormatterLoader, - locale: &DataLocale, + prefs: DateTimeFormatterPreferences, pattern_items: impl Iterator, ) -> Result<(), PatternLoadError> { let mut numeric_field = None; @@ -1681,42 +1699,42 @@ impl RawDateTimeNames { // G..GGGGG (FS::Era, One | Two | Three | Four | Five) => { - self.load_year_names(year_provider, locale, field.length)?; + self.load_year_names(year_provider, prefs, field.length)?; } // U..UUUUU (FS::Year(Year::Cyclic), One | Two | Three | Four | Five) => { numeric_field = Some(field); - self.load_year_names(year_provider, locale, field.length)?; + self.load_year_names(year_provider, prefs, field.length)?; } // MMM..MMMMM (FS::Month(Month::Format), Three | Four | Five) => { - self.load_month_names(month_provider, locale, Month::Format, field.length)?; + self.load_month_names(month_provider, prefs, Month::Format, field.length)?; } // LLL..LLLLL (FS::Month(Month::StandAlone), Three | Four | Five) => { - self.load_month_names(month_provider, locale, Month::StandAlone, field.length)?; + self.load_month_names(month_provider, prefs, Month::StandAlone, field.length)?; } // E..EE (FS::Weekday(Weekday::Format), One | Two) => { self.load_weekday_names( weekday_provider, - locale, + prefs, Weekday::Format, field.length, )?; } // EEE..EEEEEE, eee..eeeeee, ccc..cccccc (FS::Weekday(symbol), Three | Four | Five | Six) => { - self.load_weekday_names(weekday_provider, locale, symbol, field.length)?; + self.load_weekday_names(weekday_provider, prefs, symbol, field.length)?; } // a..aaaaa, b..bbbbb (FS::DayPeriod(_), One | Two | Three | Four | Five) => { - self.load_day_period_names(dayperiod_provider, locale, field.length)?; + self.load_day_period_names(dayperiod_provider, prefs, field.length)?; } ///// Time zone symbols ///// @@ -1724,48 +1742,48 @@ impl RawDateTimeNames { // z..zzz (FS::TimeZone(TimeZone::SpecificNonLocation), One | Two | Three) => { numeric_field = Some(field); - self.load_time_zone_essentials(zone_essentials_provider, locale)?; + self.load_time_zone_essentials(zone_essentials_provider, prefs)?; self.load_time_zone_specific_short_names( mz_specific_short_provider, mz_period_provider, - locale, + prefs, )?; } // zzzz (FS::TimeZone(TimeZone::SpecificNonLocation), Four) => { numeric_field = Some(field); - self.load_time_zone_essentials(zone_essentials_provider, locale)?; + self.load_time_zone_essentials(zone_essentials_provider, prefs)?; self.load_time_zone_specific_long_names( mz_specific_long_provider, mz_period_provider, - locale, + prefs, )?; - self.load_time_zone_location_names(locations_provider, locale)?; + self.load_time_zone_location_names(locations_provider, prefs)?; } // v (FS::TimeZone(TimeZone::GenericNonLocation), One) => { numeric_field = Some(field); - self.load_time_zone_essentials(zone_essentials_provider, locale)?; + self.load_time_zone_essentials(zone_essentials_provider, prefs)?; self.load_time_zone_generic_short_names( mz_generic_short_provider, mz_period_provider, - locale, + prefs, )?; // For fallback: - self.load_time_zone_location_names(locations_provider, locale)?; + self.load_time_zone_location_names(locations_provider, prefs)?; } // vvvv (FS::TimeZone(TimeZone::GenericNonLocation), Four) => { numeric_field = Some(field); - self.load_time_zone_essentials(zone_essentials_provider, locale)?; + self.load_time_zone_essentials(zone_essentials_provider, prefs)?; self.load_time_zone_generic_long_names( mz_generic_long_provider, mz_period_provider, - locale, + prefs, )?; // For fallback: - self.load_time_zone_location_names(locations_provider, locale)?; + self.load_time_zone_location_names(locations_provider, prefs)?; } // V @@ -1775,13 +1793,13 @@ impl RawDateTimeNames { // VVVV (FS::TimeZone(TimeZone::Location), Four) => { numeric_field = Some(field); - self.load_time_zone_essentials(zone_essentials_provider, locale)?; - self.load_time_zone_location_names(locations_provider, locale)?; + self.load_time_zone_essentials(zone_essentials_provider, prefs)?; + self.load_time_zone_location_names(locations_provider, prefs)?; } // O, OOOO (FS::TimeZone(TimeZone::LocalizedOffset), One | Four) => { - self.load_time_zone_essentials(zone_essentials_provider, locale)?; + self.load_time_zone_essentials(zone_essentials_provider, prefs)?; numeric_field = Some(field); } @@ -1841,7 +1859,7 @@ impl RawDateTimeNames { } if let Some(field) = numeric_field { - self.load_fixed_decimal_formatter(fixed_decimal_formatter_loader, locale) + self.load_fixed_decimal_formatter(fixed_decimal_formatter_loader, prefs) .map_err(|e| PatternLoadError::Data(e, field))?; } diff --git a/components/datetime/src/pattern/pattern.rs b/components/datetime/src/pattern/pattern.rs index a8246366dfa..3c400766e40 100644 --- a/components/datetime/src/pattern/pattern.rs +++ b/components/datetime/src/pattern/pattern.rs @@ -53,7 +53,7 @@ size_test!(DateTimePattern, date_time_pattern_size, 32); /// /// // Load data that resolves to the same pattern: /// let data_pattern = FixedCalendarDateTimeFormatter::::try_new( -/// &locale!("es-MX").into(), +/// locale!("es-MX").into(), /// YMD::medium(), /// ) /// .unwrap() diff --git a/components/datetime/src/raw/neo.rs b/components/datetime/src/raw/neo.rs index 5a49e93cae2..3f61b7c7784 100644 --- a/components/datetime/src/raw/neo.rs +++ b/components/datetime/src/raw/neo.rs @@ -12,6 +12,7 @@ use crate::provider::pattern::{ GenericPatternItem, PatternItem, }; use crate::provider::{neo::*, ErasedPackedPatterns, PackedSkeletonVariant}; +use crate::DateTimeFormatterPreferences; use icu_calendar::types::YearAmbiguity; use icu_provider::prelude::*; use marker_attrs::GlueType; @@ -43,6 +44,14 @@ pub(crate) struct RawPreferences { pub(crate) hour_cycle: Option, } +impl RawPreferences { + pub(crate) fn from_prefs(prefs: DateTimeFormatterPreferences) -> Self { + Self { + hour_cycle: prefs.hour_cycle.map(fields::Hour::from_hour_cycle), + } + } +} + #[derive(Debug)] pub(crate) enum DatePatternSelectionData { SkeletonDate { @@ -181,13 +190,14 @@ pub(crate) enum DateTimeZonePatternDataBorrowed<'a> { impl DatePatternSelectionData { pub(crate) fn try_new_with_skeleton( provider: &(impl BoundDataProvider + ?Sized), - locale: &DataLocale, + prefs: DateTimeFormatterPreferences, attributes: &DataMarkerAttributes, options: RawOptions, ) -> Result { + let locale = provider.bound_marker().make_locale(prefs.locale_prefs); let payload = provider .load_bound(DataRequest { - id: DataIdentifierBorrowed::for_marker_attributes_and_locale(attributes, locale), + id: DataIdentifierBorrowed::for_marker_attributes_and_locale(attributes, &locale), ..Default::default() })? .payload; @@ -283,14 +293,15 @@ impl<'a> DatePatternDataBorrowed<'a> { impl OverlapPatternSelectionData { pub(crate) fn try_new_with_skeleton( provider: &(impl BoundDataProvider + ?Sized), - locale: &DataLocale, + prefs: DateTimeFormatterPreferences, attributes: &DataMarkerAttributes, options: RawOptions, - prefs: RawPreferences, ) -> Result { + let locale = provider.bound_marker().make_locale(prefs.locale_prefs); + let prefs = RawPreferences::from_prefs(prefs); let payload = provider .load_bound(DataRequest { - id: DataIdentifierBorrowed::for_marker_attributes_and_locale(attributes, locale), + id: DataIdentifierBorrowed::for_marker_attributes_and_locale(attributes, &locale), ..Default::default() })? .payload; @@ -349,11 +360,12 @@ impl OverlapPatternSelectionData { impl TimePatternSelectionData { pub(crate) fn try_new_with_skeleton( provider: &(impl BoundDataProvider + ?Sized), - locale: &DataLocale, + prefs: DateTimeFormatterPreferences, components: TimeFieldSet, options: RawOptions, - prefs: RawPreferences, ) -> Result { + let locale = provider.bound_marker().make_locale(prefs.locale_prefs); + let prefs = RawPreferences::from_prefs(prefs); // First try to load with the explicit hour cycle. If there is no explicit hour cycle, // or if loading the explicit hour cycle fails, then load with the default hour cycle. let mut maybe_payload = None; @@ -362,7 +374,7 @@ impl TimePatternSelectionData { .load_bound(DataRequest { id: DataIdentifierBorrowed::for_marker_attributes_and_locale( components.id_str_for_hour_cycle(Some(hour_cycle)), - locale, + &locale, ), ..Default::default() }) @@ -376,7 +388,7 @@ impl TimePatternSelectionData { .load_bound(DataRequest { id: DataIdentifierBorrowed::for_marker_attributes_and_locale( components.id_str_for_hour_cycle(None), - locale, + &locale, ), ..Default::default() })? @@ -484,16 +496,15 @@ impl DateTimeZonePatternSelectionData { date_provider: &(impl BoundDataProvider + ?Sized), time_provider: &(impl BoundDataProvider + ?Sized), glue_provider: &(impl BoundDataProvider + ?Sized), - locale: &DataLocale, + prefs: DateTimeFormatterPreferences, skeleton: CompositeFieldSet, - prefs: RawPreferences, ) -> Result { match skeleton { CompositeFieldSet::Date(field_set) => { let options = field_set.to_raw_options(); let selection = DatePatternSelectionData::try_new_with_skeleton( date_provider, - locale, + prefs, field_set.id_str(), options, )?; @@ -503,7 +514,7 @@ impl DateTimeZonePatternSelectionData { let options = field_set.to_raw_options(); let selection = DatePatternSelectionData::try_new_with_skeleton( date_provider, - locale, + prefs, field_set.id_str(), options, )?; @@ -513,10 +524,9 @@ impl DateTimeZonePatternSelectionData { let options = field_set.to_raw_options(); let selection = TimePatternSelectionData::try_new_with_skeleton( time_provider, - locale, + prefs, field_set, options, - prefs, )?; Ok(Self::Time(selection)) } @@ -532,10 +542,9 @@ impl DateTimeZonePatternSelectionData { if let Some(overlap) = OverlapPatternSelectionData::try_new_with_skeleton( // Note: overlap patterns are stored in the date provider date_provider, - locale, + prefs, attributes, options, - prefs, ) .allow_identifier_not_found()? { @@ -544,25 +553,24 @@ impl DateTimeZonePatternSelectionData { } let date = DatePatternSelectionData::try_new_with_skeleton( date_provider, - locale, + prefs, field_set.to_date_field_set().id_str(), options, )?; let time = TimePatternSelectionData::try_new_with_skeleton( time_provider, - locale, + prefs, field_set.to_time_field_set(), options, - prefs, )?; - let glue = Self::load_glue(glue_provider, locale, options, GlueType::DateTime)?; + let glue = Self::load_glue(glue_provider, prefs, options, GlueType::DateTime)?; Ok(Self::DateTimeGlue { date, time, glue }) } CompositeFieldSet::DateZone(field_set, time_zone_style) => { let options = field_set.to_raw_options(); let date = DatePatternSelectionData::try_new_with_skeleton( date_provider, - locale, + prefs, field_set.id_str(), options, )?; @@ -572,17 +580,16 @@ impl DateTimeZonePatternSelectionData { NeoSkeletonLength::Short, ); let zone = ZonePatternSelectionData::new_with_skeleton(zone_field_set); - let glue = Self::load_glue(glue_provider, locale, options, GlueType::DateZone)?; + let glue = Self::load_glue(glue_provider, prefs, options, GlueType::DateZone)?; Ok(Self::DateZoneGlue { date, zone, glue }) } CompositeFieldSet::TimeZone(field_set, time_zone_style) => { let options = field_set.to_raw_options(); let time = TimePatternSelectionData::try_new_with_skeleton( time_provider, - locale, + prefs, field_set, options, - prefs, )?; // Always use the short length for time zones when mixed with another field (Time) let zone_field_set = ZoneFieldSet::from_time_zone_style_and_length( @@ -590,23 +597,22 @@ impl DateTimeZonePatternSelectionData { NeoSkeletonLength::Short, ); let zone = ZonePatternSelectionData::new_with_skeleton(zone_field_set); - let glue = Self::load_glue(glue_provider, locale, options, GlueType::TimeZone)?; + let glue = Self::load_glue(glue_provider, prefs, options, GlueType::TimeZone)?; Ok(Self::TimeZoneGlue { time, zone, glue }) } CompositeFieldSet::DateTimeZone(field_set, time_zone_style) => { let options = field_set.to_raw_options(); let date = DatePatternSelectionData::try_new_with_skeleton( date_provider, - locale, + prefs, field_set.to_date_field_set().id_str(), options, )?; let time = TimePatternSelectionData::try_new_with_skeleton( time_provider, - locale, + prefs, field_set.to_time_field_set(), options, - prefs, )?; // Always use the short length for time zones when mixed with another field (Date + Time) let zone_field_set = ZoneFieldSet::from_time_zone_style_and_length( @@ -614,7 +620,7 @@ impl DateTimeZonePatternSelectionData { NeoSkeletonLength::Short, ); let zone = ZonePatternSelectionData::new_with_skeleton(zone_field_set); - let glue = Self::load_glue(glue_provider, locale, options, GlueType::DateTimeZone)?; + let glue = Self::load_glue(glue_provider, prefs, options, GlueType::DateTimeZone)?; Ok(Self::DateTimeZoneGlue { date, time, @@ -626,12 +632,13 @@ impl DateTimeZonePatternSelectionData { } fn load_glue( - glue_provider: &(impl BoundDataProvider + ?Sized), - locale: &DataLocale, + provider: &(impl BoundDataProvider + ?Sized), + prefs: DateTimeFormatterPreferences, options: RawOptions, glue_type: GlueType, ) -> Result, DataError> { - glue_provider + let locale = provider.bound_marker().make_locale(prefs.locale_prefs); + provider .load_bound(DataRequest { id: DataIdentifierBorrowed::for_marker_attributes_and_locale( marker_attrs::pattern_marker_attr_for_glue( @@ -644,7 +651,7 @@ impl DateTimeZonePatternSelectionData { }, glue_type, ), - locale, + &locale, ), ..Default::default() }) diff --git a/components/datetime/tests/datetime.rs b/components/datetime/tests/datetime.rs index cbd6df2dddf..02a88a9139f 100644 --- a/components/datetime/tests/datetime.rs +++ b/components/datetime/tests/datetime.rs @@ -15,8 +15,8 @@ use icu_calendar::{ any_calendar::{AnyCalendarKind, IntoAnyCalendar}, AsCalendar, Calendar, DateTime, }; -use icu_datetime::fieldsets::enums::*; use icu_datetime::scaffold::CldrCalendar; +use icu_datetime::{fieldsets::enums::*, DateTimeFormatterPreferences}; use icu_datetime::{ pattern::DateTimePattern, pattern::TypedDateTimeNames, DateTimeFormatter, FixedCalendarDateTimeFormatter, @@ -297,9 +297,9 @@ fn assert_fixture_element( zone: TimeZoneInfo::utc(), }; - let dtf = FixedCalendarDateTimeFormatter::try_new(&locale.into(), skeleton).expect(description); + let dtf = FixedCalendarDateTimeFormatter::try_new(locale.into(), skeleton).expect(description); - let any_dtf = DateTimeFormatter::try_new(&locale.into(), skeleton).expect(description); + let any_dtf = DateTimeFormatter::try_new(locale.into(), skeleton).expect(description); let actual1 = dtf.format(&input_value); assert_try_writeable_eq!( @@ -364,7 +364,7 @@ fn test_fixture_with_time_zones(fixture_name: &str, file: &str) { apply_preference_bag_to_locale(hour_cycle.into(), &mut locale); } let dtf = { - FixedCalendarDateTimeFormatter::::try_new(&locale.into(), skeleton) + FixedCalendarDateTimeFormatter::::try_new(locale.into(), skeleton) .unwrap() }; assert_writeable_eq!( @@ -394,7 +394,7 @@ fn test_dayperiod_patterns() { DateTimePattern::try_from_pattern_str(pattern_input).unwrap(); let mut pattern_formatter = TypedDateTimeNames::::try_new( - &(&locale).into(), + (&locale).into(), ) .unwrap(); let formatted_datetime = pattern_formatter @@ -427,7 +427,7 @@ fn test_time_zone_format_configs() { .unwrap() .0 { - let data_locale: DataLocale = test.locale.parse::().unwrap().into(); + let prefs: DateTimeFormatterPreferences = test.locale.parse::().unwrap().into(); let zoned_datetime = mock::parse_zoned_gregorian_from_str(&test.datetime); for (pattern_input, expect) in &test.expectations { let Some(skeleton) = patterns::time_zones::pattern_to_semantic_skeleton(pattern_input) @@ -435,17 +435,16 @@ fn test_time_zone_format_configs() { continue; }; let tzf = - FixedCalendarDateTimeFormatter::::try_new(&data_locale, skeleton) - .unwrap(); + FixedCalendarDateTimeFormatter::::try_new(prefs, skeleton).unwrap(); assert_writeable_eq!( writeable::adapters::LossyWrap(tzf.format(&zoned_datetime.zone)), *expect, "\n\ - locale: `{}`,\n\ + prefs: `{:?}`,\n\ datetime: `{}`,\n\ config: `{:?}`,\n ", - data_locale, + prefs, test.datetime, pattern_input, ); @@ -457,7 +456,7 @@ fn test_time_zone_format_configs() { fn test_time_zone_format_offset_seconds() { use icu_datetime::fieldsets::O; - let tzf = FixedCalendarDateTimeFormatter::<(), _>::try_new(&locale!("en").into(), O::medium()) + let tzf = FixedCalendarDateTimeFormatter::<(), _>::try_new(locale!("en").into(), O::medium()) .unwrap(); assert_try_writeable_eq!( tzf.format(&UtcOffset::try_from_seconds(12).unwrap()), @@ -469,7 +468,7 @@ fn test_time_zone_format_offset_seconds() { fn test_time_zone_format_offset_fallback() { use icu_datetime::fieldsets::O; - let tzf = FixedCalendarDateTimeFormatter::<(), _>::try_new(&locale!("en").into(), O::medium()) + let tzf = FixedCalendarDateTimeFormatter::<(), _>::try_new(locale!("en").into(), O::medium()) .unwrap(); assert_try_writeable_eq!( tzf.format( @@ -488,7 +487,7 @@ fn test_time_zone_patterns() { .unwrap() .0 { - let data_locale: DataLocale = test.locale.parse::().unwrap().into(); + let prefs: DateTimeFormatterPreferences = test.locale.parse::().unwrap().into(); let zoned_datetime = mock::parse_zoned_gregorian_from_str(&test.datetime); for (pattern_input, expect) in &test.expectations { @@ -498,7 +497,7 @@ fn test_time_zone_patterns() { } let parsed_pattern = DateTimePattern::try_from_pattern_str(pattern_input).unwrap(); let mut pattern_formatter = - TypedDateTimeNames::::try_new(&data_locale).unwrap(); + TypedDateTimeNames::::try_new(prefs).unwrap(); let formatted_datetime = pattern_formatter .include_for_pattern(&parsed_pattern) .unwrap() @@ -507,10 +506,10 @@ fn test_time_zone_patterns() { writeable::adapters::LossyWrap(formatted_datetime), *expect, "\n\ - locale: `{}`,\n\ + prefs: `{:?}`,\n\ datetime: `{}`,\n\ pattern: `{}`", - data_locale, + prefs, test.datetime, pattern_input, ); diff --git a/components/datetime/tests/resolved_components.rs b/components/datetime/tests/resolved_components.rs index cc4115552b6..b74f5e10b78 100644 --- a/components/datetime/tests/resolved_components.rs +++ b/components/datetime/tests/resolved_components.rs @@ -18,7 +18,7 @@ fn assert_resolved_components( locale: Locale, ) { let dtf = - FixedCalendarDateTimeFormatter::::try_new(&locale.into(), skeleton).unwrap(); + FixedCalendarDateTimeFormatter::::try_new(locale.into(), skeleton).unwrap(); let datetime = DateTime { date: Date::try_new_gregorian(2024, 1, 1).unwrap(), time: Time::midnight(), diff --git a/components/datetime/tests/simple_test.rs b/components/datetime/tests/simple_test.rs index f89b9c521f3..63a561782c3 100644 --- a/components/datetime/tests/simple_test.rs +++ b/components/datetime/tests/simple_test.rs @@ -8,7 +8,7 @@ use icu_datetime::fieldsets::enums::{ CompositeDateTimeFieldSet, DateAndTimeFieldSet, DateFieldSet, }; use icu_datetime::fieldsets::{self, YMD}; -use icu_datetime::FixedCalendarDateTimeFormatter; +use icu_datetime::{DateTimeFormatterPreferences, FixedCalendarDateTimeFormatter}; use icu_locale_core::{locale, Locale}; use writeable::assert_try_writeable_eq; @@ -80,14 +80,10 @@ fn neo_datetime_lengths() { DateAndTimeFieldSet::YMDT(fieldsets::YMDT::short()), DateAndTimeFieldSet::YMDT(fieldsets::YMDT::short().hm()), ] { - for locale in [ - locale!("en").into(), - locale!("fr").into(), - locale!("zh").into(), - locale!("hi").into(), - ] { + for locale in [locale!("en"), locale!("fr"), locale!("zh"), locale!("hi")] { + let prefs = DateTimeFormatterPreferences::from(&locale); let skeleton = CompositeDateTimeFieldSet::DateTime(field_set); - let formatter = FixedCalendarDateTimeFormatter::try_new(&locale, skeleton).unwrap(); + let formatter = FixedCalendarDateTimeFormatter::try_new(prefs, skeleton).unwrap(); let formatted = formatter.format(&datetime); let expected = expected_iter.next().unwrap(); assert_try_writeable_eq!(formatted, *expected, Ok(()), "{skeleton:?} {locale:?}"); @@ -106,14 +102,9 @@ fn neo_date_lengths() { DateFieldSet::YMD(fieldsets::YMD::short()), ] { let date_skeleton = CompositeDateTimeFieldSet::Date(field_set); - for locale in [ - locale!("en").into(), - locale!("fr").into(), - locale!("zh").into(), - locale!("hi").into(), - ] { - let formatter = - FixedCalendarDateTimeFormatter::try_new(&locale, date_skeleton).unwrap(); + for locale in [locale!("en"), locale!("fr"), locale!("zh"), locale!("hi")] { + let prefs = DateTimeFormatterPreferences::from(&locale); + let formatter = FixedCalendarDateTimeFormatter::try_new(prefs, date_skeleton).unwrap(); let formatted = formatter.format(&datetime); let expected = expected_iter.next().unwrap(); assert_try_writeable_eq!(formatted, *expected, Ok(()), "{date_skeleton:?} {locale:?}"); @@ -169,8 +160,8 @@ fn overlap_patterns() { expected, } in cases { - let formatter = - FixedCalendarDateTimeFormatter::try_new(&(&locale).into(), skeleton).unwrap(); + let prefs = DateTimeFormatterPreferences::from(&locale); + let formatter = FixedCalendarDateTimeFormatter::try_new(prefs, skeleton).unwrap(); let formatted = formatter.format(&datetime); assert_try_writeable_eq!(formatted, expected, Ok(()), "{locale:?} {skeleton:?}"); } @@ -181,7 +172,7 @@ fn hebrew_months() { let datetime = DateTime::try_new_iso(2011, 4, 3, 14, 15, 7).unwrap(); let datetime = datetime.to_calendar(Hebrew); let formatter = - FixedCalendarDateTimeFormatter::try_new(&locale!("en").into(), YMD::medium()).unwrap(); + FixedCalendarDateTimeFormatter::try_new(locale!("en").into(), YMD::medium()).unwrap(); let formatted_datetime = formatter.format(&datetime); @@ -192,17 +183,17 @@ fn hebrew_months() { fn test_5387() { let datetime = DateTime::try_new_gregorian(2024, 8, 16, 14, 15, 16).unwrap(); let formatter_auto = FixedCalendarDateTimeFormatter::try_new( - &locale!("en").into(), + locale!("en").into(), CompositeDateTimeFieldSet::DateTime(DateAndTimeFieldSet::ET(fieldsets::ET::medium())), ) .unwrap(); let formatter_h12 = FixedCalendarDateTimeFormatter::try_new( - &locale!("en-u-hc-h12").into(), + locale!("en-u-hc-h12").into(), CompositeDateTimeFieldSet::DateTime(DateAndTimeFieldSet::ET(fieldsets::ET::medium())), ) .unwrap(); let formatter_h24 = FixedCalendarDateTimeFormatter::try_new( - &locale!("en-u-hc-h23").into(), + locale!("en-u-hc-h23").into(), CompositeDateTimeFieldSet::DateTime(DateAndTimeFieldSet::ET(fieldsets::ET::medium())), ) .unwrap(); diff --git a/components/icu/README.md b/components/icu/README.md index c0ff0a1f5cb..a77ca5625a1 100644 --- a/components/icu/README.md +++ b/components/icu/README.md @@ -32,7 +32,7 @@ use icu::datetime::{DateTimeFormatter, NeoSkeletonLength, fieldsets::YMD}; use icu::locale::locale; let dtf = DateTimeFormatter::try_new( - &locale!("es-US").into(), + locale!("es-US").into(), YMD::medium(), ) .expect("compiled data should include 'es-US'"); @@ -69,7 +69,7 @@ let provider = LocaleFallbackProvider::new(provider, fallbacker); let dtf = DateTimeFormatter::try_new_with_buffer_provider( &provider, - &locale!("es-US").into(), + locale!("es-US").into(), YMD::medium(), ) .expect("data should include 'es-US', 'es', or 'und'"); diff --git a/components/icu/examples/tui.rs b/components/icu/examples/tui.rs index 834d2cd1b4a..0868709fe9d 100644 --- a/components/icu/examples/tui.rs +++ b/components/icu/examples/tui.rs @@ -22,7 +22,7 @@ fn main() { let locale = args .get(1) .map(|s| s.parse().expect("Failed to parse locale")) - .unwrap_or_else(|| locale!("en").into()); + .unwrap_or_else(|| locale!("en")); let user_name = args.as_slice().get(2).map(String::as_str).unwrap_or("John"); @@ -39,9 +39,11 @@ fn main() { println!("User: {user_name}"); { - let dtf = - FixedCalendarDateTimeFormatter::::try_new(&locale, YMDTO::medium()) - .expect("Failed to create zoned datetime formatter."); + let dtf = FixedCalendarDateTimeFormatter::::try_new( + locale.into(), + YMDTO::medium(), + ) + .expect("Failed to create zoned datetime formatter."); let date = Date::try_new_gregorian(2020, 10, 10).unwrap(); let time = Time::try_new(18, 56, 0, 0).unwrap(); let zone = TimeZoneInfo::utc(); diff --git a/components/icu/src/lib.rs b/components/icu/src/lib.rs index 147a62c861b..f5a59b5a94d 100644 --- a/components/icu/src/lib.rs +++ b/components/icu/src/lib.rs @@ -32,7 +32,7 @@ //! use icu::locale::locale; //! //! let dtf = DateTimeFormatter::try_new( -//! &locale!("es-US").into(), +//! locale!("es-US").into(), //! YMD::medium(), //! ) //! .expect("compiled data should include 'es-US'"); @@ -69,7 +69,7 @@ //! //! let dtf = DateTimeFormatter::try_new_with_buffer_provider( //! &provider, -//! &locale!("es-US").into(), +//! locale!("es-US").into(), //! YMD::medium(), //! ) //! .expect("data should include 'es-US', 'es', or 'und'"); diff --git a/ffi/capi/src/calendar.rs b/ffi/capi/src/calendar.rs index 76170147492..0e34cf64019 100644 --- a/ffi/capi/src/calendar.rs +++ b/ffi/capi/src/calendar.rs @@ -108,14 +108,14 @@ pub mod ffi { provider: &DataProvider, locale: &Locale, ) -> Result, DataError> { - let locale = locale.to_datalocale(); + let prefs = (&locale.0).into(); Ok(Box::new(Calendar(Arc::new(call_constructor!( icu_calendar::AnyCalendar::new_for_locale [r => Ok(r)], icu_calendar::AnyCalendar::try_new_for_locale_with_any_provider, icu_calendar::AnyCalendar::try_new_for_locale_with_buffer_provider, provider, - &locale + prefs )?)))) } diff --git a/ffi/capi/src/datetime_formatter.rs b/ffi/capi/src/datetime_formatter.rs index 07af7416384..0149488cd7b 100644 --- a/ffi/capi/src/datetime_formatter.rs +++ b/ffi/capi/src/datetime_formatter.rs @@ -45,7 +45,7 @@ pub mod ffi { locale: &Locale, length: DateTimeLength, ) -> Result, DateTimeFormatterLoadError> { - let locale = locale.to_datalocale(); + let prefs = (&locale.0).into(); let options = T::with_length(NeoSkeletonLength::from(length)).hm(); Ok(Box::new(TimeFormatter(call_constructor!( @@ -53,7 +53,7 @@ pub mod ffi { icu_datetime::FixedCalendarDateTimeFormatter::try_new_with_any_provider, icu_datetime::FixedCalendarDateTimeFormatter::try_new_with_buffer_provider, provider, - &locale, + prefs, options )?))) } @@ -99,7 +99,7 @@ pub mod ffi { locale: &Locale, length: DateTimeLength, ) -> Result, DateTimeFormatterLoadError> { - let locale = locale.to_datalocale(); + let prefs = (&locale.0).into(); let options = YMD::with_length(NeoSkeletonLength::from(length)); Ok(Box::new(GregorianDateFormatter(call_constructor!( @@ -107,7 +107,7 @@ pub mod ffi { icu_datetime::FixedCalendarDateTimeFormatter::try_new_with_any_provider, icu_datetime::FixedCalendarDateTimeFormatter::try_new_with_buffer_provider, provider, - &locale, + prefs, options )?))) } @@ -149,7 +149,7 @@ pub mod ffi { locale: &Locale, length: DateTimeLength, ) -> Result, DateTimeFormatterLoadError> { - let locale = locale.to_datalocale(); + let prefs = (&locale.0).into(); let options = YMDT::with_length(NeoSkeletonLength::from(length)).hm(); Ok(Box::new(GregorianDateTimeFormatter(call_constructor!( @@ -157,7 +157,7 @@ pub mod ffi { icu_datetime::FixedCalendarDateTimeFormatter::try_new_with_any_provider, icu_datetime::FixedCalendarDateTimeFormatter::try_new_with_buffer_provider, provider, - &locale, + prefs, options )?))) } @@ -188,7 +188,7 @@ pub mod ffi { locale: &Locale, length: DateTimeLength, ) -> Result, DateTimeFormatterLoadError> { - let locale = locale.to_datalocale(); + let prefs = (&locale.0).into(); let options = YMD::with_length(NeoSkeletonLength::from(length)); Ok(Box::new(DateFormatter(call_constructor!( @@ -196,7 +196,7 @@ pub mod ffi { icu_datetime::DateTimeFormatter::try_new_with_any_provider, icu_datetime::DateTimeFormatter::try_new_with_buffer_provider, provider, - &locale, + prefs, options )?))) } @@ -263,7 +263,7 @@ pub mod ffi { locale: &Locale, length: DateTimeLength, ) -> Result, DateTimeFormatterLoadError> { - let locale = locale.to_datalocale(); + let prefs = (&locale.0).into(); let options = YMDT::with_length(NeoSkeletonLength::from(length)).hm(); Ok(Box::new(DateTimeFormatter(call_constructor!( @@ -271,7 +271,7 @@ pub mod ffi { icu_datetime::DateTimeFormatter::try_new_with_any_provider, icu_datetime::DateTimeFormatter::try_new_with_buffer_provider, provider, - &locale, + prefs, options, )?))) } diff --git a/ffi/capi/src/zoned_formatter.rs b/ffi/capi/src/zoned_formatter.rs index 01aff22f06e..8b8b0c82035 100644 --- a/ffi/capi/src/zoned_formatter.rs +++ b/ffi/capi/src/zoned_formatter.rs @@ -40,7 +40,7 @@ pub mod ffi { locale: &Locale, length: DateTimeLength, ) -> Result, DateTimeFormatterLoadError> { - let locale = locale.to_datalocale(); + let prefs = (&locale.0).into(); let options = YMDTV::with_length(NeoSkeletonLength::from(length)); Ok(Box::new(GregorianZonedDateTimeFormatter( @@ -49,7 +49,7 @@ pub mod ffi { icu_datetime::FixedCalendarDateTimeFormatter::try_new_with_any_provider, icu_datetime::FixedCalendarDateTimeFormatter::try_new_with_buffer_provider, provider, - &locale, + prefs, options )?, ))) @@ -94,7 +94,7 @@ pub mod ffi { locale: &Locale, length: DateTimeLength, ) -> Result, DateTimeFormatterLoadError> { - let locale = locale.to_datalocale(); + let prefs = (&locale.0).into(); let options = YMDTV::with_length(NeoSkeletonLength::from(length)); Ok(Box::new(ZonedDateTimeFormatter(call_constructor!( @@ -102,7 +102,7 @@ pub mod ffi { icu_datetime::DateTimeFormatter::try_new_with_any_provider, icu_datetime::DateTimeFormatter::try_new_with_buffer_provider, provider, - &locale, + prefs, options, )?))) } diff --git a/ffi/capi/tests/missing_apis.txt b/ffi/capi/tests/missing_apis.txt index 24ac126fd14..8ad8d63387f 100644 --- a/ffi/capi/tests/missing_apis.txt +++ b/ffi/capi/tests/missing_apis.txt @@ -14,6 +14,10 @@ # Please check in with @Manishearth, @robertbastian, or @sffc if you have questions +icu::calendar::AnyCalendarPreferences#Struct +icu::calendar::AnyCalendarPreferences::extend#FnInStruct +icu::calendar::any_calendar::AnyCalendarPreferences#Struct +icu::calendar::any_calendar::AnyCalendarPreferences::extend#FnInStruct icu::calendar::types::YearAmbiguity#Enum icu::calendar::types::YearInfo::year_ambiguity#FnInStruct icu::collator::CollatorPreferences::extend#FnInStruct @@ -23,6 +27,8 @@ icu::datetime::DateTimeFormatter::strict_format#FnInStruct icu::datetime::DateTimeFormatter::try_into_typed_formatter#FnInStruct icu::datetime::DateTimeFormatter::try_new#FnInStruct icu::datetime::DateTimeFormatterLoadError#Enum +icu::datetime::DateTimeFormatterPreferences#Struct +icu::datetime::DateTimeFormatterPreferences::extend#FnInStruct icu::datetime::FixedCalendarDateTimeFormatter#Struct icu::datetime::FixedCalendarDateTimeFormatter::format#FnInStruct icu::datetime::FixedCalendarDateTimeFormatter::into_formatter#FnInStruct diff --git a/provider/core/src/marker.rs b/provider/core/src/marker.rs index f9281faa681..0605d99112a 100644 --- a/provider/core/src/marker.rs +++ b/provider/core/src/marker.rs @@ -3,7 +3,7 @@ // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). use crate::fallback::LocaleFallbackConfig; -use crate::{DataError, DataErrorKind, DataProvider, DataProviderWithMarker}; +use crate::{DataError, DataErrorKind, DataLocale, DataProvider, DataProviderWithMarker}; use core::fmt; use core::marker::PhantomData; use yoke::Yokeable; @@ -603,6 +603,14 @@ impl DataMarkerInfo { Err(DataErrorKind::MarkerNotFound.with_marker(marker)) } } + + /// Constructs a [`DataLocale`] for this [`DataMarkerInfo`]. + pub fn make_locale( + self, + locale: icu_locale_core::preferences::LocalePreferences, + ) -> DataLocale { + DataLocale::from_preferences_with_info(locale, self) + } } /// See [`DataMarkerInfo`]. diff --git a/provider/core/src/request.rs b/provider/core/src/request.rs index fb39b1cfbbd..12c35b3ec45 100644 --- a/provider/core/src/request.rs +++ b/provider/core/src/request.rs @@ -20,6 +20,7 @@ use zerovec::ule::VarULE; use crate::fallback::LocaleFallbackPriority; use crate::DataMarker; +use crate::DataMarkerInfo; /// The request type passed into all data provider implementations. #[derive(Default, Debug, Clone, Copy, PartialEq, Eq)] @@ -283,6 +284,13 @@ impl DataLocale { /// Returns a [`DataLocale`] usable for the marker `M`. pub const fn from_preferences_locale( locale: icu_locale_core::preferences::LocalePreferences, + ) -> Self { + Self::from_preferences_with_info(locale, M::INFO) + } + + pub(crate) const fn from_preferences_with_info( + locale: icu_locale_core::preferences::LocalePreferences, + info: DataMarkerInfo, ) -> Self { Self { language: locale.language, @@ -290,7 +298,7 @@ impl DataLocale { region: match (locale.region, locale.ue_region) { (Some(_), Some(r)) if matches!( - M::INFO.fallback_config.priority, + info.fallback_config.priority, LocaleFallbackPriority::Region ) => { diff --git a/tutorials/data_management.md b/tutorials/data_management.md index fdee122a3a2..552b260472c 100644 --- a/tutorials/data_management.md +++ b/tutorials/data_management.md @@ -173,7 +173,7 @@ fn main() { let dtf = DateTimeFormatter::try_new_with_buffer_provider( &buffer_provider, - &LOCALE.into(), + LOCALE.into(), YMDT::medium() ) .expect("blob should contain required markers and `ja` data"); @@ -226,7 +226,7 @@ fn main() { let dtf = FixedCalendarDateTimeFormatter::::try_new_with_buffer_provider( &buffer_provider, - &LOCALE.into(), + LOCALE.into(), YMDT::medium(), ) .expect("blob should contain required data"); diff --git a/tutorials/intro.md b/tutorials/intro.md index 2dab5163b14..9ce43011aec 100644 --- a/tutorials/intro.md +++ b/tutorials/intro.md @@ -114,7 +114,7 @@ const LOCALE: Locale = locale!("ja"); // let's try some other language fn main() { let dtf = DateTimeFormatter::try_new( - &LOCALE.into(), + LOCALE.into(), YMDT::medium(), ) .expect("ja data should be available"); diff --git a/tutorials/intro_interactive.md b/tutorials/intro_interactive.md index 51440588a8a..c930fb1cd0f 100644 --- a/tutorials/intro_interactive.md +++ b/tutorials/intro_interactive.md @@ -164,7 +164,7 @@ let iso_date = get_current_date(); // Create and use an ICU4X date formatter: let date_formatter = DateTimeFormatter::try_new( - &(&locale).into(), + (&locale).into(), YMD::medium(), ) .expect("should have data for specified locale"); diff --git a/tutorials/rust/buffer/src/main.rs b/tutorials/rust/buffer/src/main.rs index 71c6e32c86e..5b83a653270 100644 --- a/tutorials/rust/buffer/src/main.rs +++ b/tutorials/rust/buffer/src/main.rs @@ -14,7 +14,7 @@ //! For more information, see the tutorial [cargo.md](../../cargo.md). use icu::calendar::{DateTime, Gregorian}; -use icu::datetime::{FixedCalendarDateTimeFormatter, fieldsets::YMDT, options::NeoSkeletonLength}; +use icu::datetime::{FixedCalendarDateTimeFormatter, fieldsets::YMDT}; use icu::locale::locale; use icu_provider_blob::BlobDataProvider; @@ -27,7 +27,7 @@ fn main() { let formatter = FixedCalendarDateTimeFormatter::::try_new_with_buffer_provider( &provider, - &locale!("my").into(), + locale!("my").into(), YMDT::medium(), ) .expect("locale 'my' should be present in compiled data");