Bug 1910110 - Return early when channel URI is void r=rpl a=Aryx
[gecko.git] / intl / icu_capi / src / datetime.rs
blob4d40b38c053f33d99f1cff193ccfcee69df09743
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 ).
5 #[diplomat::bridge]
6 pub mod ffi {
7     use alloc::boxed::Box;
8     use alloc::sync::Arc;
9     use core::convert::TryInto;
10     use core::fmt::Write;
12     use icu_calendar::{AnyCalendar, DateTime, Iso, Time};
13     use tinystr::TinyAsciiStr;
15     use crate::calendar::ffi::ICU4XCalendar;
16     use crate::date::ffi::{ICU4XDate, ICU4XIsoDate, ICU4XIsoWeekday};
17     use crate::errors::ffi::ICU4XError;
18     use crate::time::ffi::ICU4XTime;
20     #[cfg(feature = "icu_calendar")]
21     use crate::week::ffi::ICU4XWeekCalculator;
23     #[diplomat::opaque]
24     /// An ICU4X DateTime object capable of containing a ISO-8601 date and time.
25     #[diplomat::rust_link(icu::calendar::DateTime, Struct)]
26     pub struct ICU4XIsoDateTime(pub DateTime<Iso>);
28     impl ICU4XIsoDateTime {
29         /// Creates a new [`ICU4XIsoDateTime`] from the specified date and time.
30         #[diplomat::rust_link(icu::calendar::DateTime::try_new_iso_datetime, FnInStruct)]
31         #[diplomat::attr(all(supports = constructors, supports = fallible_constructors), constructor)]
32         pub fn create(
33             year: i32,
34             month: u8,
35             day: u8,
36             hour: u8,
37             minute: u8,
38             second: u8,
39             nanosecond: u32,
40         ) -> Result<Box<ICU4XIsoDateTime>, ICU4XError> {
41             let mut dt = DateTime::try_new_iso_datetime(year, month, day, hour, minute, second)?;
42             dt.time.nanosecond = nanosecond.try_into()?;
43             Ok(Box::new(ICU4XIsoDateTime(dt)))
44         }
46         /// Creates a new [`ICU4XIsoDateTime`] from an [`ICU4XIsoDate`] and [`ICU4XTime`] object
47         #[diplomat::rust_link(icu::calendar::DateTime::new, FnInStruct)]
48         #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "from_date_and_time")]
49         pub fn crate_from_date_and_time(
50             date: &ICU4XIsoDate,
51             time: &ICU4XTime,
52         ) -> Box<ICU4XIsoDateTime> {
53             let dt = DateTime::new(date.0, time.0);
54             Box::new(ICU4XIsoDateTime(dt))
55         }
57         /// Creates a new [`ICU4XIsoDateTime`] of midnight on January 1, 1970
58         #[diplomat::rust_link(icu::calendar::DateTime::local_unix_epoch, FnInStruct)]
59         #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "local_unix_epoch")]
60         pub fn local_unix_epoch() -> Box<ICU4XIsoDateTime> {
61             let dt = DateTime::local_unix_epoch();
62             Box::new(ICU4XIsoDateTime(dt))
63         }
65         /// Construct from the minutes since the local unix epoch for this date (Jan 1 1970, 00:00)
66         #[diplomat::rust_link(
67             icu::calendar::DateTime::from_minutes_since_local_unix_epoch,
68             FnInStruct
69         )]
70         #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "from_minutes_since_local_unix_epoch")]
71         pub fn create_from_minutes_since_local_unix_epoch(minutes: i32) -> Box<ICU4XIsoDateTime> {
72             Box::new(ICU4XIsoDateTime(
73                 DateTime::from_minutes_since_local_unix_epoch(minutes),
74             ))
75         }
77         /// Gets the date contained in this object
78         #[diplomat::rust_link(icu::calendar::DateTime::date, StructField)]
79         #[diplomat::attr(supports = accessors, getter)]
80         pub fn date(&self) -> Box<ICU4XIsoDate> {
81             Box::new(ICU4XIsoDate(self.0.date))
82         }
84         /// Gets the time contained in this object
85         #[diplomat::rust_link(icu::calendar::DateTime::time, StructField)]
86         #[diplomat::attr(supports = accessors, getter)]
87         pub fn time(&self) -> Box<ICU4XTime> {
88             Box::new(ICU4XTime(self.0.time))
89         }
91         /// Converts this to an [`ICU4XDateTime`] capable of being mixed with dates of
92         /// other calendars
93         #[diplomat::rust_link(icu::calendar::DateTime::to_any, FnInStruct)]
94         #[diplomat::rust_link(icu::calendar::DateTime::new_from_iso, FnInStruct, hidden)]
95         pub fn to_any(&self) -> Box<ICU4XDateTime> {
96             Box::new(ICU4XDateTime(self.0.to_any().wrap_calendar_in_arc()))
97         }
99         /// Gets the minutes since the local unix epoch for this date (Jan 1 1970, 00:00)
100         #[diplomat::rust_link(icu::calendar::DateTime::minutes_since_local_unix_epoch, FnInStruct)]
101         #[diplomat::attr(supports = accessors, getter)]
102         pub fn minutes_since_local_unix_epoch(&self) -> i32 {
103             self.0.minutes_since_local_unix_epoch()
104         }
106         /// Convert this datetime to one in a different calendar
107         #[diplomat::rust_link(icu::calendar::DateTime::to_calendar, FnInStruct)]
108         pub fn to_calendar(&self, calendar: &ICU4XCalendar) -> Box<ICU4XDateTime> {
109             Box::new(ICU4XDateTime(self.0.to_calendar(calendar.0.clone())))
110         }
112         /// Returns the hour in this time
113         #[diplomat::rust_link(icu::calendar::Time::hour, StructField)]
114         #[diplomat::attr(supports = accessors, getter)]
115         pub fn hour(&self) -> u8 {
116             self.0.time.hour.into()
117         }
118         /// Returns the minute in this time
119         #[diplomat::rust_link(icu::calendar::Time::minute, StructField)]
120         #[diplomat::attr(supports = accessors, getter)]
121         pub fn minute(&self) -> u8 {
122             self.0.time.minute.into()
123         }
124         /// Returns the second in this time
125         #[diplomat::rust_link(icu::calendar::Time::second, StructField)]
126         #[diplomat::attr(supports = accessors, getter)]
127         pub fn second(&self) -> u8 {
128             self.0.time.second.into()
129         }
130         /// Returns the nanosecond in this time
131         #[diplomat::rust_link(icu::calendar::Time::nanosecond, StructField)]
132         #[diplomat::attr(supports = accessors, getter)]
133         pub fn nanosecond(&self) -> u32 {
134             self.0.time.nanosecond.into()
135         }
137         /// Returns the 1-indexed day in the year for this date
138         #[diplomat::rust_link(icu::calendar::Date::day_of_year_info, FnInStruct)]
139         #[diplomat::attr(supports = accessors, getter)]
140         pub fn day_of_year(&self) -> u16 {
141             self.0.date.day_of_year_info().day_of_year
142         }
144         /// Returns the 1-indexed day in the month for this date
145         #[diplomat::rust_link(icu::calendar::Date::day_of_month, FnInStruct)]
146         #[diplomat::attr(supports = accessors, getter)]
147         pub fn day_of_month(&self) -> u32 {
148             self.0.date.day_of_month().0
149         }
151         /// Returns the day in the week for this day
152         #[diplomat::rust_link(icu::calendar::Date::day_of_week, FnInStruct)]
153         #[diplomat::attr(supports = accessors, getter)]
154         pub fn day_of_week(&self) -> ICU4XIsoWeekday {
155             self.0.date.day_of_week().into()
156         }
158         /// Returns the week number in this month, 1-indexed, based on what
159         /// is considered the first day of the week (often a locale preference).
160         ///
161         /// `first_weekday` can be obtained via `first_weekday()` on [`ICU4XWeekCalculator`]
162         #[diplomat::rust_link(icu::calendar::Date::week_of_month, FnInStruct)]
163         #[diplomat::rust_link(
164             icu::calendar::week::WeekCalculator::week_of_month,
165             FnInStruct,
166             hidden
167         )]
168         pub fn week_of_month(&self, first_weekday: ICU4XIsoWeekday) -> u32 {
169             self.0.date.week_of_month(first_weekday.into()).0
170         }
172         /// Returns the week number in this year, using week data
173         #[diplomat::rust_link(icu::calendar::Date::week_of_year, FnInStruct)]
174         #[diplomat::rust_link(
175             icu::calendar::week::WeekCalculator::week_of_year,
176             FnInStruct,
177             hidden
178         )]
179         #[cfg(feature = "icu_calendar")]
180         pub fn week_of_year(
181             &self,
182             calculator: &ICU4XWeekCalculator,
183         ) -> Result<crate::week::ffi::ICU4XWeekOf, ICU4XError> {
184             Ok(self.0.date.week_of_year(&calculator.0)?.into())
185         }
187         /// Returns 1-indexed number of the month of this date in its year
188         #[diplomat::rust_link(icu::calendar::Date::month, FnInStruct)]
189         #[diplomat::attr(supports = accessors, getter)]
190         pub fn month(&self) -> u32 {
191             self.0.date.month().ordinal
192         }
194         /// Returns the year number for this date
195         #[diplomat::rust_link(icu::calendar::Date::year, FnInStruct)]
196         #[diplomat::attr(supports = accessors, getter)]
197         pub fn year(&self) -> i32 {
198             self.0.date.year().number
199         }
201         /// Returns whether this date is in a leap year
202         #[diplomat::rust_link(icu::calendar::Date::is_in_leap_year, FnInStruct)]
203         #[diplomat::attr(supports = accessors, getter)]
204         pub fn is_in_leap_year(&self) -> bool {
205             self.0.date.is_in_leap_year()
206         }
208         /// Returns the number of months in the year represented by this date
209         #[diplomat::rust_link(icu::calendar::Date::months_in_year, FnInStruct)]
210         #[diplomat::attr(supports = accessors, getter)]
211         pub fn months_in_year(&self) -> u8 {
212             self.0.date.months_in_year()
213         }
215         /// Returns the number of days in the month represented by this date
216         #[diplomat::rust_link(icu::calendar::Date::days_in_month, FnInStruct)]
217         #[diplomat::attr(supports = accessors, getter)]
218         pub fn days_in_month(&self) -> u8 {
219             self.0.date.days_in_month()
220         }
222         /// Returns the number of days in the year represented by this date
223         #[diplomat::rust_link(icu::calendar::Date::days_in_year, FnInStruct)]
224         #[diplomat::attr(supports = accessors, getter)]
225         pub fn days_in_year(&self) -> u16 {
226             self.0.date.days_in_year()
227         }
228     }
230     #[diplomat::opaque]
231     /// An ICU4X DateTime object capable of containing a date and time for any calendar.
232     #[diplomat::rust_link(icu::calendar::DateTime, Struct)]
233     pub struct ICU4XDateTime(pub DateTime<Arc<AnyCalendar>>);
235     impl ICU4XDateTime {
236         /// Creates a new [`ICU4XDateTime`] representing the ISO date and time
237         /// given but in a given calendar
238         #[diplomat::rust_link(icu::DateTime::new_from_iso, FnInStruct)]
239         #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "from_iso_in_calendar")]
240         #[allow(clippy::too_many_arguments)]
241         pub fn create_from_iso_in_calendar(
242             year: i32,
243             month: u8,
244             day: u8,
245             hour: u8,
246             minute: u8,
247             second: u8,
248             nanosecond: u32,
249             calendar: &ICU4XCalendar,
250         ) -> Result<Box<ICU4XDateTime>, ICU4XError> {
251             let cal = calendar.0.clone();
252             let mut dt = DateTime::try_new_iso_datetime(year, month, day, hour, minute, second)?;
253             dt.time.nanosecond = nanosecond.try_into()?;
254             Ok(Box::new(ICU4XDateTime(dt.to_calendar(cal))))
255         }
256         /// Creates a new [`ICU4XDateTime`] from the given codes, which are interpreted in the given calendar system
257         #[diplomat::rust_link(icu::calendar::DateTime::try_new_from_codes, FnInStruct)]
258         #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "from_codes_in_calendar")]
259         #[allow(clippy::too_many_arguments)]
260         pub fn create_from_codes_in_calendar(
261             era_code: &DiplomatStr,
262             year: i32,
263             month_code: &DiplomatStr,
264             day: u8,
265             hour: u8,
266             minute: u8,
267             second: u8,
268             nanosecond: u32,
269             calendar: &ICU4XCalendar,
270         ) -> Result<Box<ICU4XDateTime>, ICU4XError> {
271             let era = TinyAsciiStr::from_bytes(era_code)
272                 .map_err(|_| ICU4XError::CalendarUnknownEraError)?
273                 .into();
274             let month = TinyAsciiStr::from_bytes(month_code)
275                 .map_err(|_| ICU4XError::CalendarUnknownMonthCodeError)?
276                 .into();
277             let cal = calendar.0.clone();
278             let hour = hour.try_into()?;
279             let minute = minute.try_into()?;
280             let second = second.try_into()?;
281             let nanosecond = nanosecond.try_into()?;
282             let time = Time {
283                 hour,
284                 minute,
285                 second,
286                 nanosecond,
287             };
288             Ok(Box::new(ICU4XDateTime(DateTime::try_new_from_codes(
289                 era, year, month, day, time, cal,
290             )?)))
291         }
292         /// Creates a new [`ICU4XDateTime`] from an [`ICU4XDate`] and [`ICU4XTime`] object
293         #[diplomat::rust_link(icu::calendar::DateTime::new, FnInStruct)]
294         #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "from_date_and_time")]
295         pub fn create_from_date_and_time(date: &ICU4XDate, time: &ICU4XTime) -> Box<ICU4XDateTime> {
296             let dt = DateTime::new(date.0.clone(), time.0);
297             Box::new(ICU4XDateTime(dt))
298         }
300         /// Gets a copy of the date contained in this object
301         #[diplomat::rust_link(icu::calendar::DateTime::date, StructField)]
302         #[diplomat::attr(supports = accessors, getter)]
303         pub fn date(&self) -> Box<ICU4XDate> {
304             Box::new(ICU4XDate(self.0.date.clone()))
305         }
307         /// Gets the time contained in this object
308         #[diplomat::rust_link(icu::calendar::DateTime::time, StructField)]
309         #[diplomat::attr(supports = accessors, getter)]
310         pub fn time(&self) -> Box<ICU4XTime> {
311             Box::new(ICU4XTime(self.0.time))
312         }
314         /// Converts this date to ISO
315         #[diplomat::rust_link(icu::calendar::DateTime::to_iso, FnInStruct)]
316         pub fn to_iso(&self) -> Box<ICU4XIsoDateTime> {
317             Box::new(ICU4XIsoDateTime(self.0.to_iso()))
318         }
320         /// Convert this datetime to one in a different calendar
321         #[diplomat::rust_link(icu::calendar::DateTime::to_calendar, FnInStruct)]
322         pub fn to_calendar(&self, calendar: &ICU4XCalendar) -> Box<ICU4XDateTime> {
323             Box::new(ICU4XDateTime(self.0.to_calendar(calendar.0.clone())))
324         }
326         /// Returns the hour in this time
327         #[diplomat::rust_link(icu::calendar::Time::hour, StructField)]
328         #[diplomat::attr(supports = accessors, getter)]
329         pub fn hour(&self) -> u8 {
330             self.0.time.hour.into()
331         }
332         /// Returns the minute in this time
333         #[diplomat::rust_link(icu::calendar::Time::minute, StructField)]
334         #[diplomat::attr(supports = accessors, getter)]
335         pub fn minute(&self) -> u8 {
336             self.0.time.minute.into()
337         }
338         /// Returns the second in this time
339         #[diplomat::rust_link(icu::calendar::Time::second, StructField)]
340         #[diplomat::attr(supports = accessors, getter)]
341         pub fn second(&self) -> u8 {
342             self.0.time.second.into()
343         }
344         /// Returns the nanosecond in this time
345         #[diplomat::rust_link(icu::calendar::Time::nanosecond, StructField)]
346         #[diplomat::attr(supports = accessors, getter)]
347         pub fn nanosecond(&self) -> u32 {
348             self.0.time.nanosecond.into()
349         }
351         /// Returns the 1-indexed day in the year for this date
352         #[diplomat::rust_link(icu::calendar::Date::day_of_year_info, FnInStruct)]
353         #[diplomat::attr(supports = accessors, getter)]
354         pub fn day_of_year(&self) -> u16 {
355             self.0.date.day_of_year_info().day_of_year
356         }
358         /// Returns the 1-indexed day in the month for this date
359         #[diplomat::rust_link(icu::calendar::Date::day_of_month, FnInStruct)]
360         #[diplomat::attr(supports = accessors, getter)]
361         pub fn day_of_month(&self) -> u32 {
362             self.0.date.day_of_month().0
363         }
365         /// Returns the day in the week for this day
366         #[diplomat::rust_link(icu::calendar::Date::day_of_week, FnInStruct)]
367         #[diplomat::attr(supports = accessors, getter)]
368         pub fn day_of_week(&self) -> ICU4XIsoWeekday {
369             self.0.date.day_of_week().into()
370         }
372         /// Returns the week number in this month, 1-indexed, based on what
373         /// is considered the first day of the week (often a locale preference).
374         ///
375         /// `first_weekday` can be obtained via `first_weekday()` on [`ICU4XWeekCalculator`]
376         #[diplomat::rust_link(icu::calendar::Date::week_of_month, FnInStruct)]
377         #[diplomat::rust_link(
378             icu::calendar::week::WeekCalculator::week_of_month,
379             FnInStruct,
380             hidden
381         )]
382         pub fn week_of_month(&self, first_weekday: ICU4XIsoWeekday) -> u32 {
383             self.0.date.week_of_month(first_weekday.into()).0
384         }
386         /// Returns the week number in this year, using week data
387         #[diplomat::rust_link(icu::calendar::Date::week_of_year, FnInStruct)]
388         #[diplomat::rust_link(
389             icu::calendar::week::WeekCalculator::week_of_year,
390             FnInStruct,
391             hidden
392         )]
393         #[cfg(feature = "icu_calendar")]
394         pub fn week_of_year(
395             &self,
396             calculator: &ICU4XWeekCalculator,
397         ) -> Result<crate::week::ffi::ICU4XWeekOf, ICU4XError> {
398             Ok(self.0.date.week_of_year(&calculator.0)?.into())
399         }
401         /// Returns 1-indexed number of the month of this date in its year
402         ///
403         /// Note that for lunar calendars this may not lead to the same month
404         /// having the same ordinal month across years; use month_code if you care
405         /// about month identity.
406         #[diplomat::rust_link(icu::calendar::Date::month, FnInStruct)]
407         #[diplomat::attr(supports = accessors, getter)]
408         pub fn ordinal_month(&self) -> u32 {
409             self.0.date.month().ordinal
410         }
412         /// Returns the month code for this date. Typically something
413         /// like "M01", "M02", but can be more complicated for lunar calendars.
414         #[diplomat::rust_link(icu::calendar::Date::month, FnInStruct)]
415         #[diplomat::attr(supports = accessors, getter)]
416         pub fn month_code(
417             &self,
418             write: &mut diplomat_runtime::DiplomatWriteable,
419         ) -> Result<(), ICU4XError> {
420             let code = self.0.date.month().code;
421             write.write_str(&code.0)?;
422             Ok(())
423         }
425         /// Returns the year number in the current era for this date
426         #[diplomat::rust_link(icu::calendar::Date::year, FnInStruct)]
427         #[diplomat::attr(supports = accessors, getter)]
428         pub fn year_in_era(&self) -> i32 {
429             self.0.date.year().number
430         }
432         /// Returns the era for this date,
433         #[diplomat::rust_link(icu::calendar::Date::year, FnInStruct)]
434         #[diplomat::attr(supports = accessors, getter)]
435         pub fn era(
436             &self,
437             write: &mut diplomat_runtime::DiplomatWriteable,
438         ) -> Result<(), ICU4XError> {
439             let era = self.0.date.year().era;
440             write.write_str(&era.0)?;
441             Ok(())
442         }
444         /// Returns the number of months in the year represented by this date
445         #[diplomat::rust_link(icu::calendar::Date::months_in_year, FnInStruct)]
446         #[diplomat::attr(supports = accessors, getter)]
447         pub fn months_in_year(&self) -> u8 {
448             self.0.date.months_in_year()
449         }
451         /// Returns the number of days in the month represented by this date
452         #[diplomat::rust_link(icu::calendar::Date::days_in_month, FnInStruct)]
453         #[diplomat::attr(supports = accessors, getter)]
454         pub fn days_in_month(&self) -> u8 {
455             self.0.date.days_in_month()
456         }
458         /// Returns the number of days in the year represented by this date
459         #[diplomat::rust_link(icu::calendar::Date::days_in_year, FnInStruct)]
460         #[diplomat::attr(supports = accessors, getter)]
461         pub fn days_in_year(&self) -> u16 {
462             self.0.date.days_in_year()
463         }
465         /// Returns the [`ICU4XCalendar`] object backing this date
466         #[diplomat::rust_link(icu::calendar::Date::calendar, FnInStruct)]
467         #[diplomat::rust_link(icu::calendar::Date::calendar_wrapper, FnInStruct, hidden)]
468         #[diplomat::attr(supports = accessors, getter)]
469         pub fn calendar(&self) -> Box<ICU4XCalendar> {
470             Box::new(ICU4XCalendar(self.0.date.calendar_wrapper().clone()))
471         }
472     }