datetime_helpers.rs (9584B)
1 // This file is part of ICU4X. For terms of use, please see the file 2 // called LICENSE at the top level of the ICU4X source tree 3 // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). 4 5 #![allow(dead_code)] // features in here are a mess 6 7 use alloc::boxed::Box; 8 use icu_calendar::Gregorian; 9 use icu_datetime::{ 10 fieldsets::builder::BuilderError, fieldsets::enums::*, fieldsets::Combo, pattern::*, 11 scaffold::*, DateTimeFormatter, DateTimeFormatterLoadError, FixedCalendarDateTimeFormatter, 12 }; 13 14 pub(crate) fn map_or_default<Input, Output>(input: Option<Input>) -> Output 15 where 16 Output: From<Input> + Default, 17 { 18 input.map(Output::from).unwrap_or_default() 19 } 20 21 pub(super) fn date_formatter_with_zone<Zone>( 22 formatter: &DateTimeFormatter<DateFieldSet>, 23 locale: &crate::unstable::locale_core::ffi::Locale, 24 zone: Zone, 25 load: impl FnOnce( 26 &mut DateTimeNames<Combo<DateFieldSet, Zone>>, 27 ) -> Result<(), crate::unstable::errors::ffi::DateTimeFormatterLoadError>, 28 to_formatter: impl FnOnce( 29 DateTimeNames<Combo<DateFieldSet, Zone>>, 30 Combo<DateFieldSet, Zone>, 31 ) -> Result< 32 DateTimeFormatter<Combo<DateFieldSet, Zone>>, 33 ( 34 DateTimeFormatterLoadError, 35 DateTimeNames<Combo<DateFieldSet, Zone>>, 36 ), 37 >, 38 ) -> Result< 39 Box<crate::unstable::zoned_date_formatter::ffi::ZonedDateFormatter>, 40 crate::unstable::errors::ffi::DateTimeFormatterLoadError, 41 > 42 where 43 Zone: DateTimeMarkers + ZoneMarkers, 44 <Zone as DateTimeMarkers>::Z: ZoneMarkers, 45 Combo<DateFieldSet, Zone>: DateTimeNamesFrom<DateFieldSet>, 46 ZonedDateFieldSet: DateTimeNamesFrom<Combo<DateFieldSet, Zone>>, 47 { 48 let prefs = (&locale.0).into(); 49 let mut names = DateTimeNames::from_formatter(prefs, formatter.clone()) 50 .cast_into_fset::<Combo<DateFieldSet, Zone>>(); 51 load(&mut names)?; 52 let field_set = formatter 53 .to_field_set_builder() 54 .build_date() 55 .map_err(|e| match e { 56 BuilderError::InvalidDateFields => { 57 // This can fail if the date fields are for a calendar period 58 crate::unstable::errors::ffi::DateTimeFormatterLoadError::InvalidDateFields 59 } 60 _ => { 61 debug_assert!(false, "should be infallible, but got: {e:?}"); 62 crate::unstable::errors::ffi::DateTimeFormatterLoadError::Unknown 63 } 64 })? 65 .with_zone(zone); 66 let formatter = to_formatter(names, field_set) 67 // This can fail if the locale doesn't match and the fields conflict 68 .map_err(|(e, _)| e)? 69 .cast_into_fset(); 70 Ok(Box::new( 71 crate::unstable::zoned_date_formatter::ffi::ZonedDateFormatter(formatter), 72 )) 73 } 74 75 pub(super) fn datetime_formatter_with_zone<Zone>( 76 formatter: &DateTimeFormatter<CompositeDateTimeFieldSet>, 77 locale: &crate::unstable::locale_core::ffi::Locale, 78 zone: Zone, 79 load: impl FnOnce( 80 &mut DateTimeNames<Combo<DateAndTimeFieldSet, Zone>>, 81 ) -> Result<(), crate::unstable::errors::ffi::DateTimeFormatterLoadError>, 82 to_formatter: impl FnOnce( 83 DateTimeNames<Combo<DateAndTimeFieldSet, Zone>>, 84 Combo<DateAndTimeFieldSet, Zone>, 85 ) -> Result< 86 DateTimeFormatter<Combo<DateAndTimeFieldSet, Zone>>, 87 ( 88 DateTimeFormatterLoadError, 89 DateTimeNames<Combo<DateAndTimeFieldSet, Zone>>, 90 ), 91 >, 92 ) -> Result< 93 Box<crate::unstable::zoned_date_time_formatter::ffi::ZonedDateTimeFormatter>, 94 crate::unstable::errors::ffi::DateTimeFormatterLoadError, 95 > 96 where 97 Zone: DateTimeMarkers + ZoneMarkers, 98 <Zone as DateTimeMarkers>::Z: ZoneMarkers, 99 Combo<DateAndTimeFieldSet, Zone>: DateTimeNamesFrom<CompositeDateTimeFieldSet>, 100 ZonedDateAndTimeFieldSet: DateTimeNamesFrom<Combo<DateAndTimeFieldSet, Zone>>, 101 { 102 let prefs = (&locale.0).into(); 103 let mut names = DateTimeNames::from_formatter(prefs, formatter.clone()) 104 .cast_into_fset::<Combo<DateAndTimeFieldSet, Zone>>(); 105 load(&mut names)?; 106 let field_set = formatter 107 .to_field_set_builder() 108 .build_date_and_time() 109 .map_err(|e| match e { 110 BuilderError::InvalidDateFields => { 111 debug_assert!(false, "fields were already validated in DateTimeFormatter"); 112 crate::unstable::errors::ffi::DateTimeFormatterLoadError::InvalidDateFields 113 } 114 _ => { 115 debug_assert!(false, "should be infallible, but got: {e:?}"); 116 crate::unstable::errors::ffi::DateTimeFormatterLoadError::Unknown 117 } 118 })? 119 .with_zone(zone); 120 let formatter = to_formatter(names, field_set) 121 // This can fail if the locale doesn't match and the fields conflict 122 .map_err(|(e, _)| e)? 123 .cast_into_fset(); 124 Ok(Box::new( 125 crate::unstable::zoned_date_time_formatter::ffi::ZonedDateTimeFormatter(formatter), 126 )) 127 } 128 129 pub(super) fn date_formatter_gregorian_with_zone<Zone>( 130 formatter: &FixedCalendarDateTimeFormatter<Gregorian, DateFieldSet>, 131 locale: &crate::unstable::locale_core::ffi::Locale, 132 zone: Zone, 133 load: impl FnOnce( 134 &mut FixedCalendarDateTimeNames<Gregorian, Combo<DateFieldSet, Zone>>, 135 ) -> Result<(), crate::unstable::errors::ffi::DateTimeFormatterLoadError>, 136 to_formatter: impl FnOnce( 137 FixedCalendarDateTimeNames<Gregorian, Combo<DateFieldSet, Zone>>, 138 Combo<DateFieldSet, Zone>, 139 ) -> Result< 140 FixedCalendarDateTimeFormatter<Gregorian, Combo<DateFieldSet, Zone>>, 141 ( 142 DateTimeFormatterLoadError, 143 FixedCalendarDateTimeNames<Gregorian, Combo<DateFieldSet, Zone>>, 144 ), 145 >, 146 ) -> Result< 147 Box<crate::unstable::zoned_date_formatter::ffi::ZonedDateFormatterGregorian>, 148 crate::unstable::errors::ffi::DateTimeFormatterLoadError, 149 > 150 where 151 Zone: DateTimeMarkers + ZoneMarkers, 152 <Zone as DateTimeMarkers>::Z: ZoneMarkers, 153 Combo<DateFieldSet, Zone>: DateTimeNamesFrom<DateFieldSet>, 154 ZonedDateFieldSet: DateTimeNamesFrom<Combo<DateFieldSet, Zone>>, 155 { 156 let prefs = (&locale.0).into(); 157 let mut names = FixedCalendarDateTimeNames::from_formatter(prefs, formatter.clone()) 158 .cast_into_fset::<Combo<DateFieldSet, Zone>>(); 159 load(&mut names)?; 160 let field_set = formatter 161 .to_field_set_builder() 162 .build_date() 163 .map_err(|e| match e { 164 BuilderError::InvalidDateFields => { 165 // This can fail if the date fields are for a calendar period 166 crate::unstable::errors::ffi::DateTimeFormatterLoadError::InvalidDateFields 167 } 168 _ => { 169 debug_assert!(false, "should be infallible, but got: {e:?}"); 170 crate::unstable::errors::ffi::DateTimeFormatterLoadError::Unknown 171 } 172 })? 173 .with_zone(zone); 174 let formatter = to_formatter(names, field_set) 175 // This can fail if the locale doesn't match and the fields conflict 176 .map_err(|(e, _)| e)? 177 .cast_into_fset(); 178 Ok(Box::new( 179 crate::unstable::zoned_date_formatter::ffi::ZonedDateFormatterGregorian(formatter), 180 )) 181 } 182 183 pub(super) fn datetime_formatter_gregorian_with_zone<Zone>( 184 formatter: &FixedCalendarDateTimeFormatter<Gregorian, CompositeDateTimeFieldSet>, 185 locale: &crate::unstable::locale_core::ffi::Locale, 186 zone: Zone, 187 load: impl FnOnce( 188 &mut FixedCalendarDateTimeNames<Gregorian, Combo<DateAndTimeFieldSet, Zone>>, 189 ) -> Result<(), crate::unstable::errors::ffi::DateTimeFormatterLoadError>, 190 to_formatter: impl FnOnce( 191 FixedCalendarDateTimeNames<Gregorian, Combo<DateAndTimeFieldSet, Zone>>, 192 Combo<DateAndTimeFieldSet, Zone>, 193 ) -> Result< 194 FixedCalendarDateTimeFormatter<Gregorian, Combo<DateAndTimeFieldSet, Zone>>, 195 ( 196 DateTimeFormatterLoadError, 197 FixedCalendarDateTimeNames<Gregorian, Combo<DateAndTimeFieldSet, Zone>>, 198 ), 199 >, 200 ) -> Result< 201 Box<crate::unstable::zoned_date_time_formatter::ffi::ZonedDateTimeFormatterGregorian>, 202 crate::unstable::errors::ffi::DateTimeFormatterLoadError, 203 > 204 where 205 Zone: DateTimeMarkers + ZoneMarkers, 206 <Zone as DateTimeMarkers>::Z: ZoneMarkers, 207 Combo<DateAndTimeFieldSet, Zone>: DateTimeNamesFrom<CompositeDateTimeFieldSet>, 208 ZonedDateAndTimeFieldSet: DateTimeNamesFrom<Combo<DateAndTimeFieldSet, Zone>>, 209 { 210 let prefs = (&locale.0).into(); 211 let mut names = FixedCalendarDateTimeNames::from_formatter(prefs, formatter.clone()) 212 .cast_into_fset::<Combo<DateAndTimeFieldSet, Zone>>(); 213 load(&mut names)?; 214 let field_set = formatter 215 .to_field_set_builder() 216 .build_date_and_time() 217 .map_err(|e| match e { 218 BuilderError::InvalidDateFields => { 219 debug_assert!(false, "fields were already validated in DateTimeFormatter"); 220 crate::unstable::errors::ffi::DateTimeFormatterLoadError::InvalidDateFields 221 } 222 _ => { 223 debug_assert!(false, "should be infallible, but got: {e:?}"); 224 crate::unstable::errors::ffi::DateTimeFormatterLoadError::Unknown 225 } 226 })? 227 .with_zone(zone); 228 let formatter = to_formatter(names, field_set) 229 // This can fail if the locale doesn't match and the fields conflict 230 .map_err(|(e, _)| e)? 231 .cast_into_fset(); 232 Ok(Box::new( 233 crate::unstable::zoned_date_time_formatter::ffi::ZonedDateTimeFormatterGregorian(formatter), 234 )) 235 }