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 ).
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 {
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>);
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(
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()))
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())))
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()))
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
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
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()
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).
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,
96 pub fn week_of_month(&self, first_weekday: ICU4XIsoWeekday) -> u32 {
97 self.0.week_of_month(first_weekday.into()).0
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,
107 #[cfg(feature = "icu_calendar")]
110 calculator: &ICU4XWeekCalculator,
111 ) -> Result<crate::week::ffi::ICU4XWeekOf, ICU4XError> {
112 Ok(self.0.week_of_year(&calculator.0)?.into())
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
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 {
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()
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()
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()
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()
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>>);
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(
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),
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,
187 month_code: &DiplomatStr,
189 calendar: &ICU4XCalendar,
190 ) -> Result<Box<ICU4XDate>, ICU4XError> {
191 let era = TinyAsciiStr::from_bytes(era_code)
192 .map_err(|_| ICU4XError::CalendarUnknownEraError)?
194 let month = TinyAsciiStr::from_bytes(month_code)
195 .map_err(|_| ICU4XError::CalendarUnknownMonthCodeError)?
197 let cal = calendar.0.clone();
198 Ok(Box::new(ICU4XDate(Date::try_new_from_codes(
199 era, year, month, day, cal,
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())))
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()))
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
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
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()
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).
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,
246 pub fn week_of_month(&self, first_weekday: ICU4XIsoWeekday) -> u32 {
247 self.0.week_of_month(first_weekday.into()).0
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,
257 #[cfg(feature = "icu_calendar")]
260 calculator: &ICU4XWeekCalculator,
261 ) -> Result<crate::week::ffi::ICU4XWeekOf, ICU4XError> {
262 Ok(self.0.week_of_year(&calculator.0)?.into())
265 /// Returns 1-indexed number of the month of this date in its year
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
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)]
282 write: &mut diplomat_runtime::DiplomatWriteable,
283 ) -> Result<(), ICU4XError> {
284 let code = self.0.month().code;
285 write.write_str(&code.0)?;
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 {
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)]
302 write: &mut diplomat_runtime::DiplomatWriteable,
303 ) -> Result<(), ICU4XError> {
304 let era = self.0.year().era;
305 write.write_str(&era.0)?;
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()
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()
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()
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()))