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 #[diplomat::bridge] 6 #[diplomat::abi_rename = "icu4x_{0}_mv1"] 7 #[diplomat::attr(auto, namespace = "icu4x")] 8 pub mod ffi { 9 use alloc::boxed::Box; 10 use icu_datetime::fieldsets::{zone::GenericShort, Combo, YMDT}; 11 #[cfg(any(feature = "compiled_data", feature = "buffer_provider"))] 12 use icu_datetime::options::Length; 13 14 #[cfg(feature = "buffer_provider")] 15 use crate::provider::ffi::DataProvider; 16 use crate::{ 17 date::ffi::{Date, IsoDate}, 18 errors::ffi::DateTimeFormatError, 19 time::ffi::Time, 20 timezone::ffi::TimeZoneInfo, 21 }; 22 23 #[cfg(any(feature = "compiled_data", feature = "buffer_provider"))] 24 use crate::{ 25 datetime_formatter::ffi::DateTimeLength, errors::ffi::DateTimeFormatterLoadError, 26 locale_core::ffi::Locale, 27 }; 28 29 use writeable::Writeable; 30 31 #[diplomat::opaque] 32 /// An object capable of formatting a date time with time zone to a string. 33 #[diplomat::rust_link(icu::datetime::FixedCalendarDateTimeFormatter, Struct)] 34 #[diplomat::rust_link(icu::datetime::fieldsets::YMDT, Struct, compact)] 35 #[diplomat::rust_link(icu::datetime::fieldsets::zone::GenericShort, Struct, compact)] 36 pub struct GregorianZonedDateTimeFormatter( 37 pub icu_datetime::FixedCalendarDateTimeFormatter< 38 icu_calendar::Gregorian, 39 Combo<YMDT, GenericShort>, 40 >, 41 ); 42 43 impl GregorianZonedDateTimeFormatter { 44 /// Creates a new [`GregorianZonedDateTimeFormatter`] from locale data using compiled data. 45 /// 46 /// This function has `date_length` and `time_length` arguments and uses default options 47 /// for the time zone. 48 #[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor = "with_length")] 49 #[diplomat::demo(default_constructor)] 50 #[cfg(feature = "compiled_data")] 51 #[diplomat::rust_link(icu::datetime::FixedCalendarDateTimeFormatter::try_new, FnInStruct)] create_with_length( locale: &Locale, length: DateTimeLength, ) -> Result<Box<GregorianZonedDateTimeFormatter>, DateTimeFormatterLoadError>52 pub fn create_with_length( 53 locale: &Locale, 54 length: DateTimeLength, 55 ) -> Result<Box<GregorianZonedDateTimeFormatter>, DateTimeFormatterLoadError> { 56 let prefs = (&locale.0).into(); 57 let options = YMDT::with_length(Length::from(length)).zone(GenericShort); 58 59 Ok(Box::new(GregorianZonedDateTimeFormatter( 60 icu_datetime::FixedCalendarDateTimeFormatter::try_new(prefs, options)?, 61 ))) 62 } 63 /// Creates a new [`GregorianZonedDateTimeFormatter`] from locale data using a particular data source. 64 /// 65 /// This function has `date_length` and `time_length` arguments and uses default options 66 /// for the time zone. 67 #[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor = "with_length_and_provider")] 68 #[cfg(feature = "buffer_provider")] 69 #[diplomat::rust_link(icu::datetime::FixedCalendarDateTimeFormatter::try_new, FnInStruct)] create_with_length_and_provider( provider: &DataProvider, locale: &Locale, length: DateTimeLength, ) -> Result<Box<GregorianZonedDateTimeFormatter>, DateTimeFormatterLoadError>70 pub fn create_with_length_and_provider( 71 provider: &DataProvider, 72 locale: &Locale, 73 length: DateTimeLength, 74 ) -> Result<Box<GregorianZonedDateTimeFormatter>, DateTimeFormatterLoadError> { 75 let prefs = (&locale.0).into(); 76 let options = YMDT::with_length(Length::from(length)).zone(GenericShort); 77 78 Ok(Box::new(GregorianZonedDateTimeFormatter( 79 icu_datetime::FixedCalendarDateTimeFormatter::try_new_with_buffer_provider( 80 provider.get()?, 81 prefs, 82 options, 83 )?, 84 ))) 85 } 86 /// Formats an [`IsoDate`] a [`Time`], and a [`TimeZoneInfo`] to a string. 87 #[diplomat::rust_link(icu::datetime::FixedCalendarDateTimeFormatter::format, FnInStruct)] 88 #[diplomat::rust_link(icu::datetime::FormattedDateTime, Struct, hidden)] format_iso( &self, date: &IsoDate, time: &Time, zone: &TimeZoneInfo, write: &mut diplomat_runtime::DiplomatWrite, ) -> Result<(), DateTimeFormatError>89 pub fn format_iso( 90 &self, 91 date: &IsoDate, 92 time: &Time, 93 zone: &TimeZoneInfo, 94 write: &mut diplomat_runtime::DiplomatWrite, 95 ) -> Result<(), DateTimeFormatError> { 96 let zdt = icu_time::ZonedDateTime { 97 date: icu_calendar::Date::new_from_iso(date.0, icu_calendar::Gregorian), 98 time: time.0, 99 zone: zone 100 .time_zone_id 101 .with_offset(zone.offset) 102 .at_time((date.0, time.0)) 103 .with_zone_variant( 104 zone.zone_variant 105 .ok_or(DateTimeFormatError::ZoneInfoMissingFields)?, 106 ), 107 }; 108 let _infallible = self.0.format(&zdt).write_to(write); 109 Ok(()) 110 } 111 } 112 113 #[diplomat::opaque] 114 /// An object capable of formatting a date time with time zone to a string. 115 #[diplomat::rust_link(icu::datetime::DateTimeFormatter, Struct)] 116 #[diplomat::rust_link(icu::datetime::fieldsets::YMDT, Struct, compact)] 117 #[diplomat::rust_link(icu::datetime::fieldsets::zone::GenericShort, Struct, compact)] 118 pub struct ZonedDateTimeFormatter( 119 pub icu_datetime::DateTimeFormatter<Combo<YMDT, GenericShort>>, 120 ); 121 122 impl ZonedDateTimeFormatter { 123 /// Creates a new [`ZonedDateTimeFormatter`] from locale data using compiled data. 124 /// 125 /// This function has `date_length` and `time_length` arguments and uses default options 126 /// for the time zone. 127 #[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor = "with_length")] 128 #[diplomat::demo(default_constructor)] 129 #[cfg(feature = "compiled_data")] 130 #[diplomat::rust_link(icu::datetime::DateTimeFormatter::try_new, FnInStruct)] create_with_length( locale: &Locale, length: DateTimeLength, ) -> Result<Box<ZonedDateTimeFormatter>, DateTimeFormatterLoadError>131 pub fn create_with_length( 132 locale: &Locale, 133 length: DateTimeLength, 134 ) -> Result<Box<ZonedDateTimeFormatter>, DateTimeFormatterLoadError> { 135 let prefs = (&locale.0).into(); 136 let options = YMDT::with_length(Length::from(length)).zone(GenericShort); 137 138 Ok(Box::new(ZonedDateTimeFormatter( 139 icu_datetime::DateTimeFormatter::try_new(prefs, options)?, 140 ))) 141 } 142 /// Creates a new [`ZonedDateTimeFormatter`] from locale data using a particular data source. 143 /// 144 /// This function has `date_length` and `time_length` arguments and uses default options 145 /// for the time zone. 146 #[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor = "with_length_and_provider")] 147 #[cfg(feature = "buffer_provider")] 148 #[diplomat::rust_link(icu::datetime::DateTimeFormatter::try_new, FnInStruct)] create_with_length_and_provider( provider: &DataProvider, locale: &Locale, length: DateTimeLength, ) -> Result<Box<ZonedDateTimeFormatter>, DateTimeFormatterLoadError>149 pub fn create_with_length_and_provider( 150 provider: &DataProvider, 151 locale: &Locale, 152 length: DateTimeLength, 153 ) -> Result<Box<ZonedDateTimeFormatter>, DateTimeFormatterLoadError> { 154 let prefs = (&locale.0).into(); 155 let options = YMDT::with_length(Length::from(length)).zone(GenericShort); 156 157 Ok(Box::new(ZonedDateTimeFormatter( 158 icu_datetime::DateTimeFormatter::try_new_with_buffer_provider( 159 provider.get()?, 160 prefs, 161 options, 162 )?, 163 ))) 164 } 165 /// Formats a [`Date`] a [`Time`], and a [`TimeZoneInfo`] to a string. 166 #[diplomat::rust_link(icu::datetime::DateTimeFormatter::format, FnInStruct)] 167 #[diplomat::rust_link(icu::datetime::FormattedDateTime, Struct, hidden)] format( &self, date: &Date, time: &Time, zone: &TimeZoneInfo, write: &mut diplomat_runtime::DiplomatWrite, ) -> Result<(), DateTimeFormatError>168 pub fn format( 169 &self, 170 date: &Date, 171 time: &Time, 172 zone: &TimeZoneInfo, 173 write: &mut diplomat_runtime::DiplomatWrite, 174 ) -> Result<(), DateTimeFormatError> { 175 let zdt = icu_time::ZonedDateTime { 176 date: date.0.wrap_calendar_in_ref(), 177 time: time.0, 178 zone: zone 179 .time_zone_id 180 .with_offset(zone.offset) 181 .at_time((date.0.to_iso(), time.0)) 182 .with_zone_variant( 183 zone.zone_variant 184 .ok_or(DateTimeFormatError::ZoneInfoMissingFields)?, 185 ), 186 }; 187 let _infallible = self.0.format(&zdt).write_to(write); 188 Ok(()) 189 } 190 191 /// Formats an [`IsoDate`] a [`Time`], and a [`TimeZoneInfo`] to a string. 192 #[diplomat::rust_link(icu::datetime::DateTimeFormatter::format, FnInStruct)] 193 #[diplomat::rust_link(icu::datetime::FormattedDateTime, Struct, hidden)] format_iso( &self, date: &IsoDate, time: &Time, zone: &TimeZoneInfo, write: &mut diplomat_runtime::DiplomatWrite, ) -> Result<(), DateTimeFormatError>194 pub fn format_iso( 195 &self, 196 date: &IsoDate, 197 time: &Time, 198 zone: &TimeZoneInfo, 199 write: &mut diplomat_runtime::DiplomatWrite, 200 ) -> Result<(), DateTimeFormatError> { 201 let zdt = icu_time::ZonedDateTime { 202 date: date.0, 203 time: time.0, 204 zone: zone 205 .time_zone_id 206 .with_offset(zone.offset) 207 .at_time((date.0, time.0)) 208 .with_zone_variant( 209 zone.zone_variant 210 .ok_or(DateTimeFormatError::ZoneInfoMissingFields)?, 211 ), 212 }; 213 let _infallible = self.0.format(&zdt).write_to(write); 214 Ok(()) 215 } 216 } 217 } 218