Backed out changeset ef158dc7becf (bug 1915433) for causing xpcshell failures. CLOSED...
[gecko.git] / intl / icu_capi / src / date.rs
blob09313a664f957289979fe6b49ab4bd93b8363831
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::fmt::Write;
10     use icu_calendar::types::IsoWeekday;
11     use icu_calendar::AnyCalendar;
12     use icu_calendar::{Date, Iso};
13     use tinystr::TinyAsciiStr;
15     use crate::calendar::ffi::ICU4XCalendar;
16     use crate::errors::ffi::ICU4XError;
18     #[cfg(feature = "icu_calendar")]
19     use crate::week::ffi::ICU4XWeekCalculator;
21     #[diplomat::enum_convert(IsoWeekday)]
22     pub enum ICU4XIsoWeekday {
23         Monday = 1,
24         Tuesday,
25         Wednesday,
26         Thursday,
27         Friday,
28         Saturday,
29         Sunday,
30     }
31     #[diplomat::opaque]
32     #[diplomat::transparent_convert]
33     /// An ICU4X Date object capable of containing a ISO-8601 date
34     #[diplomat::rust_link(icu::calendar::Date, Struct)]
35     pub struct ICU4XIsoDate(pub Date<Iso>);
37     impl ICU4XIsoDate {
38         /// Creates a new [`ICU4XIsoDate`] from the specified date and time.
39         #[diplomat::rust_link(icu::calendar::Date::try_new_iso_date, FnInStruct)]
40         #[diplomat::attr(all(supports = constructors, supports = fallible_constructors), constructor)]
41         pub fn create(year: i32, month: u8, day: u8) -> Result<Box<ICU4XIsoDate>, ICU4XError> {
42             Ok(Box::new(ICU4XIsoDate(Date::try_new_iso_date(
43                 year, month, day,
44             )?)))
45         }
47         /// Creates a new [`ICU4XIsoDate`] representing January 1, 1970.
48         #[diplomat::rust_link(icu::calendar::Date::unix_epoch, FnInStruct)]
49         #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "for_unix_epoch")]
50         pub fn create_for_unix_epoch() -> Box<ICU4XIsoDate> {
51             Box::new(ICU4XIsoDate(Date::unix_epoch()))
52         }
54         /// Convert this date to one in a different calendar
55         #[diplomat::rust_link(icu::calendar::Date::to_calendar, FnInStruct)]
56         pub fn to_calendar(&self, calendar: &ICU4XCalendar) -> Box<ICU4XDate> {
57             Box::new(ICU4XDate(self.0.to_calendar(calendar.0.clone())))
58         }
60         #[diplomat::rust_link(icu::calendar::Date::to_any, FnInStruct)]
61         pub fn to_any(&self) -> Box<ICU4XDate> {
62             Box::new(ICU4XDate(self.0.to_any().wrap_calendar_in_arc()))
63         }
65         /// Returns the 1-indexed day in the year for this date
66         #[diplomat::rust_link(icu::calendar::Date::day_of_year_info, FnInStruct)]
67         #[diplomat::attr(supports = accessors, getter)]
68         pub fn day_of_year(&self) -> u16 {
69             self.0.day_of_year_info().day_of_year
70         }
72         /// Returns the 1-indexed day in the month for this date
73         #[diplomat::rust_link(icu::calendar::Date::day_of_month, FnInStruct)]
74         #[diplomat::attr(supports = accessors, getter)]
75         pub fn day_of_month(&self) -> u32 {
76             self.0.day_of_month().0
77         }
79         /// Returns the day in the week for this day
80         #[diplomat::rust_link(icu::calendar::Date::day_of_week, FnInStruct)]
81         #[diplomat::attr(supports = accessors, getter)]
82         pub fn day_of_week(&self) -> ICU4XIsoWeekday {
83             self.0.day_of_week().into()
84         }
86         /// Returns the week number in this month, 1-indexed, based on what
87         /// is considered the first day of the week (often a locale preference).
88         ///
89         /// `first_weekday` can be obtained via `first_weekday()` on [`ICU4XWeekCalculator`]
90         #[diplomat::rust_link(icu::calendar::Date::week_of_month, FnInStruct)]
91         #[diplomat::rust_link(
92             icu::calendar::week::WeekCalculator::week_of_month,
93             FnInStruct,
94             hidden
95         )]
96         pub fn week_of_month(&self, first_weekday: ICU4XIsoWeekday) -> u32 {
97             self.0.week_of_month(first_weekday.into()).0
98         }
100         /// Returns the week number in this year, using week data
101         #[diplomat::rust_link(icu::calendar::Date::week_of_year, FnInStruct)]
102         #[diplomat::rust_link(
103             icu::calendar::week::WeekCalculator::week_of_year,
104             FnInStruct,
105             hidden
106         )]
107         #[cfg(feature = "icu_calendar")]
108         pub fn week_of_year(
109             &self,
110             calculator: &ICU4XWeekCalculator,
111         ) -> Result<crate::week::ffi::ICU4XWeekOf, ICU4XError> {
112             Ok(self.0.week_of_year(&calculator.0)?.into())
113         }
115         /// Returns 1-indexed number of the month of this date in its year
116         #[diplomat::rust_link(icu::calendar::Date::month, FnInStruct)]
117         #[diplomat::attr(supports = accessors, getter)]
118         pub fn month(&self) -> u32 {
119             self.0.month().ordinal
120         }
122         /// Returns the year number for this date
123         #[diplomat::rust_link(icu::calendar::Date::year, FnInStruct)]
124         #[diplomat::attr(supports = accessors, getter)]
125         pub fn year(&self) -> i32 {
126             self.0.year().number
127         }
129         /// Returns if the year is a leap year for this date
130         #[diplomat::rust_link(icu::calendar::Date::is_in_leap_year, FnInStruct)]
131         #[diplomat::attr(supports = accessors, getter)]
132         pub fn is_in_leap_year(&self) -> bool {
133             self.0.is_in_leap_year()
134         }
136         /// Returns the number of months in the year represented by this date
137         #[diplomat::rust_link(icu::calendar::Date::months_in_year, FnInStruct)]
138         #[diplomat::attr(supports = accessors, getter)]
139         pub fn months_in_year(&self) -> u8 {
140             self.0.months_in_year()
141         }
143         /// Returns the number of days in the month represented by this date
144         #[diplomat::rust_link(icu::calendar::Date::days_in_month, FnInStruct)]
145         #[diplomat::attr(supports = accessors, getter)]
146         pub fn days_in_month(&self) -> u8 {
147             self.0.days_in_month()
148         }
150         /// Returns the number of days in the year represented by this date
151         #[diplomat::rust_link(icu::calendar::Date::days_in_year, FnInStruct)]
152         #[diplomat::attr(supports = accessors, getter)]
153         pub fn days_in_year(&self) -> u16 {
154             self.0.days_in_year()
155         }
156     }
158     #[diplomat::opaque]
159     #[diplomat::transparent_convert]
160     /// An ICU4X Date object capable of containing a date and time for any calendar.
161     #[diplomat::rust_link(icu::calendar::Date, Struct)]
162     pub struct ICU4XDate(pub Date<Arc<AnyCalendar>>);
164     impl ICU4XDate {
165         /// Creates a new [`ICU4XDate`] representing the ISO date and time
166         /// given but in a given calendar
167         #[diplomat::rust_link(icu::calendar::Date::new_from_iso, FnInStruct)]
168         #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "from_iso_in_calendar")]
169         pub fn create_from_iso_in_calendar(
170             year: i32,
171             month: u8,
172             day: u8,
173             calendar: &ICU4XCalendar,
174         ) -> Result<Box<ICU4XDate>, ICU4XError> {
175             let cal = calendar.0.clone();
176             Ok(Box::new(ICU4XDate(
177                 Date::try_new_iso_date(year, month, day)?.to_calendar(cal),
178             )))
179         }
181         /// Creates a new [`ICU4XDate`] from the given codes, which are interpreted in the given calendar system
182         #[diplomat::rust_link(icu::calendar::Date::try_new_from_codes, FnInStruct)]
183         #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "from_codes_in_calendar")]
184         pub fn create_from_codes_in_calendar(
185             era_code: &DiplomatStr,
186             year: i32,
187             month_code: &DiplomatStr,
188             day: u8,
189             calendar: &ICU4XCalendar,
190         ) -> Result<Box<ICU4XDate>, ICU4XError> {
191             let era = TinyAsciiStr::from_bytes(era_code)
192                 .map_err(|_| ICU4XError::CalendarUnknownEraError)?
193                 .into();
194             let month = TinyAsciiStr::from_bytes(month_code)
195                 .map_err(|_| ICU4XError::CalendarUnknownMonthCodeError)?
196                 .into();
197             let cal = calendar.0.clone();
198             Ok(Box::new(ICU4XDate(Date::try_new_from_codes(
199                 era, year, month, day, cal,
200             )?)))
201         }
203         /// Convert this date to one in a different calendar
204         #[diplomat::rust_link(icu::calendar::Date::to_calendar, FnInStruct)]
205         pub fn to_calendar(&self, calendar: &ICU4XCalendar) -> Box<ICU4XDate> {
206             Box::new(ICU4XDate(self.0.to_calendar(calendar.0.clone())))
207         }
209         /// Converts this date to ISO
210         #[diplomat::rust_link(icu::calendar::Date::to_iso, FnInStruct)]
211         pub fn to_iso(&self) -> Box<ICU4XIsoDate> {
212             Box::new(ICU4XIsoDate(self.0.to_iso()))
213         }
215         /// Returns the 1-indexed day in the year for this date
216         #[diplomat::rust_link(icu::calendar::Date::day_of_year_info, FnInStruct)]
217         #[diplomat::attr(supports = accessors, getter)]
218         pub fn day_of_year(&self) -> u16 {
219             self.0.day_of_year_info().day_of_year
220         }
222         /// Returns the 1-indexed day in the month for this date
223         #[diplomat::rust_link(icu::calendar::Date::day_of_month, FnInStruct)]
224         #[diplomat::attr(supports = accessors, getter)]
225         pub fn day_of_month(&self) -> u32 {
226             self.0.day_of_month().0
227         }
229         /// Returns the day in the week for this day
230         #[diplomat::rust_link(icu::calendar::Date::day_of_week, FnInStruct)]
231         #[diplomat::attr(supports = accessors, getter)]
232         pub fn day_of_week(&self) -> ICU4XIsoWeekday {
233             self.0.day_of_week().into()
234         }
236         /// Returns the week number in this month, 1-indexed, based on what
237         /// is considered the first day of the week (often a locale preference).
238         ///
239         /// `first_weekday` can be obtained via `first_weekday()` on [`ICU4XWeekCalculator`]
240         #[diplomat::rust_link(icu::calendar::Date::week_of_month, FnInStruct)]
241         #[diplomat::rust_link(
242             icu::calendar::week::WeekCalculator::week_of_month,
243             FnInStruct,
244             hidden
245         )]
246         pub fn week_of_month(&self, first_weekday: ICU4XIsoWeekday) -> u32 {
247             self.0.week_of_month(first_weekday.into()).0
248         }
250         /// Returns the week number in this year, using week data
251         #[diplomat::rust_link(icu::calendar::Date::week_of_year, FnInStruct)]
252         #[diplomat::rust_link(
253             icu::calendar::week::WeekCalculator::week_of_year,
254             FnInStruct,
255             hidden
256         )]
257         #[cfg(feature = "icu_calendar")]
258         pub fn week_of_year(
259             &self,
260             calculator: &ICU4XWeekCalculator,
261         ) -> Result<crate::week::ffi::ICU4XWeekOf, ICU4XError> {
262             Ok(self.0.week_of_year(&calculator.0)?.into())
263         }
265         /// Returns 1-indexed number of the month of this date in its year
266         ///
267         /// Note that for lunar calendars this may not lead to the same month
268         /// having the same ordinal month across years; use month_code if you care
269         /// about month identity.
270         #[diplomat::rust_link(icu::calendar::Date::month, FnInStruct)]
271         #[diplomat::attr(supports = accessors, getter)]
272         pub fn ordinal_month(&self) -> u32 {
273             self.0.month().ordinal
274         }
276         /// Returns the month code for this date. Typically something
277         /// like "M01", "M02", but can be more complicated for lunar calendars.
278         #[diplomat::rust_link(icu::calendar::Date::month, FnInStruct)]
279         #[diplomat::attr(supports = accessors, getter)]
280         pub fn month_code(
281             &self,
282             write: &mut diplomat_runtime::DiplomatWriteable,
283         ) -> Result<(), ICU4XError> {
284             let code = self.0.month().code;
285             write.write_str(&code.0)?;
286             Ok(())
287         }
289         /// Returns the year number in the current era for this date
290         #[diplomat::rust_link(icu::calendar::Date::year, FnInStruct)]
291         #[diplomat::attr(supports = accessors, getter)]
292         pub fn year_in_era(&self) -> i32 {
293             self.0.year().number
294         }
296         /// Returns the era for this date,
297         #[diplomat::rust_link(icu::Date::year, FnInStruct)]
298         #[diplomat::rust_link(icu::types::Era, Struct, compact)]
299         #[diplomat::attr(supports = accessors, getter)]
300         pub fn era(
301             &self,
302             write: &mut diplomat_runtime::DiplomatWriteable,
303         ) -> Result<(), ICU4XError> {
304             let era = self.0.year().era;
305             write.write_str(&era.0)?;
306             Ok(())
307         }
309         /// Returns the number of months in the year represented by this date
310         #[diplomat::rust_link(icu::calendar::Date::months_in_year, FnInStruct)]
311         #[diplomat::attr(supports = accessors, getter)]
312         pub fn months_in_year(&self) -> u8 {
313             self.0.months_in_year()
314         }
316         /// Returns the number of days in the month represented by this date
317         #[diplomat::rust_link(icu::calendar::Date::days_in_month, FnInStruct)]
318         #[diplomat::attr(supports = accessors, getter)]
319         pub fn days_in_month(&self) -> u8 {
320             self.0.days_in_month()
321         }
323         /// Returns the number of days in the year represented by this date
324         #[diplomat::rust_link(icu::calendar::Date::days_in_year, FnInStruct)]
325         #[diplomat::attr(supports = accessors, getter)]
326         pub fn days_in_year(&self) -> u16 {
327             self.0.days_in_year()
328         }
330         /// Returns the [`ICU4XCalendar`] object backing this date
331         #[diplomat::rust_link(icu::calendar::Date::calendar, FnInStruct)]
332         #[diplomat::rust_link(icu::calendar::Date::calendar_wrapper, FnInStruct, hidden)]
333         #[diplomat::attr(supports = accessors, getter)]
334         pub fn calendar(&self) -> Box<ICU4XCalendar> {
335             Box::new(ICU4XCalendar(self.0.calendar_wrapper().clone()))
336         }
337     }