icu_datetime/scaffold/
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
5//! Scaffolding traits and impls for calendars.
6
7use crate::provider::{neo::*, *};
8use crate::scaffold::UnstableSealed;
9use crate::{DateTimeFormatterPreferences, MismatchedCalendarError};
10use core::marker::PhantomData;
11use icu_calendar::cal::Roc;
12use icu_calendar::cal::{self, Chinese};
13use icu_calendar::cal::{
14    Buddhist, Coptic, Dangi, Ethiopian, Gregorian, Hebrew, HijriSimulated, HijriTabular,
15    HijriUmmAlQura, Indian, Japanese, JapaneseExtended, Persian,
16};
17use icu_calendar::{AnyCalendar, AnyCalendarKind, AsCalendar, Date, IntoAnyCalendar, Ref};
18use icu_provider::marker::NeverMarker;
19use icu_provider::prelude::*;
20use icu_time::{
21    zone::{models::TimeZoneModel, UtcOffset},
22    DateTime, Time, TimeZoneInfo, ZonedDateTime,
23};
24
25/// A calendar that can be found in CLDR.
26///
27/// New implementors of this trait will likely also wish to modify `get_era_code_map()`
28/// in the CLDR transformer to support any new era maps.
29///
30/// <div class="stab unstable">
31/// 🚫 This trait is sealed; it cannot be implemented by user code. If an API requests an item that implements this
32/// trait, please consider using a type from the implementors listed below.
33/// </div>
34pub trait CldrCalendar: UnstableSealed {
35    /// The data marker for loading year symbols for this calendar.
36    type YearNamesV1: DataMarker<DataStruct = YearNames<'static>>;
37
38    /// The data marker for loading month symbols for this calendar.
39    type MonthNamesV1: DataMarker<DataStruct = MonthNames<'static>>;
40
41    /// The data marker for loading skeleton patterns for this calendar.
42    type SkeletaV1: DataMarker<DataStruct = PackedPatterns<'static>>;
43}
44
45impl CldrCalendar for () {
46    type YearNamesV1 = NeverMarker<YearNames<'static>>;
47    type MonthNamesV1 = NeverMarker<MonthNames<'static>>;
48    type SkeletaV1 = NeverMarker<PackedPatterns<'static>>;
49}
50
51impl CldrCalendar for Buddhist {
52    type YearNamesV1 = DatetimeNamesYearBuddhistV1;
53    type MonthNamesV1 = DatetimeNamesMonthBuddhistV1;
54    type SkeletaV1 = DatetimePatternsDateBuddhistV1;
55}
56
57impl CldrCalendar for Chinese {
58    type YearNamesV1 = DatetimeNamesYearChineseV1;
59    type MonthNamesV1 = DatetimeNamesMonthChineseV1;
60    type SkeletaV1 = DatetimePatternsDateChineseV1;
61}
62
63impl CldrCalendar for Coptic {
64    type YearNamesV1 = DatetimeNamesYearCopticV1;
65    type MonthNamesV1 = DatetimeNamesMonthCopticV1;
66    type SkeletaV1 = DatetimePatternsDateCopticV1;
67}
68
69impl CldrCalendar for Dangi {
70    type YearNamesV1 = DatetimeNamesYearDangiV1;
71    type MonthNamesV1 = DatetimeNamesMonthDangiV1;
72    type SkeletaV1 = DatetimePatternsDateDangiV1;
73}
74
75impl CldrCalendar for Ethiopian {
76    type YearNamesV1 = DatetimeNamesYearEthiopianV1;
77    type MonthNamesV1 = DatetimeNamesMonthEthiopianV1;
78    type SkeletaV1 = DatetimePatternsDateEthiopianV1;
79}
80
81impl CldrCalendar for Gregorian {
82    type YearNamesV1 = DatetimeNamesYearGregorianV1;
83    type MonthNamesV1 = DatetimeNamesMonthGregorianV1;
84    type SkeletaV1 = DatetimePatternsDateGregorianV1;
85}
86
87impl CldrCalendar for Hebrew {
88    type YearNamesV1 = DatetimeNamesYearHebrewV1;
89    type MonthNamesV1 = DatetimeNamesMonthHebrewV1;
90    type SkeletaV1 = DatetimePatternsDateHebrewV1;
91}
92
93impl CldrCalendar for Indian {
94    type YearNamesV1 = DatetimeNamesYearIndianV1;
95    type MonthNamesV1 = DatetimeNamesMonthIndianV1;
96    type SkeletaV1 = DatetimePatternsDateIndianV1;
97}
98
99impl CldrCalendar for HijriTabular {
100    type YearNamesV1 = DatetimeNamesYearHijriV1;
101    type MonthNamesV1 = DatetimeNamesMonthHijriV1;
102    type SkeletaV1 = DatetimePatternsDateHijriV1;
103}
104
105impl CldrCalendar for HijriSimulated {
106    type YearNamesV1 = DatetimeNamesYearHijriV1;
107    type MonthNamesV1 = DatetimeNamesMonthHijriV1;
108    type SkeletaV1 = DatetimePatternsDateHijriV1;
109}
110
111impl CldrCalendar for HijriUmmAlQura {
112    type YearNamesV1 = DatetimeNamesYearHijriV1;
113    type MonthNamesV1 = DatetimeNamesMonthHijriV1;
114    type SkeletaV1 = DatetimePatternsDateHijriV1;
115}
116
117impl CldrCalendar for Japanese {
118    type YearNamesV1 = DatetimeNamesYearJapaneseV1;
119    type MonthNamesV1 = DatetimeNamesMonthJapaneseV1;
120    type SkeletaV1 = DatetimePatternsDateJapaneseV1;
121}
122
123impl CldrCalendar for JapaneseExtended {
124    type YearNamesV1 = DatetimeNamesYearJapanextV1;
125    type MonthNamesV1 = DatetimeNamesMonthJapanextV1;
126    type SkeletaV1 = DatetimePatternsDateJapanextV1;
127}
128
129impl CldrCalendar for Persian {
130    type YearNamesV1 = DatetimeNamesYearPersianV1;
131    type MonthNamesV1 = DatetimeNamesMonthPersianV1;
132    type SkeletaV1 = DatetimePatternsDatePersianV1;
133}
134
135impl CldrCalendar for Roc {
136    type YearNamesV1 = DatetimeNamesYearRocV1;
137    type MonthNamesV1 = DatetimeNamesMonthRocV1;
138    type SkeletaV1 = DatetimePatternsDateRocV1;
139}
140
141impl UnstableSealed for () {}
142impl UnstableSealed for Buddhist {}
143impl UnstableSealed for Chinese {}
144impl UnstableSealed for Coptic {}
145impl UnstableSealed for Dangi {}
146impl UnstableSealed for Ethiopian {}
147impl UnstableSealed for Gregorian {}
148impl UnstableSealed for Hebrew {}
149impl UnstableSealed for Indian {}
150impl UnstableSealed for HijriTabular {}
151impl UnstableSealed for HijriSimulated {}
152impl UnstableSealed for HijriUmmAlQura {}
153impl UnstableSealed for Japanese {}
154impl UnstableSealed for JapaneseExtended {}
155impl UnstableSealed for Persian {}
156impl UnstableSealed for Roc {}
157
158/// A collection of marker types associated with all formattable calendars.
159///
160/// This is used to group together the calendar-specific marker types that produce a common
161/// [`DynamicDataMarker`]. For example, this trait can be implemented for [`YearNamesV1`].
162///
163/// This trait serves as a building block for a cross-calendar [`BoundDataProvider`].
164///
165/// <div class="stab unstable">
166/// 🚧 This trait is considered unstable; it may change at any time, in breaking or non-breaking ways,
167/// including in SemVer minor releases. Do not implement this trait in userland unless you are prepared for things to occasionally break.
168/// </div>
169pub trait CalMarkers<M>: UnstableSealed
170where
171    M: DynamicDataMarker,
172{
173    /// The type for a [`Buddhist`] calendar
174    type Buddhist: DataMarker<DataStruct = M::DataStruct>;
175    /// The type for a [`Chinese`] calendar
176    type Chinese: DataMarker<DataStruct = M::DataStruct>;
177    /// The type for a [`Coptic`] calendar
178    type Coptic: DataMarker<DataStruct = M::DataStruct>;
179    /// The type for a [`Dangi`] calendar
180    type Dangi: DataMarker<DataStruct = M::DataStruct>;
181    /// The type for an [`Ethiopian`] calendar (either era style)
182    type Ethiopian: DataMarker<DataStruct = M::DataStruct>;
183    /// The type for a [`Gregorian`] calendar
184    type Gregorian: DataMarker<DataStruct = M::DataStruct>;
185    /// The type for a [`Hebrew`] calendar
186    type Hebrew: DataMarker<DataStruct = M::DataStruct>;
187    /// The type for a [`Indian`] calendar
188    type Indian: DataMarker<DataStruct = M::DataStruct>;
189    /// The type for Hirji calendars
190    type Hijri: DataMarker<DataStruct = M::DataStruct>;
191    /// The type for a [`Japanese`] calendar
192    type Japanese: DataMarker<DataStruct = M::DataStruct>;
193    /// The type for a [`Persian`] calendar
194    type Persian: DataMarker<DataStruct = M::DataStruct>;
195    /// The type for a [`Roc`] calendar
196    type Roc: DataMarker<DataStruct = M::DataStruct>;
197}
198
199/// Implementation of [`CalMarkers`] that includes data for all calendars.
200#[derive(Debug)]
201#[allow(clippy::exhaustive_enums)] // empty enum
202pub enum FullDataCalMarkers {}
203
204impl UnstableSealed for FullDataCalMarkers {}
205
206/// Implementation of [`CalMarkers`] that includes data for no calendars.
207#[derive(Debug)]
208#[allow(clippy::exhaustive_enums)] // empty enum
209pub enum NoDataCalMarkers {}
210
211impl UnstableSealed for NoDataCalMarkers {}
212
213impl<M> CalMarkers<M> for NoDataCalMarkers
214where
215    M: DynamicDataMarker,
216{
217    type Buddhist = NeverMarker<M::DataStruct>;
218    type Chinese = NeverMarker<M::DataStruct>;
219    type Coptic = NeverMarker<M::DataStruct>;
220    type Dangi = NeverMarker<M::DataStruct>;
221    type Ethiopian = NeverMarker<M::DataStruct>;
222    type Gregorian = NeverMarker<M::DataStruct>;
223    type Hebrew = NeverMarker<M::DataStruct>;
224    type Indian = NeverMarker<M::DataStruct>;
225    type Hijri = NeverMarker<M::DataStruct>;
226    type Japanese = NeverMarker<M::DataStruct>;
227    type Persian = NeverMarker<M::DataStruct>;
228    type Roc = NeverMarker<M::DataStruct>;
229}
230
231/// A calendar type that is supported by [`DateTimeFormatter`](crate::DateTimeFormatter).
232///
233/// [`FixedCalendarDateTimeFormatter`](crate::FixedCalendarDateTimeFormatter) might support additional calendars.
234pub trait IntoFormattableAnyCalendar: CldrCalendar + IntoAnyCalendar {}
235
236// keep in sync with FormattableAnyCalendarKind
237impl IntoFormattableAnyCalendar for Buddhist {}
238impl IntoFormattableAnyCalendar for Chinese {}
239impl IntoFormattableAnyCalendar for Coptic {}
240impl IntoFormattableAnyCalendar for Dangi {}
241impl IntoFormattableAnyCalendar for Ethiopian {}
242impl IntoFormattableAnyCalendar for Gregorian {}
243impl IntoFormattableAnyCalendar for Hebrew {}
244impl IntoFormattableAnyCalendar for Indian {}
245impl IntoFormattableAnyCalendar for HijriTabular {}
246impl IntoFormattableAnyCalendar for HijriSimulated {}
247impl IntoFormattableAnyCalendar for HijriUmmAlQura {}
248impl IntoFormattableAnyCalendar for Japanese {}
249// _NOT_ JapaneseExtended
250impl IntoFormattableAnyCalendar for Persian {}
251impl IntoFormattableAnyCalendar for Roc {}
252
253// keep in sync with IntoFormattableAnyCalendar
254#[derive(Debug, Clone, Copy)]
255pub(crate) enum FormattableAnyCalendarKind {
256    Buddhist,
257    Chinese,
258    Coptic,
259    Dangi,
260    Ethiopian,
261    EthiopianAmeteAlem,
262    Gregorian,
263    Hebrew,
264    Indian,
265    HijriTabularTypeIIFriday,
266    // _NOT_ HijriSimulatedMecca
267    HijriTabularTypeIIThursday,
268    HijriUmmAlQura,
269    Japanese,
270    // _NOT_ JapaneseExtended
271    Persian,
272    Roc,
273}
274
275impl FormattableAnyCalendarKind {
276    pub(crate) fn try_from_any_calendar_kind(kind: AnyCalendarKind) -> Option<Self> {
277        use AnyCalendarKind::*;
278        let res = match kind {
279            Buddhist => Self::Buddhist,
280            Chinese => Self::Chinese,
281            Coptic => Self::Coptic,
282            Dangi => Self::Dangi,
283            Ethiopian => Self::Ethiopian,
284            EthiopianAmeteAlem => Self::EthiopianAmeteAlem,
285            Gregorian => Self::Gregorian,
286            Hebrew => Self::Hebrew,
287            Indian => Self::Indian,
288            HijriTabularTypeIIFriday => Self::HijriTabularTypeIIFriday,
289            HijriSimulatedMecca => return None,
290            HijriTabularTypeIIThursday => Self::HijriTabularTypeIIThursday,
291            HijriUmmAlQura => Self::HijriUmmAlQura,
292            Iso => return None,
293            Japanese => Self::Japanese,
294            JapaneseExtended => return None,
295            Persian => Self::Persian,
296            Roc => Self::Roc,
297            _ => {
298                debug_assert!(false, "cross-crate exhaustive match");
299                return None;
300            }
301        };
302        Some(res)
303    }
304
305    pub(crate) fn from_preferences(mut prefs: DateTimeFormatterPreferences) -> Self {
306        if let Some(algo) = prefs.calendar_algorithm {
307            if let Ok(kind) = AnyCalendarKind::try_from(algo) {
308                if let Some(res) = Self::try_from_any_calendar_kind(kind) {
309                    return res;
310                }
311            }
312        }
313        // Calendar not specified or not supported by DateTimeFormatter
314        // Currently this is CalendarAlgorithm::Iso8601, CalendarAlgorithm::Hijri(Rgsa)
315        // Let AnyCalendarKind constructor select an appropriate fallback
316        prefs.calendar_algorithm = None;
317        let kind = AnyCalendarKind::new((&prefs).into());
318        match Self::try_from_any_calendar_kind(kind) {
319            Some(res) => res,
320            None => {
321                debug_assert!(false, "all locale-default calendars are supported");
322                // fall back to something non-Gregorian to make errors more obvious
323                FormattableAnyCalendarKind::Coptic
324            }
325        }
326    }
327}
328
329/// A version of [`AnyCalendar`] for the calendars supported in the any-calendar formatter.
330#[derive(Debug, Clone)]
331pub(crate) struct FormattableAnyCalendar {
332    any_calendar: AnyCalendar,
333    kind: FormattableAnyCalendarKind,
334}
335
336impl FormattableAnyCalendar {
337    pub(crate) fn from_calendar(calendar: impl IntoFormattableAnyCalendar) -> Self {
338        let any_calendar = calendar.to_any();
339        let kind = any_calendar.kind();
340        let kind = FormattableAnyCalendarKind::try_from_any_calendar_kind(any_calendar.kind())
341            .unwrap_or_else(|| {
342                debug_assert!(false, "{kind:?} is not a FormattableAnyCalendarKind");
343                FormattableAnyCalendarKind::Coptic
344            });
345        Self { any_calendar, kind }
346    }
347
348    pub(crate) fn try_from_any_calendar(any_calendar: AnyCalendar) -> Option<Self> {
349        let kind = FormattableAnyCalendarKind::try_from_any_calendar_kind(any_calendar.kind())?;
350        Some(Self { any_calendar, kind })
351    }
352
353    pub(crate) fn kind(&self) -> FormattableAnyCalendarKind {
354        self.kind
355    }
356
357    #[cfg(feature = "compiled_data")]
358    pub(crate) fn try_new(kind: FormattableAnyCalendarKind) -> Result<Self, DataError> {
359        use FormattableAnyCalendarKind::*;
360        let any_calendar = match kind {
361            Buddhist => AnyCalendar::Buddhist(cal::Buddhist),
362            Chinese => AnyCalendar::Chinese(cal::Chinese::new()),
363            Coptic => AnyCalendar::Coptic(cal::Coptic),
364            Dangi => AnyCalendar::Dangi(cal::Dangi::new()),
365            Ethiopian => AnyCalendar::Ethiopian(cal::Ethiopian::new()),
366            EthiopianAmeteAlem => AnyCalendar::Ethiopian(cal::Ethiopian::new_with_era_style(
367                cal::EthiopianEraStyle::AmeteAlem,
368            )),
369            Gregorian => AnyCalendar::Gregorian(cal::Gregorian),
370            Hebrew => AnyCalendar::Hebrew(cal::Hebrew),
371            Indian => AnyCalendar::Indian(cal::Indian),
372            HijriTabularTypeIIFriday => AnyCalendar::HijriTabular(cal::HijriTabular::new(
373                cal::HijriTabularLeapYears::TypeII,
374                cal::HijriTabularEpoch::Friday,
375            )),
376            HijriTabularTypeIIThursday => AnyCalendar::HijriTabular(cal::HijriTabular::new(
377                cal::HijriTabularLeapYears::TypeII,
378                cal::HijriTabularEpoch::Thursday,
379            )),
380            HijriUmmAlQura => AnyCalendar::HijriUmmAlQura(cal::HijriUmmAlQura::new()),
381            Japanese => AnyCalendar::Japanese(cal::Japanese::new()),
382            Persian => AnyCalendar::Persian(cal::Persian),
383            Roc => AnyCalendar::Roc(cal::Roc),
384        };
385        Ok(Self { any_calendar, kind })
386    }
387
388    #[cfg(feature = "serde")]
389    pub(crate) fn try_new_with_buffer_provider<P>(
390        provider: &P,
391        kind: FormattableAnyCalendarKind,
392    ) -> Result<Self, DataError>
393    where
394        P: ?Sized + BufferProvider,
395    {
396        use FormattableAnyCalendarKind::*;
397        let any_calendar = match kind {
398            Buddhist => AnyCalendar::Buddhist(cal::Buddhist),
399            Chinese => AnyCalendar::Chinese(cal::Chinese::try_new_with_buffer_provider(provider)?),
400            Coptic => AnyCalendar::Coptic(cal::Coptic),
401            Dangi => AnyCalendar::Dangi(cal::Dangi::try_new_with_buffer_provider(provider)?),
402            Ethiopian => AnyCalendar::Ethiopian(cal::Ethiopian::new()),
403            EthiopianAmeteAlem => AnyCalendar::Ethiopian(cal::Ethiopian::new_with_era_style(
404                cal::EthiopianEraStyle::AmeteAlem,
405            )),
406            Gregorian => AnyCalendar::Gregorian(cal::Gregorian),
407            Hebrew => AnyCalendar::Hebrew(cal::Hebrew),
408            Indian => AnyCalendar::Indian(cal::Indian),
409            HijriTabularTypeIIFriday => AnyCalendar::HijriTabular(cal::HijriTabular::new(
410                cal::HijriTabularLeapYears::TypeII,
411                cal::HijriTabularEpoch::Friday,
412            )),
413            HijriTabularTypeIIThursday => AnyCalendar::HijriTabular(cal::HijriTabular::new(
414                cal::HijriTabularLeapYears::TypeII,
415                cal::HijriTabularEpoch::Thursday,
416            )),
417            HijriUmmAlQura => AnyCalendar::HijriUmmAlQura(cal::HijriUmmAlQura::new()),
418            Japanese => {
419                AnyCalendar::Japanese(cal::Japanese::try_new_with_buffer_provider(provider)?)
420            }
421            Persian => AnyCalendar::Persian(cal::Persian),
422            Roc => AnyCalendar::Roc(cal::Roc),
423        };
424        Ok(Self { any_calendar, kind })
425    }
426
427    pub(crate) fn try_new_unstable<P>(
428        provider: &P,
429        kind: FormattableAnyCalendarKind,
430    ) -> Result<Self, DataError>
431    where
432        P: ?Sized
433            + DataProvider<icu_calendar::provider::CalendarJapaneseModernV1>
434            + DataProvider<icu_calendar::provider::CalendarChineseV1>
435            + DataProvider<icu_calendar::provider::CalendarDangiV1>,
436    {
437        use FormattableAnyCalendarKind::*;
438        let any_calendar = match kind {
439            Buddhist => AnyCalendar::Buddhist(cal::Buddhist),
440            Chinese => AnyCalendar::Chinese(cal::Chinese::try_new_unstable(provider)?),
441            Coptic => AnyCalendar::Coptic(cal::Coptic),
442            Dangi => AnyCalendar::Dangi(cal::Dangi::try_new_unstable(provider)?),
443            Ethiopian => AnyCalendar::Ethiopian(cal::Ethiopian::new()),
444            EthiopianAmeteAlem => AnyCalendar::Ethiopian(cal::Ethiopian::new_with_era_style(
445                cal::EthiopianEraStyle::AmeteAlem,
446            )),
447            Gregorian => AnyCalendar::Gregorian(cal::Gregorian),
448            Hebrew => AnyCalendar::Hebrew(cal::Hebrew),
449            Indian => AnyCalendar::Indian(cal::Indian),
450            HijriTabularTypeIIFriday => AnyCalendar::HijriTabular(cal::HijriTabular::new(
451                cal::HijriTabularLeapYears::TypeII,
452                cal::HijriTabularEpoch::Friday,
453            )),
454            HijriTabularTypeIIThursday => AnyCalendar::HijriTabular(cal::HijriTabular::new(
455                cal::HijriTabularLeapYears::TypeII,
456                cal::HijriTabularEpoch::Thursday,
457            )),
458            HijriUmmAlQura => AnyCalendar::HijriUmmAlQura(cal::HijriUmmAlQura::new()),
459            Japanese => AnyCalendar::Japanese(cal::Japanese::try_new_unstable(provider)?),
460            Persian => AnyCalendar::Persian(cal::Persian),
461            Roc => AnyCalendar::Roc(cal::Roc),
462        };
463        Ok(Self { any_calendar, kind })
464    }
465
466    pub(crate) fn into_untagged(self) -> UntaggedFormattableAnyCalendar {
467        UntaggedFormattableAnyCalendar {
468            any_calendar: self.any_calendar,
469        }
470    }
471}
472
473#[derive(Debug, Clone)]
474pub(crate) struct UntaggedFormattableAnyCalendar {
475    // Invariant: the kind must be representable as an FormattableAnyCalendarKind
476    any_calendar: AnyCalendar,
477}
478
479/// A version of [`FormattableAnyCalendar`] that is smaller on the stack.
480impl UntaggedFormattableAnyCalendar {
481    pub(crate) fn into_tagged(self) -> FormattableAnyCalendar {
482        let kind = FormattableAnyCalendarKind::try_from_any_calendar_kind(self.any_calendar.kind())
483            .unwrap_or_else(|| {
484                debug_assert!(false, "unreachable by invariant");
485                // fall back to something non-Gregorian to make errors more obvious
486                FormattableAnyCalendarKind::Coptic
487            });
488        FormattableAnyCalendar {
489            any_calendar: self.any_calendar,
490            kind,
491        }
492    }
493
494    pub(crate) fn any_calendar(&self) -> &AnyCalendar {
495        &self.any_calendar
496    }
497
498    pub(crate) fn take_any_calendar(self) -> AnyCalendar {
499        self.any_calendar
500    }
501}
502
503pub(crate) struct FormattableAnyCalendarNamesLoader<H, P> {
504    provider: P,
505    kind: FormattableAnyCalendarKind,
506    _helper: PhantomData<H>,
507}
508
509impl<H, P> FormattableAnyCalendarNamesLoader<H, P> {
510    pub(crate) fn new(provider: P, kind: FormattableAnyCalendarKind) -> Self {
511        Self {
512            provider,
513            kind,
514            _helper: PhantomData,
515        }
516    }
517}
518
519impl<M, H, P> BoundDataProvider<M> for FormattableAnyCalendarNamesLoader<H, P>
520where
521    M: DynamicDataMarker,
522    H: CalMarkers<M>,
523    P: Sized
524        + DataProvider<H::Buddhist>
525        + DataProvider<H::Chinese>
526        + DataProvider<H::Coptic>
527        + DataProvider<H::Dangi>
528        + DataProvider<H::Ethiopian>
529        + DataProvider<H::Gregorian>
530        + DataProvider<H::Hebrew>
531        + DataProvider<H::Indian>
532        + DataProvider<H::Hijri>
533        + DataProvider<H::Japanese>
534        + DataProvider<H::Persian>
535        + DataProvider<H::Roc>,
536{
537    fn load_bound(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> {
538        use FormattableAnyCalendarKind::*;
539        let p = &self.provider;
540        match self.kind {
541            Buddhist => H::Buddhist::bind(p).load_bound(req),
542            Chinese => H::Chinese::bind(p).load_bound(req),
543            Coptic => H::Coptic::bind(p).load_bound(req),
544            Dangi => H::Dangi::bind(p).load_bound(req),
545            Ethiopian | EthiopianAmeteAlem => H::Ethiopian::bind(p).load_bound(req),
546            Gregorian => H::Gregorian::bind(p).load_bound(req),
547            Hebrew => H::Hebrew::bind(p).load_bound(req),
548            Indian => H::Indian::bind(p).load_bound(req),
549            HijriTabularTypeIIFriday | HijriTabularTypeIIThursday | HijriUmmAlQura => {
550                H::Hijri::bind(p).load_bound(req)
551            }
552            Japanese => H::Japanese::bind(p).load_bound(req),
553            Persian => H::Persian::bind(p).load_bound(req),
554            Roc => H::Roc::bind(p).load_bound(req),
555        }
556    }
557    fn bound_marker(&self) -> DataMarkerInfo {
558        use FormattableAnyCalendarKind::*;
559        match self.kind {
560            Buddhist => H::Buddhist::INFO,
561            Chinese => H::Chinese::INFO,
562            Coptic => H::Coptic::INFO,
563            Dangi => H::Dangi::INFO,
564            Ethiopian | EthiopianAmeteAlem => H::Ethiopian::INFO,
565            Gregorian => H::Gregorian::INFO,
566            Hebrew => H::Hebrew::INFO,
567            Indian => H::Indian::INFO,
568            HijriTabularTypeIIFriday | HijriTabularTypeIIThursday | HijriUmmAlQura => {
569                H::Hijri::INFO
570            }
571            Japanese => H::Japanese::INFO,
572            Persian => H::Persian::INFO,
573            Roc => H::Roc::INFO,
574        }
575    }
576}
577
578impl CalMarkers<YearNamesV1> for FullDataCalMarkers {
579    type Buddhist = <Buddhist as CldrCalendar>::YearNamesV1;
580    type Chinese = <Chinese as CldrCalendar>::YearNamesV1;
581    type Coptic = <Coptic as CldrCalendar>::YearNamesV1;
582    type Dangi = <Dangi as CldrCalendar>::YearNamesV1;
583    type Ethiopian = <Ethiopian as CldrCalendar>::YearNamesV1;
584    type Gregorian = <Gregorian as CldrCalendar>::YearNamesV1;
585    type Hebrew = <Hebrew as CldrCalendar>::YearNamesV1;
586    type Indian = <Indian as CldrCalendar>::YearNamesV1;
587    type Hijri = <HijriUmmAlQura as CldrCalendar>::YearNamesV1;
588    type Japanese = <Japanese as CldrCalendar>::YearNamesV1;
589    type Persian = <Persian as CldrCalendar>::YearNamesV1;
590    type Roc = <Roc as CldrCalendar>::YearNamesV1;
591}
592
593impl CalMarkers<MonthNamesV1> for FullDataCalMarkers {
594    type Buddhist = <Buddhist as CldrCalendar>::MonthNamesV1;
595    type Chinese = <Chinese as CldrCalendar>::MonthNamesV1;
596    type Coptic = <Coptic as CldrCalendar>::MonthNamesV1;
597    type Dangi = <Dangi as CldrCalendar>::MonthNamesV1;
598    type Ethiopian = <Ethiopian as CldrCalendar>::MonthNamesV1;
599    type Gregorian = <Gregorian as CldrCalendar>::MonthNamesV1;
600    type Hebrew = <Hebrew as CldrCalendar>::MonthNamesV1;
601    type Indian = <Indian as CldrCalendar>::MonthNamesV1;
602    type Hijri = <HijriUmmAlQura as CldrCalendar>::MonthNamesV1;
603    type Japanese = <Japanese as CldrCalendar>::MonthNamesV1;
604    type Persian = <Persian as CldrCalendar>::MonthNamesV1;
605    type Roc = <Roc as CldrCalendar>::MonthNamesV1;
606}
607
608impl CalMarkers<ErasedPackedPatterns> for FullDataCalMarkers {
609    type Buddhist = <Buddhist as CldrCalendar>::SkeletaV1;
610    type Chinese = <Chinese as CldrCalendar>::SkeletaV1;
611    type Coptic = <Coptic as CldrCalendar>::SkeletaV1;
612    type Dangi = <Dangi as CldrCalendar>::SkeletaV1;
613    type Ethiopian = <Ethiopian as CldrCalendar>::SkeletaV1;
614    type Gregorian = <Gregorian as CldrCalendar>::SkeletaV1;
615    type Hebrew = <Hebrew as CldrCalendar>::SkeletaV1;
616    type Indian = <Indian as CldrCalendar>::SkeletaV1;
617    type Hijri = <HijriUmmAlQura as CldrCalendar>::SkeletaV1;
618    type Japanese = <Japanese as CldrCalendar>::SkeletaV1;
619    type Persian = <Persian as CldrCalendar>::SkeletaV1;
620    type Roc = <Roc as CldrCalendar>::SkeletaV1;
621}
622
623/// A type that can be converted into a specific calendar system.
624// This trait is implementable
625pub trait ConvertCalendar {
626    /// The converted type. This can be the same as the receiver type.
627    type Converted<'a>: Sized;
628    /// Converts `self` to the specified [`AnyCalendar`].
629    fn to_calendar<'a>(&self, calendar: &'a AnyCalendar) -> Self::Converted<'a>;
630}
631
632impl<C: IntoAnyCalendar, A: AsCalendar<Calendar = C>> ConvertCalendar for Date<A> {
633    type Converted<'a> = Date<Ref<'a, AnyCalendar>>;
634    #[inline]
635    fn to_calendar<'a>(&self, calendar: &'a AnyCalendar) -> Self::Converted<'a> {
636        self.to_calendar(Ref(calendar))
637    }
638}
639
640impl ConvertCalendar for Time {
641    type Converted<'a> = Time;
642    #[inline]
643    fn to_calendar<'a>(&self, _: &'a AnyCalendar) -> Self::Converted<'a> {
644        *self
645    }
646}
647
648impl<C: IntoAnyCalendar, A: AsCalendar<Calendar = C>> ConvertCalendar for DateTime<A> {
649    type Converted<'a> = DateTime<Ref<'a, AnyCalendar>>;
650    #[inline]
651    fn to_calendar<'a>(&self, calendar: &'a AnyCalendar) -> Self::Converted<'a> {
652        DateTime {
653            date: self.date.to_calendar(Ref(calendar)),
654            time: self.time,
655        }
656    }
657}
658
659impl<C: IntoAnyCalendar, A: AsCalendar<Calendar = C>, Z: Copy> ConvertCalendar
660    for ZonedDateTime<A, Z>
661{
662    type Converted<'a> = ZonedDateTime<Ref<'a, AnyCalendar>, Z>;
663    #[inline]
664    fn to_calendar<'a>(&self, calendar: &'a AnyCalendar) -> Self::Converted<'a> {
665        ZonedDateTime {
666            date: self.date.to_calendar(Ref(calendar)),
667            time: self.time,
668            zone: self.zone,
669        }
670    }
671}
672
673impl<O: TimeZoneModel> ConvertCalendar for TimeZoneInfo<O> {
674    type Converted<'a> = TimeZoneInfo<O>;
675    #[inline]
676    fn to_calendar<'a>(&self, _: &'a AnyCalendar) -> Self::Converted<'a> {
677        *self
678    }
679}
680
681/// An input that may be associated with a specific runtime calendar.
682// This trait is implementable
683pub trait InSameCalendar {
684    /// Checks whether this type is compatible with the given calendar.
685    ///
686    /// Types that are agnostic to calendar systems should return `Ok(())`.
687    fn check_any_calendar_kind(
688        &self,
689        any_calendar_kind: AnyCalendarKind,
690    ) -> Result<(), MismatchedCalendarError>;
691}
692
693impl<C: IntoAnyCalendar, A: AsCalendar<Calendar = C>> InSameCalendar for Date<A> {
694    #[inline]
695    fn check_any_calendar_kind(
696        &self,
697        any_calendar_kind: AnyCalendarKind,
698    ) -> Result<(), MismatchedCalendarError> {
699        if self.calendar().kind() == any_calendar_kind {
700            Ok(())
701        } else {
702            Err(MismatchedCalendarError {
703                this_kind: any_calendar_kind,
704                date_kind: Some(self.calendar().kind()),
705            })
706        }
707    }
708}
709
710impl InSameCalendar for Time {
711    #[inline]
712    fn check_any_calendar_kind(&self, _: AnyCalendarKind) -> Result<(), MismatchedCalendarError> {
713        Ok(())
714    }
715}
716
717impl<C: IntoAnyCalendar, A: AsCalendar<Calendar = C>> InSameCalendar for DateTime<A> {
718    #[inline]
719    fn check_any_calendar_kind(
720        &self,
721        any_calendar_kind: AnyCalendarKind,
722    ) -> Result<(), MismatchedCalendarError> {
723        self.date.check_any_calendar_kind(any_calendar_kind)
724    }
725}
726
727impl<C: IntoAnyCalendar, A: AsCalendar<Calendar = C>, Z> InSameCalendar for ZonedDateTime<A, Z> {
728    #[inline]
729    fn check_any_calendar_kind(
730        &self,
731        any_calendar_kind: AnyCalendarKind,
732    ) -> Result<(), MismatchedCalendarError> {
733        self.date.check_any_calendar_kind(any_calendar_kind)
734    }
735}
736
737impl InSameCalendar for UtcOffset {
738    #[inline]
739    fn check_any_calendar_kind(&self, _: AnyCalendarKind) -> Result<(), MismatchedCalendarError> {
740        Ok(())
741    }
742}
743
744impl<O: TimeZoneModel> InSameCalendar for TimeZoneInfo<O> {
745    #[inline]
746    fn check_any_calendar_kind(&self, _: AnyCalendarKind) -> Result<(), MismatchedCalendarError> {
747        Ok(())
748    }
749}
750
751/// An input associated with a fixed, static calendar.
752// This trait is implementable
753pub trait InFixedCalendar<C> {}
754
755impl<C: CldrCalendar, A: AsCalendar<Calendar = C>> InFixedCalendar<C> for Date<A> {}
756
757impl<C> InFixedCalendar<C> for Time {}
758
759impl<C: CldrCalendar, A: AsCalendar<Calendar = C>> InFixedCalendar<C> for DateTime<A> {}
760
761impl<C: CldrCalendar, A: AsCalendar<Calendar = C>, Z> InFixedCalendar<C> for ZonedDateTime<A, Z> {}
762
763impl<C> InFixedCalendar<C> for UtcOffset {}
764
765impl<C, O: TimeZoneModel> InFixedCalendar<C> for TimeZoneInfo<O> {}