icu_calendar/calendar.rs
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
5use calendrical_calculations::rata_die::RataDie;
6
7use crate::cal::iso::IsoDateInner;
8use crate::error::{DateError, DateFromFieldsError};
9use crate::options::DateFromFieldsOptions;
10use crate::options::{DateAddOptions, DateDifferenceOptions};
11use crate::{types, Iso};
12use core::fmt;
13
14/// A calendar implementation
15///
16/// Only implementors of [`Calendar`] should care about these methods, in general users of
17/// these calendars should use the methods on [`Date`](crate::Date) instead.
18///
19/// Individual [`Calendar`] implementations may have inherent utility methods
20/// allowing for direct construction, etc.
21///
22/// <div class="stab unstable">
23/// 🚫 This trait is sealed; it should not be implemented by user code. If an API requests an item that implements this
24/// trait, please consider using a type from the implementors listed below.
25///
26/// It is still possible to implement this trait in userland (since `UnstableSealed` is public),
27/// do not do so unless you are prepared for things to occasionally break.
28/// </div>
29pub trait Calendar: crate::cal::scaffold::UnstableSealed {
30 /// The internal type used to represent dates
31 ///
32 /// Equality and ordering should observe normal calendar semantics.
33 type DateInner: Eq + Copy + PartialOrd + fmt::Debug;
34 /// The type of YearInfo returned by the date
35 type Year: fmt::Debug + Into<types::YearInfo>;
36 /// The type of error returned by `until`
37 type DifferenceError;
38
39 /// Construct a date from era/month codes and fields
40 ///
41 /// The year is the [extended year](crate::Date::extended_year) if no era is provided
42 #[expect(clippy::wrong_self_convention)]
43 fn from_codes(
44 &self,
45 era: Option<&str>,
46 year: i32,
47 month_code: types::MonthCode,
48 day: u8,
49 ) -> Result<Self::DateInner, DateError>;
50
51 /// Construct a date from a bag of date fields.
52 ///
53 /// <div class="stab unstable">
54 /// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways,
55 /// including in SemVer minor releases. Do not use this type unless you are prepared for things to occasionally break.
56 ///
57 /// Graduation tracking issue: [issue #7161](https://github.com/unicode-org/icu4x/issues/7161).
58 /// </div>
59 ///
60 /// ✨ *Enabled with the `unstable` Cargo feature.*
61 #[expect(clippy::wrong_self_convention)]
62 #[cfg(feature = "unstable")]
63 fn from_fields(
64 &self,
65 fields: types::DateFields,
66 options: DateFromFieldsOptions,
67 ) -> Result<Self::DateInner, DateFromFieldsError>;
68
69 /// Whether `from_iso`/`to_iso` is more efficient
70 /// than `from_rata_die`/`to_rata_die`.
71 fn has_cheap_iso_conversion(&self) -> bool;
72
73 /// Construct the date from an ISO date.
74 ///
75 /// Only called if `HAS_CHEAP_ISO_CONVERSION` is set.
76 #[expect(clippy::wrong_self_convention)]
77 fn from_iso(&self, iso: IsoDateInner) -> Self::DateInner {
78 self.from_rata_die(Iso.to_rata_die(&iso))
79 }
80 /// Obtain an ISO date from this date.
81 ///
82 /// Only called if `HAS_CHEAP_ISO_CONVERSION` is set.
83 fn to_iso(&self, date: &Self::DateInner) -> IsoDateInner {
84 Iso.from_rata_die(self.to_rata_die(date))
85 }
86
87 /// Construct the date from a [`RataDie`]
88 #[expect(clippy::wrong_self_convention)]
89 fn from_rata_die(&self, rd: RataDie) -> Self::DateInner;
90 /// Obtain a [`RataDie`] from this date
91 fn to_rata_die(&self, date: &Self::DateInner) -> RataDie;
92
93 /// Count the number of months in a given year, specified by providing a date
94 /// from that year
95 fn months_in_year(&self, date: &Self::DateInner) -> u8;
96 /// Count the number of days in a given year, specified by providing a date
97 /// from that year
98 fn days_in_year(&self, date: &Self::DateInner) -> u16;
99 /// Count the number of days in a given month, specified by providing a date
100 /// from that year/month
101 fn days_in_month(&self, date: &Self::DateInner) -> u8;
102 /// Calculate if a date is in a leap year
103 fn is_in_leap_year(&self, date: &Self::DateInner) -> bool;
104
105 /// Information about the year
106 fn year_info(&self, date: &Self::DateInner) -> Self::Year;
107
108 /// The [extended year](crate::Date::extended_year).
109 fn extended_year(&self, date: &Self::DateInner) -> i32 {
110 self.year_info(date).into().extended_year()
111 }
112 /// The calendar-specific month represented by `date`
113 fn month(&self, date: &Self::DateInner) -> types::MonthInfo;
114 /// The calendar-specific day-of-month represented by `date`
115 fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth;
116 /// Information of the day of the year
117 fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear;
118
119 /// Add `duration` to `date`
120 ///
121 /// <div class="stab unstable">
122 /// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways,
123 /// including in SemVer minor releases. Do not use this type unless you are prepared for things to occasionally break.
124 ///
125 /// Graduation tracking issue: [issue #3964](https://github.com/unicode-org/icu4x/issues/3964).
126 /// </div>
127 ///
128 /// ✨ *Enabled with the `unstable` Cargo feature.*
129 #[cfg(feature = "unstable")]
130 fn add(
131 &self,
132 date: &Self::DateInner,
133 duration: types::DateDuration,
134 options: DateAddOptions,
135 ) -> Result<Self::DateInner, DateError>;
136
137 /// Calculate `date2 - date` as a duration
138 ///
139 /// `calendar2` is the calendar object associated with `date2`. In case the specific calendar objects
140 /// differ on data, the data for the first calendar is used, and `date2` may be converted if necessary.
141 ///
142 /// <div class="stab unstable">
143 /// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways,
144 /// including in SemVer minor releases. Do not use this type unless you are prepared for things to occasionally break.
145 ///
146 /// Graduation tracking issue: [issue #3964](https://github.com/unicode-org/icu4x/issues/3964).
147 /// </div>
148 ///
149 /// ✨ *Enabled with the `unstable` Cargo feature.*
150 #[cfg(feature = "unstable")]
151 fn until(
152 &self,
153 date1: &Self::DateInner,
154 date2: &Self::DateInner,
155 options: DateDifferenceOptions,
156 ) -> Result<types::DateDuration, Self::DifferenceError>;
157
158 /// Returns the [`CalendarAlgorithm`](crate::preferences::CalendarAlgorithm) that is required to match
159 /// when parsing into this calendar.
160 ///
161 /// If left empty, any algorithm will parse successfully.
162 fn calendar_algorithm(&self) -> Option<crate::preferences::CalendarAlgorithm>;
163
164 /// Obtain a name for the calendar for debug printing
165 fn debug_name(&self) -> &'static str;
166}