1use crate::cal::iso::IsoDateInner;
8use crate::cal::*;
9use crate::error::{DateError, DateFromFieldsError};
10use crate::options::DateFromFieldsOptions;
11use crate::options::{DateAddOptions, DateDifferenceOptions};
12use crate::types::{DateFields, YearInfo};
13use crate::{types, AsCalendar, Calendar, Date, Ref};
14
15use crate::preferences::{CalendarAlgorithm, HijriCalendarAlgorithm};
16use icu_locale_core::preferences::define_preferences;
17use icu_provider::prelude::*;
18
19use core::fmt;
20
21define_preferences!(
22 [Copy]
24 CalendarPreferences,
25 {
26 calendar_algorithm: CalendarAlgorithm
28 }
29);
30
31#[derive(Debug, Clone)]
73#[non_exhaustive]
74pub enum AnyCalendar {
75 Buddhist(Buddhist),
77 Chinese(ChineseTraditional),
79 Coptic(Coptic),
81 Dangi(KoreanTraditional),
83 Ethiopian(Ethiopian),
85 Gregorian(Gregorian),
87 Hebrew(Hebrew),
89 Indian(Indian),
91 HijriTabular(Hijri<hijri::TabularAlgorithm>),
93 HijriSimulated(Hijri<hijri::AstronomicalSimulation>),
95 HijriUmmAlQura(Hijri<hijri::UmmAlQura>),
97 Iso(Iso),
99 Japanese(Japanese),
101 JapaneseExtended(JapaneseExtended),
103 Persian(Persian),
105 Roc(Roc),
107}
108
109#[derive(Clone, PartialEq, Eq, Debug, Copy)]
112#[non_exhaustive]
113pub enum AnyDateInner {
114 Buddhist(<Buddhist as Calendar>::DateInner),
116 Chinese(<ChineseTraditional as Calendar>::DateInner),
118 Coptic(<Coptic as Calendar>::DateInner),
120 Dangi(<KoreanTraditional as Calendar>::DateInner),
122 Ethiopian(<Ethiopian as Calendar>::DateInner),
124 Gregorian(<Gregorian as Calendar>::DateInner),
126 Hebrew(<Hebrew as Calendar>::DateInner),
128 Indian(<Indian as Calendar>::DateInner),
130 HijriTabular(
132 <Hijri<hijri::TabularAlgorithm> as Calendar>::DateInner,
133 hijri::TabularAlgorithm,
134 ),
135 HijriSimulated(<Hijri<hijri::AstronomicalSimulation> as Calendar>::DateInner),
137 HijriUmmAlQura(<Hijri<hijri::UmmAlQura> as Calendar>::DateInner),
139 Iso(<Iso as Calendar>::DateInner),
141 Japanese(<Japanese as Calendar>::DateInner),
143 JapaneseExtended(<JapaneseExtended as Calendar>::DateInner),
145 Persian(<Persian as Calendar>::DateInner),
147 Roc(<Roc as Calendar>::DateInner),
149}
150
151impl PartialOrd for AnyDateInner {
152 #[rustfmt::skip]
153 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
154 use AnyDateInner::*;
155 match (self, other) {
156 (Buddhist(d1), Buddhist(d2)) => d1.partial_cmp(d2),
157 (Chinese(d1), Chinese(d2)) => d1.partial_cmp(d2),
158 (Coptic(d1), Coptic(d2)) => d1.partial_cmp(d2),
159 (Dangi(d1), Dangi(d2)) => d1.partial_cmp(d2),
160 (Ethiopian(d1), Ethiopian(d2)) => d1.partial_cmp(d2),
161 (Gregorian(d1), Gregorian(d2)) => d1.partial_cmp(d2),
162 (Hebrew(d1), Hebrew(d2)) => d1.partial_cmp(d2),
163 (Indian(d1), Indian(d2)) => d1.partial_cmp(d2),
164 (&HijriTabular(ref d1, s1), &HijriTabular(ref d2, s2)) if s1 == s2 => d1.partial_cmp(d2),
165 (HijriSimulated(d1), HijriSimulated(d2)) => d1.partial_cmp(d2),
166 (HijriUmmAlQura(d1), HijriUmmAlQura(d2)) => d1.partial_cmp(d2),
167 (Iso(d1), Iso(d2)) => d1.partial_cmp(d2),
168 (Japanese(d1), Japanese(d2)) => d1.partial_cmp(d2),
169 (JapaneseExtended(d1), JapaneseExtended(d2)) => d1.partial_cmp(d2),
170 (Persian(d1), Persian(d2)) => d1.partial_cmp(d2),
171 (Roc(d1), Roc(d2)) => d1.partial_cmp(d2),
172 _ => None,
173 }
174 }
175}
176
177macro_rules! match_cal_and_date {
178 (match ($cal:ident, $date:ident): ($cal_matched:ident, $date_matched:ident) => $e:expr) => {
179 match ($cal, $date) {
180 (&Self::Buddhist(ref $cal_matched), &AnyDateInner::Buddhist(ref $date_matched)) => $e,
181 (&Self::Chinese(ref $cal_matched), &AnyDateInner::Chinese(ref $date_matched)) => $e,
182 (&Self::Coptic(ref $cal_matched), &AnyDateInner::Coptic(ref $date_matched)) => $e,
183 (&Self::Dangi(ref $cal_matched), &AnyDateInner::Dangi(ref $date_matched)) => $e,
184 (&Self::Ethiopian(ref $cal_matched), &AnyDateInner::Ethiopian(ref $date_matched)) => $e,
185 (&Self::Gregorian(ref $cal_matched), &AnyDateInner::Gregorian(ref $date_matched)) => $e,
186 (&Self::Hebrew(ref $cal_matched), &AnyDateInner::Hebrew(ref $date_matched)) => $e,
187 (&Self::Indian(ref $cal_matched), &AnyDateInner::Indian(ref $date_matched)) => $e,
188 (
189 &Self::HijriTabular(ref $cal_matched),
190 &AnyDateInner::HijriTabular(ref $date_matched, sighting),
191 ) if $cal_matched.0 == sighting => $e,
192 (
193 &Self::HijriSimulated(ref $cal_matched),
194 &AnyDateInner::HijriSimulated(ref $date_matched),
195 ) => $e,
196 (
197 &Self::HijriUmmAlQura(ref $cal_matched),
198 &AnyDateInner::HijriUmmAlQura(ref $date_matched),
199 ) => $e,
200 (&Self::Iso(ref $cal_matched), &AnyDateInner::Iso(ref $date_matched)) => $e,
201 (&Self::Japanese(ref $cal_matched), &AnyDateInner::Japanese(ref $date_matched)) => $e,
202 (
203 &Self::JapaneseExtended(ref $cal_matched),
204 &AnyDateInner::JapaneseExtended(ref $date_matched),
205 ) => $e,
206 (&Self::Persian(ref $cal_matched), &AnyDateInner::Persian(ref $date_matched)) => $e,
207 (&Self::Roc(ref $cal_matched), &AnyDateInner::Roc(ref $date_matched)) => $e,
208 _ => panic!("AnyCalendar with mismatched date type"),
210 }
211 };
212}
213
214macro_rules! match_cal {
215 (match $cal:ident: ($cal_matched:ident) => $e:expr) => {
216 match $cal {
217 &Self::Buddhist(ref $cal_matched) => AnyDateInner::Buddhist($e),
218 &Self::Chinese(ref $cal_matched) => AnyDateInner::Chinese($e),
219 &Self::Coptic(ref $cal_matched) => AnyDateInner::Coptic($e),
220 &Self::Dangi(ref $cal_matched) => AnyDateInner::Dangi($e),
221 &Self::Ethiopian(ref $cal_matched) => AnyDateInner::Ethiopian($e),
222 &Self::Gregorian(ref $cal_matched) => AnyDateInner::Gregorian($e),
223 &Self::Hebrew(ref $cal_matched) => AnyDateInner::Hebrew($e),
224 &Self::Indian(ref $cal_matched) => AnyDateInner::Indian($e),
225 &Self::HijriSimulated(ref $cal_matched) => AnyDateInner::HijriSimulated($e),
226 &Self::HijriTabular(ref $cal_matched) => AnyDateInner::HijriTabular($e, $cal_matched.0),
227 &Self::HijriUmmAlQura(ref $cal_matched) => AnyDateInner::HijriUmmAlQura($e),
228 &Self::Iso(ref $cal_matched) => AnyDateInner::Iso($e),
229 &Self::Japanese(ref $cal_matched) => AnyDateInner::Japanese($e),
230 &Self::JapaneseExtended(ref $cal_matched) => AnyDateInner::JapaneseExtended($e),
231 &Self::Persian(ref $cal_matched) => AnyDateInner::Persian($e),
232 &Self::Roc(ref $cal_matched) => AnyDateInner::Roc($e),
233 }
234 };
235}
236
237#[derive(Clone, Copy, PartialEq, Debug)]
239#[non_exhaustive]
240#[doc(hidden)] pub enum AnyCalendarDifferenceError {
242 MismatchedCalendars,
269}
270
271impl crate::cal::scaffold::UnstableSealed for AnyCalendar {}
272impl Calendar for AnyCalendar {
273 type DateInner = AnyDateInner;
274 type Year = YearInfo;
275 type DifferenceError = AnyCalendarDifferenceError;
276
277 fn from_codes(
278 &self,
279 era: Option<&str>,
280 year: i32,
281 month_code: types::MonthCode,
282 day: u8,
283 ) -> Result<Self::DateInner, DateError> {
284 Ok(match_cal!(match self: (c) => c.from_codes(era, year, month_code, day)?))
285 }
286
287 #[cfg(feature = "unstable")]
288 fn from_fields(
289 &self,
290 fields: DateFields,
291 options: DateFromFieldsOptions,
292 ) -> Result<Self::DateInner, DateFromFieldsError> {
293 Ok(match_cal!(match self: (c) => c.from_fields(fields, options)?))
294 }
295
296 fn has_cheap_iso_conversion(&self) -> bool {
297 match self {
298 Self::Buddhist(ref c) => c.has_cheap_iso_conversion(),
299 Self::Chinese(ref c) => c.has_cheap_iso_conversion(),
300 Self::Coptic(ref c) => c.has_cheap_iso_conversion(),
301 Self::Dangi(ref c) => c.has_cheap_iso_conversion(),
302 Self::Ethiopian(ref c) => c.has_cheap_iso_conversion(),
303 Self::Gregorian(ref c) => c.has_cheap_iso_conversion(),
304 Self::Hebrew(ref c) => c.has_cheap_iso_conversion(),
305 Self::Indian(ref c) => c.has_cheap_iso_conversion(),
306 Self::HijriSimulated(ref c) => c.has_cheap_iso_conversion(),
307 Self::HijriTabular(ref c) => c.has_cheap_iso_conversion(),
308 Self::HijriUmmAlQura(ref c) => c.has_cheap_iso_conversion(),
309 Self::Iso(ref c) => c.has_cheap_iso_conversion(),
310 Self::Japanese(ref c) => c.has_cheap_iso_conversion(),
311 Self::JapaneseExtended(ref c) => c.has_cheap_iso_conversion(),
312 Self::Persian(ref c) => c.has_cheap_iso_conversion(),
313 Self::Roc(ref c) => c.has_cheap_iso_conversion(),
314 }
315 }
316
317 fn from_iso(&self, iso: IsoDateInner) -> AnyDateInner {
318 match_cal!(match self: (c) => c.from_iso(iso))
319 }
320
321 fn to_iso(&self, date: &Self::DateInner) -> IsoDateInner {
322 match_cal_and_date!(match (self, date): (c, d) => c.to_iso(d))
323 }
324
325 fn from_rata_die(&self, rd: calendrical_calculations::rata_die::RataDie) -> Self::DateInner {
326 match_cal!(match self: (c) => c.from_rata_die(rd))
327 }
328
329 fn to_rata_die(&self, date: &Self::DateInner) -> calendrical_calculations::rata_die::RataDie {
330 match_cal_and_date!(match (self, date): (c, d) => c.to_rata_die(d))
331 }
332
333 fn months_in_year(&self, date: &Self::DateInner) -> u8 {
334 match_cal_and_date!(match (self, date): (c, d) => c.months_in_year(d))
335 }
336
337 fn days_in_year(&self, date: &Self::DateInner) -> u16 {
338 match_cal_and_date!(match (self, date): (c, d) => c.days_in_year(d))
339 }
340
341 fn days_in_month(&self, date: &Self::DateInner) -> u8 {
342 match_cal_and_date!(match (self, date): (c, d) => c.days_in_month(d))
343 }
344
345 #[cfg(feature = "unstable")]
346 fn add(
347 &self,
348 date: &Self::DateInner,
349 duration: types::DateDuration,
350 options: DateAddOptions,
351 ) -> Result<Self::DateInner, DateError> {
352 let mut date = *date;
353 match (self, &mut date) {
354 (Self::Buddhist(c), AnyDateInner::Buddhist(ref mut d)) => {
355 *d = c.add(d, duration, options)?
356 }
357 (Self::Chinese(c), AnyDateInner::Chinese(ref mut d)) => {
358 *d = c.add(d, duration, options)?
359 }
360 (Self::Coptic(c), AnyDateInner::Coptic(ref mut d)) => {
361 *d = c.add(d, duration, options)?
362 }
363 (Self::Dangi(c), AnyDateInner::Dangi(ref mut d)) => *d = c.add(d, duration, options)?,
364 (Self::Ethiopian(c), AnyDateInner::Ethiopian(ref mut d)) => {
365 *d = c.add(d, duration, options)?
366 }
367 (Self::Gregorian(c), AnyDateInner::Gregorian(ref mut d)) => {
368 *d = c.add(d, duration, options)?
369 }
370 (Self::Hebrew(c), AnyDateInner::Hebrew(ref mut d)) => {
371 *d = c.add(d, duration, options)?
372 }
373 (Self::Indian(c), AnyDateInner::Indian(ref mut d)) => {
374 *d = c.add(d, duration, options)?
375 }
376 (Self::HijriTabular(c), AnyDateInner::HijriTabular(ref mut d, sighting))
377 if c.0 == *sighting =>
378 {
379 *d = c.add(d, duration, options)?
380 }
381 (Self::HijriSimulated(c), AnyDateInner::HijriSimulated(ref mut d)) => {
382 *d = c.add(d, duration, options)?
383 }
384 (Self::HijriUmmAlQura(c), AnyDateInner::HijriUmmAlQura(ref mut d)) => {
385 *d = c.add(d, duration, options)?
386 }
387 (Self::Iso(c), AnyDateInner::Iso(ref mut d)) => *d = c.add(d, duration, options)?,
388 (Self::Japanese(c), AnyDateInner::Japanese(ref mut d)) => {
389 *d = c.add(d, duration, options)?
390 }
391 (Self::JapaneseExtended(c), AnyDateInner::JapaneseExtended(ref mut d)) => {
392 *d = c.add(d, duration, options)?
393 }
394 (Self::Persian(c), AnyDateInner::Persian(ref mut d)) => {
395 *d = c.add(d, duration, options)?
396 }
397 (Self::Roc(c), AnyDateInner::Roc(ref mut d)) => *d = c.add(d, duration, options)?,
398 #[expect(clippy::panic)]
400 _ => panic!("AnyCalendar with mismatched date type"),
401 }
402 Ok(date)
403 }
404
405 #[cfg(feature = "unstable")]
406 fn until(
407 &self,
408 date1: &Self::DateInner,
409 date2: &Self::DateInner,
410 options: DateDifferenceOptions,
411 ) -> Result<types::DateDuration, Self::DifferenceError> {
412 let Ok(r) = match (self, date1, date2) {
413 (Self::Buddhist(c1), AnyDateInner::Buddhist(d1), AnyDateInner::Buddhist(d2)) => {
414 c1.until(d1, d2, options)
415 }
416 (Self::Chinese(c1), AnyDateInner::Chinese(d1), AnyDateInner::Chinese(d2)) => {
417 c1.until(d1, d2, options)
418 }
419 (Self::Coptic(c1), AnyDateInner::Coptic(d1), AnyDateInner::Coptic(d2)) => {
420 c1.until(d1, d2, options)
421 }
422 (Self::Dangi(c1), AnyDateInner::Dangi(d1), AnyDateInner::Dangi(d2)) => {
423 c1.until(d1, d2, options)
424 }
425 (Self::Ethiopian(c1), AnyDateInner::Ethiopian(d1), AnyDateInner::Ethiopian(d2)) => {
426 c1.until(d1, d2, options)
427 }
428 (Self::Gregorian(c1), AnyDateInner::Gregorian(d1), AnyDateInner::Gregorian(d2)) => {
429 c1.until(d1, d2, options)
430 }
431 (Self::Hebrew(c1), AnyDateInner::Hebrew(d1), AnyDateInner::Hebrew(d2)) => {
432 c1.until(d1, d2, options)
433 }
434 (Self::Indian(c1), AnyDateInner::Indian(d1), AnyDateInner::Indian(d2)) => {
435 c1.until(d1, d2, options)
436 }
437 (
438 Self::HijriTabular(c1),
439 &AnyDateInner::HijriTabular(ref d1, s1),
440 &AnyDateInner::HijriTabular(ref d2, s2),
441 ) if c1.0 == s1 && s1 == s2 => c1.until(d1, d2, options),
442 (
443 Self::HijriSimulated(c1),
444 AnyDateInner::HijriSimulated(d1),
445 AnyDateInner::HijriSimulated(d2),
446 ) => c1.until(d1, d2, options),
447 (
448 Self::HijriUmmAlQura(c1),
449 AnyDateInner::HijriUmmAlQura(d1),
450 AnyDateInner::HijriUmmAlQura(d2),
451 ) => c1.until(d1, d2, options),
452 (Self::Iso(c1), AnyDateInner::Iso(d1), AnyDateInner::Iso(d2)) => {
453 c1.until(d1, d2, options)
454 }
455 (Self::Japanese(c1), AnyDateInner::Japanese(d1), AnyDateInner::Japanese(d2)) => {
456 c1.until(d1, d2, options)
457 }
458 (
459 Self::JapaneseExtended(c1),
460 AnyDateInner::JapaneseExtended(d1),
461 AnyDateInner::JapaneseExtended(d2),
462 ) => c1.until(d1, d2, options),
463 (Self::Persian(c1), AnyDateInner::Persian(d1), AnyDateInner::Persian(d2)) => {
464 c1.until(d1, d2, options)
465 }
466 (Self::Roc(c1), AnyDateInner::Roc(d1), AnyDateInner::Roc(d2)) => {
467 c1.until(d1, d2, options)
468 }
469 _ => {
470 return Err(AnyCalendarDifferenceError::MismatchedCalendars);
471 }
472 };
473 Ok(r)
474 }
475
476 fn year_info(&self, date: &Self::DateInner) -> types::YearInfo {
477 match_cal_and_date!(match (self, date): (c, d) => c.year_info(d).into())
478 }
479
480 fn is_in_leap_year(&self, date: &Self::DateInner) -> bool {
482 match_cal_and_date!(match (self, date): (c, d) => c.is_in_leap_year(d))
483 }
484
485 fn month(&self, date: &Self::DateInner) -> types::MonthInfo {
487 match_cal_and_date!(match (self, date): (c, d) => c.month(d))
488 }
489
490 fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth {
492 match_cal_and_date!(match (self, date): (c, d) => c.day_of_month(d))
493 }
494
495 fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear {
497 match_cal_and_date!(match (self, date): (c, d) => c.day_of_year(d))
498 }
499
500 fn debug_name(&self) -> &'static str {
501 match self.kind() {
502 AnyCalendarKind::Buddhist => "AnyCalendar (Buddhist)",
503 AnyCalendarKind::Chinese => "AnyCalendar (Chinese)",
504 AnyCalendarKind::Coptic => "AnyCalendar (Coptic)",
505 AnyCalendarKind::Dangi => "AnyCalendar (Dangi)",
506 AnyCalendarKind::Ethiopian => "AnyCalendar (Ethiopian, Amete Miret)",
507 AnyCalendarKind::EthiopianAmeteAlem => "AnyCalendar (Ethiopian, Amete Alem)",
508 AnyCalendarKind::Gregorian => "AnyCalendar (Gregorian)",
509 AnyCalendarKind::Hebrew => "AnyCalendar (Hebrew)",
510 AnyCalendarKind::Indian => "AnyCalendar (Indian)",
511 AnyCalendarKind::HijriTabularTypeIIFriday => {
512 "AnyCalendar (Hijri, tabular, type II leap years, Friday epoch)"
513 }
514 AnyCalendarKind::HijriTabularTypeIIThursday => {
515 "AnyCalendar (Hijri, tabular, type II leap years, Thursday epoch)"
516 }
517 AnyCalendarKind::HijriSimulatedMecca => "AnyCalendar (Hijri, simulated Mecca)",
518 AnyCalendarKind::HijriUmmAlQura => "AnyCalendar (Hijri, Umm al-Qura)",
519 AnyCalendarKind::Iso => "AnyCalendar (Iso)",
520 AnyCalendarKind::Japanese => "AnyCalendar (Japanese)",
521 AnyCalendarKind::JapaneseExtended => "AnyCalendar (Japanese, historical era data)",
522 AnyCalendarKind::Persian => "AnyCalendar (Persian)",
523 AnyCalendarKind::Roc => "AnyCalendar (Roc)",
524 }
525 }
526
527 fn calendar_algorithm(&self) -> Option<CalendarAlgorithm> {
528 match self {
529 Self::Buddhist(ref c) => c.calendar_algorithm(),
530 Self::Chinese(ref c) => c.calendar_algorithm(),
531 Self::Coptic(ref c) => c.calendar_algorithm(),
532 Self::Dangi(ref c) => c.calendar_algorithm(),
533 Self::Ethiopian(ref c) => c.calendar_algorithm(),
534 Self::Gregorian(ref c) => c.calendar_algorithm(),
535 Self::Hebrew(ref c) => c.calendar_algorithm(),
536 Self::Indian(ref c) => c.calendar_algorithm(),
537 Self::HijriSimulated(ref c) => c.calendar_algorithm(),
538 Self::HijriTabular(ref c) => c.calendar_algorithm(),
539 Self::HijriUmmAlQura(ref c) => c.calendar_algorithm(),
540 Self::Iso(ref c) => c.calendar_algorithm(),
541 Self::Japanese(ref c) => c.calendar_algorithm(),
542 Self::JapaneseExtended(ref c) => c.calendar_algorithm(),
543 Self::Persian(ref c) => c.calendar_algorithm(),
544 Self::Roc(ref c) => c.calendar_algorithm(),
545 }
546 }
547}
548
549impl AnyCalendar {
550 #[cfg(feature = "compiled_data")]
556 pub const fn new(kind: AnyCalendarKind) -> Self {
557 match kind {
558 AnyCalendarKind::Buddhist => AnyCalendar::Buddhist(Buddhist),
559 AnyCalendarKind::Chinese => AnyCalendar::Chinese(ChineseTraditional::new()),
560 AnyCalendarKind::Coptic => AnyCalendar::Coptic(Coptic),
561 AnyCalendarKind::Dangi => AnyCalendar::Dangi(KoreanTraditional::new()),
562 AnyCalendarKind::Ethiopian => AnyCalendar::Ethiopian(Ethiopian::new_with_era_style(
563 EthiopianEraStyle::AmeteMihret,
564 )),
565 AnyCalendarKind::EthiopianAmeteAlem => {
566 AnyCalendar::Ethiopian(Ethiopian::new_with_era_style(EthiopianEraStyle::AmeteAlem))
567 }
568 AnyCalendarKind::Gregorian => AnyCalendar::Gregorian(Gregorian),
569 AnyCalendarKind::Hebrew => AnyCalendar::Hebrew(Hebrew),
570 AnyCalendarKind::Indian => AnyCalendar::Indian(Indian),
571 AnyCalendarKind::HijriTabularTypeIIFriday => {
572 AnyCalendar::HijriTabular(Hijri::new_tabular(
573 hijri::TabularAlgorithmLeapYears::TypeII,
574 hijri::TabularAlgorithmEpoch::Friday,
575 ))
576 }
577 AnyCalendarKind::HijriSimulatedMecca => {
578 AnyCalendar::HijriSimulated(Hijri::new_simulated_mecca())
579 }
580 AnyCalendarKind::HijriTabularTypeIIThursday => {
581 AnyCalendar::HijriTabular(Hijri::new_tabular(
582 hijri::TabularAlgorithmLeapYears::TypeII,
583 hijri::TabularAlgorithmEpoch::Thursday,
584 ))
585 }
586 AnyCalendarKind::HijriUmmAlQura => {
587 AnyCalendar::HijriUmmAlQura(Hijri::new_umm_al_qura())
588 }
589 AnyCalendarKind::Iso => AnyCalendar::Iso(Iso),
590 AnyCalendarKind::Japanese => AnyCalendar::Japanese(Japanese::new()),
591 AnyCalendarKind::JapaneseExtended => {
592 AnyCalendar::JapaneseExtended(JapaneseExtended::new())
593 }
594 AnyCalendarKind::Persian => AnyCalendar::Persian(Persian),
595 AnyCalendarKind::Roc => AnyCalendar::Roc(Roc),
596 }
597 }
598
599 #[cfg(feature = "serde")]
600 #[doc = icu_provider::gen_buffer_unstable_docs!(BUFFER, Self::new)]
601 pub fn try_new_with_buffer_provider<P>(
602 provider: &P,
603 kind: AnyCalendarKind,
604 ) -> Result<Self, DataError>
605 where
606 P: BufferProvider + ?Sized,
607 {
608 Ok(match kind {
609 AnyCalendarKind::Buddhist => AnyCalendar::Buddhist(Buddhist),
610 AnyCalendarKind::Chinese => AnyCalendar::Chinese(ChineseTraditional::new()),
611 AnyCalendarKind::Coptic => AnyCalendar::Coptic(Coptic),
612 AnyCalendarKind::Dangi => AnyCalendar::Dangi(KoreanTraditional::new()),
613 AnyCalendarKind::Ethiopian => AnyCalendar::Ethiopian(Ethiopian::new_with_era_style(
614 EthiopianEraStyle::AmeteMihret,
615 )),
616 AnyCalendarKind::EthiopianAmeteAlem => {
617 AnyCalendar::Ethiopian(Ethiopian::new_with_era_style(EthiopianEraStyle::AmeteAlem))
618 }
619 AnyCalendarKind::Gregorian => AnyCalendar::Gregorian(Gregorian),
620 AnyCalendarKind::Hebrew => AnyCalendar::Hebrew(Hebrew),
621 AnyCalendarKind::Indian => AnyCalendar::Indian(Indian),
622 AnyCalendarKind::HijriTabularTypeIIFriday => {
623 AnyCalendar::HijriTabular(Hijri::new_tabular(
624 hijri::TabularAlgorithmLeapYears::TypeII,
625 hijri::TabularAlgorithmEpoch::Friday,
626 ))
627 }
628 AnyCalendarKind::HijriSimulatedMecca => {
629 AnyCalendar::HijriSimulated(Hijri::new_simulated_mecca())
630 }
631 AnyCalendarKind::HijriTabularTypeIIThursday => {
632 AnyCalendar::HijriTabular(Hijri::new_tabular(
633 hijri::TabularAlgorithmLeapYears::TypeII,
634 hijri::TabularAlgorithmEpoch::Thursday,
635 ))
636 }
637 AnyCalendarKind::HijriUmmAlQura => {
638 AnyCalendar::HijriUmmAlQura(Hijri::new_umm_al_qura())
639 }
640 AnyCalendarKind::Iso => AnyCalendar::Iso(Iso),
641 AnyCalendarKind::Japanese => {
642 AnyCalendar::Japanese(Japanese::try_new_with_buffer_provider(provider)?)
643 }
644 AnyCalendarKind::JapaneseExtended => AnyCalendar::JapaneseExtended(
645 JapaneseExtended::try_new_with_buffer_provider(provider)?,
646 ),
647 AnyCalendarKind::Persian => AnyCalendar::Persian(Persian),
648 AnyCalendarKind::Roc => AnyCalendar::Roc(Roc),
649 })
650 }
651
652 #[doc = icu_provider::gen_buffer_unstable_docs!(UNSTABLE, Self::new)]
653 pub fn try_new_unstable<P>(provider: &P, kind: AnyCalendarKind) -> Result<Self, DataError>
654 where
655 P: DataProvider<crate::provider::CalendarJapaneseModernV1>
656 + DataProvider<crate::provider::CalendarJapaneseExtendedV1>
657 + ?Sized,
658 {
659 Ok(match kind {
660 AnyCalendarKind::Buddhist => AnyCalendar::Buddhist(Buddhist),
661 AnyCalendarKind::Chinese => AnyCalendar::Chinese(ChineseTraditional::new()),
662 AnyCalendarKind::Coptic => AnyCalendar::Coptic(Coptic),
663 AnyCalendarKind::Dangi => AnyCalendar::Dangi(KoreanTraditional::new()),
664 AnyCalendarKind::Ethiopian => AnyCalendar::Ethiopian(Ethiopian::new_with_era_style(
665 EthiopianEraStyle::AmeteMihret,
666 )),
667 AnyCalendarKind::EthiopianAmeteAlem => {
668 AnyCalendar::Ethiopian(Ethiopian::new_with_era_style(EthiopianEraStyle::AmeteAlem))
669 }
670 AnyCalendarKind::Gregorian => AnyCalendar::Gregorian(Gregorian),
671 AnyCalendarKind::Hebrew => AnyCalendar::Hebrew(Hebrew),
672 AnyCalendarKind::Indian => AnyCalendar::Indian(Indian),
673 AnyCalendarKind::HijriTabularTypeIIFriday => {
674 AnyCalendar::HijriTabular(Hijri::new_tabular(
675 hijri::TabularAlgorithmLeapYears::TypeII,
676 hijri::TabularAlgorithmEpoch::Friday,
677 ))
678 }
679 AnyCalendarKind::HijriSimulatedMecca => {
680 AnyCalendar::HijriSimulated(Hijri::new_simulated_mecca())
681 }
682 AnyCalendarKind::HijriTabularTypeIIThursday => {
683 AnyCalendar::HijriTabular(Hijri::new_tabular(
684 hijri::TabularAlgorithmLeapYears::TypeII,
685 hijri::TabularAlgorithmEpoch::Thursday,
686 ))
687 }
688 AnyCalendarKind::HijriUmmAlQura => {
689 AnyCalendar::HijriUmmAlQura(Hijri::new_umm_al_qura())
690 }
691 AnyCalendarKind::Iso => AnyCalendar::Iso(Iso),
692 AnyCalendarKind::Japanese => {
693 AnyCalendar::Japanese(Japanese::try_new_unstable(provider)?)
694 }
695 AnyCalendarKind::JapaneseExtended => {
696 AnyCalendar::JapaneseExtended(JapaneseExtended::try_new_unstable(provider)?)
697 }
698 AnyCalendarKind::Persian => AnyCalendar::Persian(Persian),
699 AnyCalendarKind::Roc => AnyCalendar::Roc(Roc),
700 })
701 }
702
703 pub fn kind(&self) -> AnyCalendarKind {
705 match *self {
706 Self::Buddhist(_) => AnyCalendarKind::Buddhist,
707 Self::Chinese(_) => AnyCalendarKind::Chinese,
708 Self::Coptic(_) => AnyCalendarKind::Coptic,
709 Self::Dangi(_) => AnyCalendarKind::Dangi,
710 Self::Ethiopian(ref e) => IntoAnyCalendar::kind(e),
711 Self::Gregorian(_) => AnyCalendarKind::Gregorian,
712 Self::Hebrew(_) => AnyCalendarKind::Hebrew,
713 Self::Indian(_) => AnyCalendarKind::Indian,
714 Self::HijriTabular(ref h) => IntoAnyCalendar::kind(h),
715 Self::HijriSimulated(ref h) => IntoAnyCalendar::kind(h),
716 Self::HijriUmmAlQura(_) => AnyCalendarKind::HijriUmmAlQura,
717 Self::Iso(_) => AnyCalendarKind::Iso,
718 Self::Japanese(_) => AnyCalendarKind::Japanese,
719 Self::JapaneseExtended(_) => AnyCalendarKind::JapaneseExtended,
720 Self::Persian(_) => AnyCalendarKind::Persian,
721 Self::Roc(_) => AnyCalendarKind::Roc,
722 }
723 }
724}
725
726impl<C: AsCalendar<Calendar = AnyCalendar>> Date<C> {
727 pub fn convert_any<'a>(&self, calendar: &'a AnyCalendar) -> Date<Ref<'a, AnyCalendar>> {
729 if calendar.kind() != self.calendar.as_calendar().kind() {
730 Date::new_from_iso(self.to_iso(), Ref(calendar))
731 } else {
732 Date {
733 inner: self.inner,
734 calendar: Ref(calendar),
735 }
736 }
737 }
738}
739
740#[non_exhaustive]
742#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
743pub enum AnyCalendarKind {
744 Buddhist,
748 Chinese,
752 Coptic,
756 Dangi,
760 Ethiopian,
764 EthiopianAmeteAlem,
768 Gregorian,
772 Hebrew,
776 Indian,
780 HijriTabularTypeIIFriday,
784 HijriSimulatedMecca,
788 HijriTabularTypeIIThursday,
792 HijriUmmAlQura,
796 Iso,
800 Japanese,
804 JapaneseExtended,
808 Persian,
812 Roc,
816}
817
818impl AnyCalendarKind {
819 pub fn new(prefs: CalendarPreferences) -> Self {
821 if let Some(kind) = prefs.calendar_algorithm.and_then(|a| a.try_into().ok()) {
822 return kind;
823 }
824
825 match (
827 prefs.calendar_algorithm,
828 prefs
829 .locale_preferences
830 .region()
831 .as_ref()
832 .map(|r| r.as_str()),
833 ) {
834 (Some(CalendarAlgorithm::Hijri(None)), Some("AE" | "BH" | "KW" | "QA" | "SA")) => {
835 AnyCalendarKind::HijriUmmAlQura
836 }
837 (Some(CalendarAlgorithm::Hijri(None)), _) => AnyCalendarKind::HijriTabularTypeIIFriday,
838 (_, Some("TH")) => AnyCalendarKind::Buddhist,
839 (_, Some("AF" | "IR")) => AnyCalendarKind::Persian,
840 _ => AnyCalendarKind::Gregorian,
841 }
842 }
843}
844
845impl TryFrom<CalendarAlgorithm> for AnyCalendarKind {
846 type Error = ();
847 fn try_from(v: CalendarAlgorithm) -> Result<Self, Self::Error> {
848 use CalendarAlgorithm::*;
849 match v {
850 Buddhist => Ok(AnyCalendarKind::Buddhist),
851 Chinese => Ok(AnyCalendarKind::Chinese),
852 Coptic => Ok(AnyCalendarKind::Coptic),
853 Dangi => Ok(AnyCalendarKind::Dangi),
854 Ethioaa => Ok(AnyCalendarKind::EthiopianAmeteAlem),
855 Ethiopic => Ok(AnyCalendarKind::Ethiopian),
856 Gregory => Ok(AnyCalendarKind::Gregorian),
857 Hebrew => Ok(AnyCalendarKind::Hebrew),
858 Indian => Ok(AnyCalendarKind::Indian),
859 Hijri(None) => Err(()),
860 Hijri(Some(HijriCalendarAlgorithm::Umalqura)) => Ok(AnyCalendarKind::HijriUmmAlQura),
861 Hijri(Some(HijriCalendarAlgorithm::Tbla)) => {
862 Ok(AnyCalendarKind::HijriTabularTypeIIThursday)
863 }
864 Hijri(Some(HijriCalendarAlgorithm::Civil)) => {
865 Ok(AnyCalendarKind::HijriTabularTypeIIFriday)
866 }
867 Hijri(Some(HijriCalendarAlgorithm::Rgsa)) => Ok(AnyCalendarKind::HijriSimulatedMecca),
868 Iso8601 => Ok(AnyCalendarKind::Iso),
869 Japanese => Ok(AnyCalendarKind::Japanese),
870 Persian => Ok(AnyCalendarKind::Persian),
871 Roc => Ok(AnyCalendarKind::Roc),
872 _ => {
873 debug_assert!(false, "unknown calendar algorithm {v:?}");
874 Err(())
875 }
876 }
877 }
878}
879
880impl fmt::Display for AnyCalendarKind {
881 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
882 fmt::Debug::fmt(self, f)
883 }
884}
885
886pub trait IntoAnyCalendar: Calendar + Sized {
888 fn to_any(self) -> AnyCalendar;
892
893 fn kind(&self) -> AnyCalendarKind;
895
896 fn from_any(any: AnyCalendar) -> Result<Self, AnyCalendar>;
901
902 fn from_any_ref(any: &AnyCalendar) -> Option<&Self>;
906
907 fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner;
911}
912
913impl IntoAnyCalendar for AnyCalendar {
914 #[inline]
915 fn to_any(self) -> AnyCalendar {
916 self
917 }
918 #[inline]
919 fn kind(&self) -> AnyCalendarKind {
920 self.kind()
921 }
922 #[inline]
923 fn from_any(any: AnyCalendar) -> Result<Self, AnyCalendar> {
924 Ok(any)
925 }
926 #[inline]
927 fn from_any_ref(any: &AnyCalendar) -> Option<&Self> {
928 Some(any)
929 }
930 #[inline]
931 fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner {
932 *d
933 }
934}
935
936impl IntoAnyCalendar for Buddhist {
937 #[inline]
938 fn to_any(self) -> AnyCalendar {
939 AnyCalendar::Buddhist(Buddhist)
940 }
941 #[inline]
942 fn kind(&self) -> AnyCalendarKind {
943 AnyCalendarKind::Buddhist
944 }
945 #[inline]
946 fn from_any(any: AnyCalendar) -> Result<Self, AnyCalendar> {
947 if let AnyCalendar::Buddhist(cal) = any {
948 Ok(cal)
949 } else {
950 Err(any)
951 }
952 }
953 #[inline]
954 fn from_any_ref(any: &AnyCalendar) -> Option<&Self> {
955 if let AnyCalendar::Buddhist(cal) = any {
956 Some(cal)
957 } else {
958 None
959 }
960 }
961 #[inline]
962 fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner {
963 AnyDateInner::Buddhist(*d)
964 }
965}
966
967impl From<Buddhist> for AnyCalendar {
968 fn from(value: Buddhist) -> AnyCalendar {
969 value.to_any()
970 }
971}
972
973impl IntoAnyCalendar for ChineseTraditional {
974 #[inline]
975 fn to_any(self) -> AnyCalendar {
976 AnyCalendar::Chinese(self)
977 }
978 #[inline]
979 fn kind(&self) -> AnyCalendarKind {
980 AnyCalendarKind::Chinese
981 }
982 #[inline]
983 fn from_any(any: AnyCalendar) -> Result<Self, AnyCalendar> {
984 if let AnyCalendar::Chinese(cal) = any {
985 Ok(cal)
986 } else {
987 Err(any)
988 }
989 }
990 #[inline]
991 fn from_any_ref(any: &AnyCalendar) -> Option<&Self> {
992 if let AnyCalendar::Chinese(cal) = any {
993 Some(cal)
994 } else {
995 None
996 }
997 }
998 #[inline]
999 fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner {
1000 AnyDateInner::Chinese(*d)
1001 }
1002}
1003
1004impl From<ChineseTraditional> for AnyCalendar {
1005 fn from(value: ChineseTraditional) -> AnyCalendar {
1006 value.to_any()
1007 }
1008}
1009
1010impl IntoAnyCalendar for Coptic {
1011 #[inline]
1012 fn to_any(self) -> AnyCalendar {
1013 AnyCalendar::Coptic(Coptic)
1014 }
1015 #[inline]
1016 fn kind(&self) -> AnyCalendarKind {
1017 AnyCalendarKind::Coptic
1018 }
1019 #[inline]
1020 fn from_any(any: AnyCalendar) -> Result<Self, AnyCalendar> {
1021 if let AnyCalendar::Coptic(cal) = any {
1022 Ok(cal)
1023 } else {
1024 Err(any)
1025 }
1026 }
1027 #[inline]
1028 fn from_any_ref(any: &AnyCalendar) -> Option<&Self> {
1029 if let AnyCalendar::Coptic(cal) = any {
1030 Some(cal)
1031 } else {
1032 None
1033 }
1034 }
1035 #[inline]
1036 fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner {
1037 AnyDateInner::Coptic(*d)
1038 }
1039}
1040
1041impl From<Coptic> for AnyCalendar {
1042 fn from(value: Coptic) -> AnyCalendar {
1043 value.to_any()
1044 }
1045}
1046
1047impl IntoAnyCalendar for KoreanTraditional {
1048 #[inline]
1049 fn to_any(self) -> AnyCalendar {
1050 AnyCalendar::Dangi(self)
1051 }
1052 #[inline]
1053 fn kind(&self) -> AnyCalendarKind {
1054 AnyCalendarKind::Dangi
1055 }
1056 #[inline]
1057 fn from_any(any: AnyCalendar) -> Result<Self, AnyCalendar> {
1058 if let AnyCalendar::Dangi(cal) = any {
1059 Ok(cal)
1060 } else {
1061 Err(any)
1062 }
1063 }
1064 #[inline]
1065 fn from_any_ref(any: &AnyCalendar) -> Option<&Self> {
1066 if let AnyCalendar::Dangi(cal) = any {
1067 Some(cal)
1068 } else {
1069 None
1070 }
1071 }
1072 #[inline]
1073 fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner {
1074 AnyDateInner::Dangi(*d)
1075 }
1076}
1077
1078impl From<KoreanTraditional> for AnyCalendar {
1079 fn from(value: KoreanTraditional) -> AnyCalendar {
1080 value.to_any()
1081 }
1082}
1083
1084impl IntoAnyCalendar for Ethiopian {
1085 #[inline]
1087 fn to_any(self) -> AnyCalendar {
1088 AnyCalendar::Ethiopian(self)
1089 }
1090 #[inline]
1091 fn kind(&self) -> AnyCalendarKind {
1092 match self.era_style() {
1093 EthiopianEraStyle::AmeteAlem => AnyCalendarKind::EthiopianAmeteAlem,
1094 EthiopianEraStyle::AmeteMihret => AnyCalendarKind::Ethiopian,
1095 }
1096 }
1097 #[inline]
1098 fn from_any(any: AnyCalendar) -> Result<Self, AnyCalendar> {
1099 if let AnyCalendar::Ethiopian(cal) = any {
1100 Ok(cal)
1101 } else {
1102 Err(any)
1103 }
1104 }
1105 #[inline]
1106 fn from_any_ref(any: &AnyCalendar) -> Option<&Self> {
1107 if let AnyCalendar::Ethiopian(cal) = any {
1108 Some(cal)
1109 } else {
1110 None
1111 }
1112 }
1113 #[inline]
1114 fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner {
1115 AnyDateInner::Ethiopian(*d)
1116 }
1117}
1118
1119impl From<Ethiopian> for AnyCalendar {
1120 fn from(value: Ethiopian) -> AnyCalendar {
1121 value.to_any()
1122 }
1123}
1124
1125impl IntoAnyCalendar for Gregorian {
1126 #[inline]
1127 fn to_any(self) -> AnyCalendar {
1128 AnyCalendar::Gregorian(Gregorian)
1129 }
1130 #[inline]
1131 fn kind(&self) -> AnyCalendarKind {
1132 AnyCalendarKind::Gregorian
1133 }
1134 #[inline]
1135 fn from_any(any: AnyCalendar) -> Result<Self, AnyCalendar> {
1136 if let AnyCalendar::Gregorian(cal) = any {
1137 Ok(cal)
1138 } else {
1139 Err(any)
1140 }
1141 }
1142 #[inline]
1143 fn from_any_ref(any: &AnyCalendar) -> Option<&Self> {
1144 if let AnyCalendar::Gregorian(cal) = any {
1145 Some(cal)
1146 } else {
1147 None
1148 }
1149 }
1150 #[inline]
1151 fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner {
1152 AnyDateInner::Gregorian(*d)
1153 }
1154}
1155
1156impl From<Gregorian> for AnyCalendar {
1157 fn from(value: Gregorian) -> AnyCalendar {
1158 value.to_any()
1159 }
1160}
1161
1162impl IntoAnyCalendar for Hebrew {
1163 #[inline]
1164 fn to_any(self) -> AnyCalendar {
1165 AnyCalendar::Hebrew(Hebrew)
1166 }
1167 #[inline]
1168 fn kind(&self) -> AnyCalendarKind {
1169 AnyCalendarKind::Hebrew
1170 }
1171 #[inline]
1172 fn from_any(any: AnyCalendar) -> Result<Self, AnyCalendar> {
1173 if let AnyCalendar::Hebrew(cal) = any {
1174 Ok(cal)
1175 } else {
1176 Err(any)
1177 }
1178 }
1179 #[inline]
1180 fn from_any_ref(any: &AnyCalendar) -> Option<&Self> {
1181 if let AnyCalendar::Hebrew(cal) = any {
1182 Some(cal)
1183 } else {
1184 None
1185 }
1186 }
1187 #[inline]
1188 fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner {
1189 AnyDateInner::Hebrew(*d)
1190 }
1191}
1192
1193impl From<Hebrew> for AnyCalendar {
1194 fn from(value: Hebrew) -> AnyCalendar {
1195 value.to_any()
1196 }
1197}
1198
1199impl IntoAnyCalendar for Indian {
1200 #[inline]
1201 fn to_any(self) -> AnyCalendar {
1202 AnyCalendar::Indian(Indian)
1203 }
1204 #[inline]
1205 fn kind(&self) -> AnyCalendarKind {
1206 AnyCalendarKind::Indian
1207 }
1208 #[inline]
1209 fn from_any(any: AnyCalendar) -> Result<Self, AnyCalendar> {
1210 if let AnyCalendar::Indian(cal) = any {
1211 Ok(cal)
1212 } else {
1213 Err(any)
1214 }
1215 }
1216 #[inline]
1217 fn from_any_ref(any: &AnyCalendar) -> Option<&Self> {
1218 if let AnyCalendar::Indian(cal) = any {
1219 Some(cal)
1220 } else {
1221 None
1222 }
1223 }
1224 #[inline]
1225 fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner {
1226 AnyDateInner::Indian(*d)
1227 }
1228}
1229
1230impl From<Indian> for AnyCalendar {
1231 fn from(value: Indian) -> AnyCalendar {
1232 value.to_any()
1233 }
1234}
1235
1236impl IntoAnyCalendar for Hijri<hijri::TabularAlgorithm> {
1237 #[inline]
1238 fn to_any(self) -> AnyCalendar {
1239 AnyCalendar::HijriTabular(self)
1240 }
1241 #[inline]
1242 fn kind(&self) -> AnyCalendarKind {
1243 match self.0 {
1244 hijri::TabularAlgorithm {
1245 leap_years: hijri::TabularAlgorithmLeapYears::TypeII,
1246 epoch: hijri::TabularAlgorithmEpoch::Friday,
1247 } => AnyCalendarKind::HijriTabularTypeIIFriday,
1248 hijri::TabularAlgorithm {
1249 leap_years: hijri::TabularAlgorithmLeapYears::TypeII,
1250 epoch: hijri::TabularAlgorithmEpoch::Thursday,
1251 } => AnyCalendarKind::HijriTabularTypeIIThursday,
1252 }
1253 }
1254 #[inline]
1255 fn from_any(any: AnyCalendar) -> Result<Self, AnyCalendar> {
1256 if let AnyCalendar::HijriTabular(cal) = any {
1257 Ok(cal)
1258 } else {
1259 Err(any)
1260 }
1261 }
1262 #[inline]
1263 fn from_any_ref(any: &AnyCalendar) -> Option<&Self> {
1264 if let AnyCalendar::HijriTabular(cal) = any {
1265 Some(cal)
1266 } else {
1267 None
1268 }
1269 }
1270 #[inline]
1271 fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner {
1272 AnyDateInner::HijriTabular(*d, self.0)
1273 }
1274}
1275
1276impl From<Hijri<hijri::TabularAlgorithm>> for AnyCalendar {
1277 fn from(value: Hijri<hijri::TabularAlgorithm>) -> AnyCalendar {
1278 value.to_any()
1279 }
1280}
1281
1282impl IntoAnyCalendar for Hijri<hijri::AstronomicalSimulation> {
1283 #[inline]
1284 fn to_any(self) -> AnyCalendar {
1285 AnyCalendar::HijriSimulated(self)
1286 }
1287 #[inline]
1288 fn kind(&self) -> AnyCalendarKind {
1289 match self.0.location {
1290 crate::cal::hijri_internal::SimulatedLocation::Mecca => {
1291 AnyCalendarKind::HijriSimulatedMecca
1292 }
1293 }
1294 }
1295 #[inline]
1296 fn from_any(any: AnyCalendar) -> Result<Self, AnyCalendar> {
1297 if let AnyCalendar::HijriSimulated(cal) = any {
1298 Ok(cal)
1299 } else {
1300 Err(any)
1301 }
1302 }
1303 #[inline]
1304 fn from_any_ref(any: &AnyCalendar) -> Option<&Self> {
1305 if let AnyCalendar::HijriSimulated(cal) = any {
1306 Some(cal)
1307 } else {
1308 None
1309 }
1310 }
1311 #[inline]
1312 fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner {
1313 AnyDateInner::HijriSimulated(*d)
1314 }
1315}
1316
1317impl From<Hijri<hijri::AstronomicalSimulation>> for AnyCalendar {
1318 fn from(value: Hijri<hijri::AstronomicalSimulation>) -> AnyCalendar {
1319 value.to_any()
1320 }
1321}
1322
1323impl IntoAnyCalendar for Hijri<hijri::UmmAlQura> {
1324 #[inline]
1325 fn to_any(self) -> AnyCalendar {
1326 AnyCalendar::HijriUmmAlQura(self)
1327 }
1328 #[inline]
1329 fn kind(&self) -> AnyCalendarKind {
1330 AnyCalendarKind::HijriUmmAlQura
1331 }
1332 #[inline]
1333 fn from_any(any: AnyCalendar) -> Result<Self, AnyCalendar> {
1334 if let AnyCalendar::HijriUmmAlQura(cal) = any {
1335 Ok(cal)
1336 } else {
1337 Err(any)
1338 }
1339 }
1340 #[inline]
1341 fn from_any_ref(any: &AnyCalendar) -> Option<&Self> {
1342 if let AnyCalendar::HijriUmmAlQura(cal) = any {
1343 Some(cal)
1344 } else {
1345 None
1346 }
1347 }
1348 #[inline]
1349 fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner {
1350 AnyDateInner::HijriUmmAlQura(*d)
1351 }
1352}
1353
1354impl From<Hijri<hijri::UmmAlQura>> for AnyCalendar {
1355 fn from(value: Hijri<hijri::UmmAlQura>) -> AnyCalendar {
1356 value.to_any()
1357 }
1358}
1359
1360impl IntoAnyCalendar for Iso {
1361 #[inline]
1362 fn to_any(self) -> AnyCalendar {
1363 AnyCalendar::Iso(Iso)
1364 }
1365 #[inline]
1366 fn kind(&self) -> AnyCalendarKind {
1367 AnyCalendarKind::Iso
1368 }
1369 #[inline]
1370 fn from_any(any: AnyCalendar) -> Result<Self, AnyCalendar> {
1371 if let AnyCalendar::Iso(cal) = any {
1372 Ok(cal)
1373 } else {
1374 Err(any)
1375 }
1376 }
1377 #[inline]
1378 fn from_any_ref(any: &AnyCalendar) -> Option<&Self> {
1379 if let AnyCalendar::Iso(cal) = any {
1380 Some(cal)
1381 } else {
1382 None
1383 }
1384 }
1385 #[inline]
1386 fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner {
1387 AnyDateInner::Iso(*d)
1388 }
1389}
1390
1391impl From<Iso> for AnyCalendar {
1392 fn from(value: Iso) -> AnyCalendar {
1393 value.to_any()
1394 }
1395}
1396
1397impl IntoAnyCalendar for Japanese {
1398 #[inline]
1399 fn to_any(self) -> AnyCalendar {
1400 AnyCalendar::Japanese(self)
1401 }
1402 #[inline]
1403 fn kind(&self) -> AnyCalendarKind {
1404 AnyCalendarKind::Japanese
1405 }
1406 #[inline]
1407 fn from_any(any: AnyCalendar) -> Result<Self, AnyCalendar> {
1408 if let AnyCalendar::Japanese(cal) = any {
1409 Ok(cal)
1410 } else {
1411 Err(any)
1412 }
1413 }
1414 #[inline]
1415 fn from_any_ref(any: &AnyCalendar) -> Option<&Self> {
1416 if let AnyCalendar::Japanese(cal) = any {
1417 Some(cal)
1418 } else {
1419 None
1420 }
1421 }
1422 #[inline]
1423 fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner {
1424 AnyDateInner::Japanese(*d)
1425 }
1426}
1427
1428impl From<Japanese> for AnyCalendar {
1429 fn from(value: Japanese) -> AnyCalendar {
1430 value.to_any()
1431 }
1432}
1433
1434impl IntoAnyCalendar for JapaneseExtended {
1435 #[inline]
1436 fn to_any(self) -> AnyCalendar {
1437 AnyCalendar::JapaneseExtended(self)
1438 }
1439 #[inline]
1440 fn kind(&self) -> AnyCalendarKind {
1441 AnyCalendarKind::JapaneseExtended
1442 }
1443 #[inline]
1444 fn from_any(any: AnyCalendar) -> Result<Self, AnyCalendar> {
1445 if let AnyCalendar::JapaneseExtended(cal) = any {
1446 Ok(cal)
1447 } else {
1448 Err(any)
1449 }
1450 }
1451 #[inline]
1452 fn from_any_ref(any: &AnyCalendar) -> Option<&Self> {
1453 if let AnyCalendar::JapaneseExtended(cal) = any {
1454 Some(cal)
1455 } else {
1456 None
1457 }
1458 }
1459 #[inline]
1460 fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner {
1461 AnyDateInner::JapaneseExtended(*d)
1462 }
1463}
1464
1465impl From<JapaneseExtended> for AnyCalendar {
1466 fn from(value: JapaneseExtended) -> AnyCalendar {
1467 value.to_any()
1468 }
1469}
1470
1471impl IntoAnyCalendar for Persian {
1472 #[inline]
1473 fn to_any(self) -> AnyCalendar {
1474 AnyCalendar::Persian(Persian)
1475 }
1476 #[inline]
1477 fn kind(&self) -> AnyCalendarKind {
1478 AnyCalendarKind::Persian
1479 }
1480 #[inline]
1481 fn from_any(any: AnyCalendar) -> Result<Self, AnyCalendar> {
1482 if let AnyCalendar::Persian(cal) = any {
1483 Ok(cal)
1484 } else {
1485 Err(any)
1486 }
1487 }
1488 #[inline]
1489 fn from_any_ref(any: &AnyCalendar) -> Option<&Self> {
1490 if let AnyCalendar::Persian(cal) = any {
1491 Some(cal)
1492 } else {
1493 None
1494 }
1495 }
1496 #[inline]
1497 fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner {
1498 AnyDateInner::Persian(*d)
1499 }
1500}
1501
1502impl From<Persian> for AnyCalendar {
1503 fn from(value: Persian) -> AnyCalendar {
1504 value.to_any()
1505 }
1506}
1507
1508impl IntoAnyCalendar for Roc {
1509 #[inline]
1510 fn to_any(self) -> AnyCalendar {
1511 AnyCalendar::Roc(Roc)
1512 }
1513 #[inline]
1514 fn kind(&self) -> AnyCalendarKind {
1515 AnyCalendarKind::Roc
1516 }
1517 #[inline]
1518 fn from_any(any: AnyCalendar) -> Result<Self, AnyCalendar> {
1519 if let AnyCalendar::Roc(cal) = any {
1520 Ok(cal)
1521 } else {
1522 Err(any)
1523 }
1524 }
1525 #[inline]
1526 fn from_any_ref(any: &AnyCalendar) -> Option<&Self> {
1527 if let AnyCalendar::Roc(cal) = any {
1528 Some(cal)
1529 } else {
1530 None
1531 }
1532 }
1533 #[inline]
1534 fn date_to_any(&self, d: &Self::DateInner) -> AnyDateInner {
1535 AnyDateInner::Roc(*d)
1536 }
1537}
1538
1539impl From<Roc> for AnyCalendar {
1540 fn from(value: Roc) -> AnyCalendar {
1541 value.to_any()
1542 }
1543}
1544
1545#[cfg(test)]
1546mod tests {
1547 use tinystr::tinystr;
1548 use types::MonthCode;
1549
1550 use super::*;
1551 use crate::Ref;
1552
1553 #[track_caller]
1554 fn single_test_roundtrip(
1555 calendar: Ref<AnyCalendar>,
1556 era: Option<(&str, Option<u8>)>,
1557 year: i32,
1558 month_code: &str,
1559 day: u8,
1560 ) {
1561 let month = types::MonthCode(month_code.parse().expect("month code must parse"));
1562
1563 let date = Date::try_new_from_codes(era.map(|x| x.0), year, month, day, calendar)
1564 .unwrap_or_else(|e| {
1565 panic!(
1566 "Failed to construct date for {} with {era:?}, {year}, {month}, {day}: {e:?}",
1567 calendar.debug_name(),
1568 )
1569 });
1570
1571 let roundtrip_year = date.year();
1572 let roundtrip_month = date.month().standard_code;
1573 let roundtrip_day = date.day_of_month().0;
1574
1575 assert_eq!(
1576 (month, day),
1577 (roundtrip_month, roundtrip_day),
1578 "Failed to roundtrip for calendar {}",
1579 calendar.debug_name()
1580 );
1581
1582 if let Some((era_code, era_index)) = era {
1583 let roundtrip_era_year = date.year().era().expect("year type should be era");
1584
1585 let roundtrip_year = roundtrip_year.era_year_or_related_iso();
1586 assert_eq!(
1587 (era_code, era_index, year),
1588 (
1589 roundtrip_era_year.era.as_str(),
1590 roundtrip_era_year.era_index,
1591 roundtrip_year
1592 ),
1593 "Failed to roundtrip era for calendar {}",
1594 calendar.debug_name()
1595 )
1596 } else {
1597 assert_eq!(
1598 year,
1599 date.extended_year(),
1600 "Failed to roundtrip year for calendar {}",
1601 calendar.debug_name()
1602 );
1603 }
1604
1605 let iso = date.to_iso();
1606 let reconstructed = Date::new_from_iso(iso, calendar);
1607 assert_eq!(
1608 date, reconstructed,
1609 "Failed to roundtrip via iso with {era:?}, {year}, {month}, {day}"
1610 )
1611 }
1612
1613 #[track_caller]
1614 fn single_test_error(
1615 calendar: Ref<AnyCalendar>,
1616 era: Option<(&str, Option<u8>)>,
1617 year: i32,
1618 month_code: &str,
1619 day: u8,
1620 error: DateError,
1621 ) {
1622 let month = types::MonthCode(month_code.parse().expect("month code must parse"));
1623
1624 let date = Date::try_new_from_codes(era.map(|x| x.0), year, month, day, calendar);
1625 assert_eq!(
1626 date,
1627 Err(error),
1628 "Construction with {era:?}, {year}, {month}, {day} did not return {error:?}"
1629 )
1630 }
1631
1632 #[test]
1633 fn test_any_construction() {
1634 let buddhist = AnyCalendar::new(AnyCalendarKind::Buddhist);
1635 let chinese = AnyCalendar::new(AnyCalendarKind::Chinese);
1636 let coptic = AnyCalendar::new(AnyCalendarKind::Coptic);
1637 let dangi = AnyCalendar::new(AnyCalendarKind::Dangi);
1638 let ethioaa = AnyCalendar::new(AnyCalendarKind::EthiopianAmeteAlem);
1639 let ethiopian = AnyCalendar::new(AnyCalendarKind::Ethiopian);
1640 let gregorian = AnyCalendar::new(AnyCalendarKind::Gregorian);
1641 let hebrew = AnyCalendar::new(AnyCalendarKind::Hebrew);
1642 let indian = AnyCalendar::new(AnyCalendarKind::Indian);
1643 let hijri_civil: AnyCalendar = AnyCalendar::new(AnyCalendarKind::HijriTabularTypeIIFriday);
1644 let hijri_simulated: AnyCalendar = AnyCalendar::new(AnyCalendarKind::HijriSimulatedMecca);
1645 let hijri_astronomical: AnyCalendar =
1646 AnyCalendar::new(AnyCalendarKind::HijriTabularTypeIIThursday);
1647 let hijri_umm_al_qura: AnyCalendar = AnyCalendar::new(AnyCalendarKind::HijriUmmAlQura);
1648 let japanese = AnyCalendar::new(AnyCalendarKind::Japanese);
1649 let japanext = AnyCalendar::new(AnyCalendarKind::JapaneseExtended);
1650 let persian = AnyCalendar::new(AnyCalendarKind::Persian);
1651 let roc = AnyCalendar::new(AnyCalendarKind::Roc);
1652 let buddhist = Ref(&buddhist);
1653 let chinese = Ref(&chinese);
1654 let coptic = Ref(&coptic);
1655 let dangi = Ref(&dangi);
1656 let ethioaa = Ref(ðioaa);
1657 let ethiopian = Ref(ðiopian);
1658 let gregorian = Ref(&gregorian);
1659 let hebrew = Ref(&hebrew);
1660 let indian = Ref(&indian);
1661 let hijri_civil = Ref(&hijri_civil);
1662 let hijri_simulated = Ref(&hijri_simulated);
1663 let hijri_astronomical = Ref(&hijri_astronomical);
1664 let hijri_umm_al_qura = Ref(&hijri_umm_al_qura);
1665 let japanese = Ref(&japanese);
1666 let japanext = Ref(&japanext);
1667 let persian = Ref(&persian);
1668 let roc = Ref(&roc);
1669
1670 single_test_roundtrip(buddhist, Some(("be", Some(0))), 100, "M03", 1);
1671 single_test_roundtrip(buddhist, None, 100, "M03", 1);
1672 single_test_roundtrip(buddhist, None, -100, "M03", 1);
1673 single_test_roundtrip(buddhist, Some(("be", Some(0))), -100, "M03", 1);
1674 single_test_error(
1675 buddhist,
1676 Some(("be", Some(0))),
1677 100,
1678 "M13",
1679 1,
1680 DateError::UnknownMonthCode(MonthCode(tinystr!(4, "M13"))),
1681 );
1682
1683 single_test_roundtrip(coptic, Some(("am", Some(0))), 100, "M03", 1);
1684 single_test_roundtrip(coptic, None, 2000, "M03", 1);
1685 single_test_roundtrip(coptic, None, -100, "M03", 1);
1686 single_test_roundtrip(coptic, Some(("am", Some(0))), -99, "M03", 1);
1687 single_test_roundtrip(coptic, Some(("am", Some(0))), 100, "M13", 1);
1688 single_test_error(
1689 coptic,
1690 Some(("am", Some(0))),
1691 100,
1692 "M14",
1693 1,
1694 DateError::UnknownMonthCode(MonthCode(tinystr!(4, "M14"))),
1695 );
1696
1697 single_test_roundtrip(ethiopian, Some(("am", Some(1))), 100, "M03", 1);
1698 single_test_roundtrip(ethiopian, None, 2000, "M03", 1);
1699 single_test_roundtrip(ethiopian, None, -100, "M03", 1);
1700 single_test_roundtrip(ethiopian, Some(("am", Some(1))), 2000, "M13", 1);
1701 single_test_roundtrip(ethiopian, Some(("aa", Some(0))), 5400, "M03", 1);
1702 single_test_error(
1732 ethiopian,
1733 Some(("am", Some(0))),
1734 100,
1735 "M14",
1736 1,
1737 DateError::UnknownMonthCode(MonthCode(tinystr!(4, "M14"))),
1738 );
1739
1740 single_test_roundtrip(ethioaa, Some(("aa", Some(0))), 7000, "M13", 1);
1741 single_test_roundtrip(ethioaa, None, 7000, "M13", 1);
1742 single_test_roundtrip(ethioaa, None, -100, "M13", 1);
1743 single_test_roundtrip(ethioaa, Some(("aa", Some(0))), 100, "M03", 1);
1744 single_test_error(
1745 ethiopian,
1746 Some(("aa", Some(0))),
1747 100,
1748 "M14",
1749 1,
1750 DateError::UnknownMonthCode(MonthCode(tinystr!(4, "M14"))),
1751 );
1752
1753 single_test_roundtrip(gregorian, Some(("ce", Some(1))), 100, "M03", 1);
1754 single_test_roundtrip(gregorian, None, 2000, "M03", 1);
1755 single_test_roundtrip(gregorian, None, -100, "M03", 1);
1756 single_test_roundtrip(gregorian, Some(("bce", Some(0))), 100, "M03", 1);
1757 single_test_error(
1787 gregorian,
1788 Some(("bce", Some(0))),
1789 100,
1790 "M13",
1791 1,
1792 DateError::UnknownMonthCode(MonthCode(tinystr!(4, "M13"))),
1793 );
1794
1795 single_test_roundtrip(indian, Some(("shaka", Some(0))), 100, "M03", 1);
1796 single_test_roundtrip(indian, None, 2000, "M12", 1);
1797 single_test_roundtrip(indian, None, -100, "M03", 1);
1798 single_test_roundtrip(indian, Some(("shaka", Some(0))), 0, "M03", 1);
1799 single_test_error(
1800 indian,
1801 Some(("shaka", Some(0))),
1802 100,
1803 "M13",
1804 1,
1805 DateError::UnknownMonthCode(MonthCode(tinystr!(4, "M13"))),
1806 );
1807
1808 single_test_roundtrip(chinese, None, 400, "M02", 5);
1809 single_test_roundtrip(chinese, None, 4660, "M07", 29);
1810 single_test_roundtrip(chinese, None, -100, "M11", 12);
1811 single_test_error(
1812 chinese,
1813 None,
1814 4658,
1815 "M13",
1816 1,
1817 DateError::UnknownMonthCode(MonthCode(tinystr!(4, "M13"))),
1818 );
1819
1820 single_test_roundtrip(dangi, None, 400, "M02", 5);
1821 single_test_roundtrip(dangi, None, 4660, "M08", 29);
1822 single_test_roundtrip(dangi, None, -1300, "M11", 12);
1823 single_test_error(
1824 dangi,
1825 None,
1826 10393,
1827 "M00L",
1828 1,
1829 DateError::UnknownMonthCode(MonthCode(tinystr!(4, "M00L"))),
1830 );
1831
1832 single_test_roundtrip(japanese, Some(("reiwa", None)), 3, "M03", 1);
1833 single_test_roundtrip(japanese, Some(("heisei", None)), 6, "M12", 1);
1834 single_test_roundtrip(japanese, Some(("meiji", None)), 10, "M03", 1);
1835 single_test_roundtrip(japanese, Some(("ce", None)), 1000, "M03", 1);
1836 single_test_roundtrip(japanese, None, 1000, "M03", 1);
1837 single_test_roundtrip(japanese, None, -100, "M03", 1);
1838 single_test_roundtrip(japanese, None, 2024, "M03", 1);
1839 single_test_roundtrip(japanese, Some(("bce", None)), 10, "M03", 1);
1840 single_test_error(
1870 japanese,
1871 Some(("reiwa", None)),
1872 2,
1873 "M13",
1874 1,
1875 DateError::UnknownMonthCode(MonthCode(tinystr!(4, "M13"))),
1876 );
1877
1878 single_test_roundtrip(japanext, Some(("reiwa", None)), 3, "M03", 1);
1879 single_test_roundtrip(japanext, Some(("heisei", None)), 6, "M12", 1);
1880 single_test_roundtrip(japanext, Some(("meiji", None)), 10, "M03", 1);
1881 single_test_roundtrip(japanext, Some(("tenpyokampo-749", None)), 1, "M04", 20);
1882 single_test_roundtrip(japanext, Some(("ce", None)), 100, "M03", 1);
1883 single_test_roundtrip(japanext, Some(("bce", None)), 10, "M03", 1);
1884 single_test_error(
1914 japanext,
1915 Some(("reiwa", None)),
1916 2,
1917 "M13",
1918 1,
1919 DateError::UnknownMonthCode(MonthCode(tinystr!(4, "M13"))),
1920 );
1921
1922 single_test_roundtrip(persian, Some(("ap", Some(0))), 477, "M03", 1);
1923 single_test_roundtrip(persian, None, 2083, "M07", 21);
1924 single_test_roundtrip(persian, None, -100, "M07", 21);
1925 single_test_roundtrip(persian, Some(("ap", Some(0))), 1600, "M12", 20);
1926 single_test_error(
1927 persian,
1928 Some(("ap", Some(0))),
1929 100,
1930 "M9",
1931 1,
1932 DateError::UnknownMonthCode(MonthCode(tinystr!(4, "M9"))),
1933 );
1934
1935 single_test_roundtrip(hebrew, Some(("am", Some(0))), 5773, "M03", 1);
1936 single_test_roundtrip(hebrew, None, 4993, "M07", 21);
1937 single_test_roundtrip(hebrew, None, -100, "M07", 21);
1938 single_test_roundtrip(hebrew, Some(("am", Some(0))), 5012, "M12", 20);
1939 single_test_error(
1940 hebrew,
1941 Some(("am", Some(0))),
1942 100,
1943 "M9",
1944 1,
1945 DateError::UnknownMonthCode(MonthCode(tinystr!(4, "M9"))),
1946 );
1947
1948 single_test_roundtrip(roc, Some(("roc", Some(1))), 10, "M05", 3);
1949 single_test_roundtrip(roc, Some(("broc", Some(0))), 15, "M01", 10);
1950 single_test_roundtrip(roc, None, 100, "M10", 30);
1951 single_test_roundtrip(roc, None, -100, "M10", 30);
1952
1953 single_test_roundtrip(hijri_simulated, Some(("ah", Some(0))), 477, "M03", 1);
1954 single_test_roundtrip(hijri_simulated, None, 2083, "M07", 21);
1955 single_test_roundtrip(hijri_simulated, None, -100, "M07", 21);
1956 single_test_roundtrip(hijri_simulated, Some(("ah", Some(0))), 1600, "M12", 20);
1957 single_test_error(
1958 hijri_simulated,
1959 Some(("ah", Some(0))),
1960 100,
1961 "M9",
1962 1,
1963 DateError::UnknownMonthCode(MonthCode(tinystr!(4, "M9"))),
1964 );
1965
1966 single_test_roundtrip(hijri_civil, Some(("ah", Some(0))), 477, "M03", 1);
1967 single_test_roundtrip(hijri_civil, None, 2083, "M07", 21);
1968 single_test_roundtrip(hijri_civil, None, -100, "M07", 21);
1969 single_test_roundtrip(hijri_civil, Some(("ah", Some(0))), 1600, "M12", 20);
1970 single_test_error(
1971 hijri_civil,
1972 Some(("ah", Some(0))),
1973 100,
1974 "M9",
1975 1,
1976 DateError::UnknownMonthCode(MonthCode(tinystr!(4, "M9"))),
1977 );
1978
1979 single_test_roundtrip(hijri_umm_al_qura, Some(("ah", Some(0))), 477, "M03", 1);
1980 single_test_roundtrip(hijri_umm_al_qura, None, 2083, "M07", 21);
1981 single_test_roundtrip(hijri_umm_al_qura, None, -100, "M07", 21);
1982 single_test_roundtrip(hijri_umm_al_qura, Some(("ah", Some(0))), 1600, "M12", 20);
1983 single_test_error(
1984 hijri_umm_al_qura,
1985 Some(("ah", Some(0))),
1986 100,
1987 "M9",
1988 1,
1989 DateError::UnknownMonthCode(MonthCode(tinystr!(4, "M9"))),
1990 );
1991
1992 single_test_roundtrip(hijri_astronomical, Some(("ah", Some(0))), 477, "M03", 1);
1993 single_test_roundtrip(hijri_astronomical, None, 2083, "M07", 21);
1994 single_test_roundtrip(hijri_astronomical, None, -100, "M07", 21);
1995 single_test_roundtrip(hijri_astronomical, Some(("ah", Some(0))), 1600, "M12", 20);
1996 single_test_error(
1997 hijri_astronomical,
1998 Some(("ah", Some(0))),
1999 100,
2000 "M9",
2001 1,
2002 DateError::UnknownMonthCode(MonthCode(tinystr!(4, "M9"))),
2003 );
2004 }
2005}