3 // (C) 2002 Ulrich Kunitz
8 using System.Globalization;
11 namespace MonoTests.System.Globalization
15 private int _day, _month, _year, _era;
22 if (value < 1 || value > 31)
23 throw new ArgumentOutOfRangeException(
25 "Day must be between 1 and 31.");
35 if (value < 1 || value > 13)
36 throw new ArgumentOutOfRangeException(
38 "Month must be between 1 and 13.");
57 if (value < 1 || value > 10)
58 throw new ArgumentOutOfRangeException(
60 "Era must be between 1 and 10.");
65 public Date(int day, int month, int year, int era) {
71 public Date(int day, int month, int year) : this(day,month,year,1) {}
72 public Date() : this(1,1,1,1) {}
74 public DateTime ToDateTime(Calendar cal) {
75 return cal.ToDateTime(Year,Month,Day,0,0,0,0,Era);
78 public void FromDateTime(Calendar cal, DateTime time) {
79 Date dmy = new Date();
80 dmy.Day = cal.GetDayOfMonth(time);
81 dmy.Month = cal.GetMonth(time);
82 dmy.Year = cal.GetYear(time);
83 dmy.Era = cal.GetEra(time);
90 public override string ToString() {
91 StringWriter sw = new StringWriter();
92 sw.Write("{0}.{1}.{2}", Day, Month, Year);
94 sw.Write(" era {0}", Era);
99 public override bool Equals(Object b) {
100 if (b == null || GetType() != b.GetType())
102 return Equals(this, (Date)b);
105 public static bool Equals(Date a, Date b) {
108 if (a.Year != b.Year)
110 if (a.Month != b.Month)
119 public override int GetHashCode() {
120 return ToString().GetHashCode();
124 public class CalendarTest : TestCase {
125 private Calendar[] acal;
126 private GregorianCalendar gcal;
127 private JulianCalendar jucal;
128 private HijriCalendar hical;
129 private HebrewCalendar hecal;
130 private JapaneseCalendar jacal;
131 private TaiwanCalendar tacal;
132 private KoreanCalendar kcal;
133 private ThaiBuddhistCalendar tbcal;
135 private ChineseLunisolarCalendar clcal;
136 private TaiwanLunisolarCalendar tlcal;
137 private JapaneseLunisolarCalendar jlcal;
138 private KoreanLunisolarCalendar klcal;
141 protected override void SetUp() {
142 gcal = new GregorianCalendar();
143 jucal = new JulianCalendar();
144 hical = new HijriCalendar();
145 hecal = new HebrewCalendar();
146 jacal = new JapaneseCalendar();
147 tacal = new TaiwanCalendar();
148 kcal = new KoreanCalendar();
149 tbcal = new ThaiBuddhistCalendar();
150 acal = new Calendar[] {
151 gcal, jucal, hical, hecal, jacal,
154 clcal = new ChineseLunisolarCalendar ();
155 tlcal = new TaiwanLunisolarCalendar ();
156 jlcal = new JapaneseLunisolarCalendar ();
157 klcal = new KoreanLunisolarCalendar ();
161 private void RowCheck(params Date[] adate) {
162 if (adate.Length != acal.Length)
163 throw new ArgumentException(
164 "Number of Date arguments doesn't match " +
165 "length of calendar array.");
167 DateTime timeG = adate[0].ToDateTime(gcal);
168 for (int i = 0; i < acal.Length; i++) {
169 Date date = adate[i];
172 Calendar cal = acal[i];
174 DateTime time = date.ToDateTime(cal);
175 StringWriter sw = new StringWriter();
176 sw.Write("Calendar {0} computes wrong DateTime.",
178 AssertEquals(sw.ToString(), timeG, time);
180 sw = new StringWriter();
181 Date ndate = new Date();
182 ndate.FromDateTime(cal, time);
183 sw.Write("Calendar {0} computes wrong date", cal);
184 AssertEquals(sw.ToString(), date, ndate);
188 // We are testing the implementation against the reference dates in
189 // Calendrical Calcualation. Please note that the CLR uses another
190 // epoch for the HijriCalendar, which might be the perfect thing
192 public void TestCCTable() {
193 // Gr Ju Hi He Ja Ta Ko TB
194 RowCheck(new Date(24,9,70,1),
200 new Date(24,9,2403,1),
201 new Date(24,9,613,1));
202 RowCheck(new Date(2,10,135,1),
203 new Date(3,10,135,1),
208 new Date(2,10,2468,1),
209 new Date(2,10,678,1));
210 RowCheck(new Date(8,1,470,1),
216 new Date(8,1,2803,1),
217 new Date(8,1,1013,1));
218 RowCheck(new Date(20,5,576,1),
219 new Date(18,5,576,1),
224 new Date(20,5,2909,1),
225 new Date(20,5,1119,1));
226 RowCheck(new Date(10,11,694,1),
227 new Date(7,11,694,1),
232 new Date(10,11,3027,1),
233 new Date(10,11,1237,1));
234 RowCheck(new Date(25,4,1013,1),
235 new Date(19,4,1013,1),
236 new Date(6,10,403,1),
240 new Date(25,4,3346,1),
241 new Date(25,4,1556,1));
242 RowCheck(new Date(24,5,1096,1),
243 new Date(18,5,1096,1),
244 new Date(23,5,489,1),
248 new Date(24,5,3429,1),
249 new Date(24,5,1639,1));
250 RowCheck(new Date(23,3,1190,1),
251 new Date(16,3,1190,1),
256 new Date(23,3,3523,1),
257 new Date(23,3,1733,1));
258 RowCheck(new Date(10,3,1240,1),
259 new Date(3,3,1240,1),
264 new Date(10,3,3573,1),
265 new Date(10,3,1783,1));
266 RowCheck(new Date(2,4,1288,1),
267 new Date(26,3,1288,1),
268 new Date(21,2,687,1),
272 new Date(2,4,3621,1),
273 new Date(2,4,1831,1));
274 RowCheck(new Date(27,4,1298,1),
275 new Date(20,4,1298,1),
280 new Date(27,4,3631,1),
281 new Date(27,4,1841,1));
282 RowCheck(new Date(12,6,1391,1),
283 new Date(4,6,1391,1),
288 new Date(12,6,3724,1),
289 new Date(12,6,1934,1));
290 RowCheck(new Date(3,2,1436,1),
291 new Date(25,1,1436,1),
296 new Date(3,2,3769,1),
297 new Date(3,2,1979,1));
298 RowCheck(new Date(9,4,1492,1),
299 new Date(31,3,1492,1),
304 new Date(9,4,3825,1),
305 new Date(9,4,2035,1));
306 RowCheck(new Date(19,9,1553,1),
307 new Date(9,9,1553,1),
308 new Date(1,10,960,1),
312 new Date(19,9,3886,1),
313 new Date(19,9,2096,1));
314 RowCheck(new Date(5,3,1560,1),
315 new Date(24,2,1560,1),
316 new Date(28,5,967,1),
320 new Date(5,3,3893,1),
321 new Date(5,3,2103,1));
322 RowCheck(new Date(10,6,1648,1),
323 new Date(31,5,1648,1),
324 new Date(19,5,1058,1),
325 new Date(20,9,5408,1),
328 new Date(10,6,3981,1),
329 new Date(10,6,2191,1));
330 RowCheck(new Date(30,6,1680,1),
331 new Date(20,6,1680,1),
332 new Date(3,6,1091,1),
333 new Date(3,11,5440,1),
336 new Date(30,6,4013,1),
337 new Date(30,6,2223,1));
338 RowCheck(new Date(24,7,1716,1),
339 new Date(13,7,1716,1),
340 new Date(5,8,1128,1),
341 new Date(5,11,5476,1),
344 new Date(24,7,4049,1),
345 new Date(24,7,2259,1));
346 RowCheck(new Date(19,6,1768,1),
347 new Date(8,6,1768,1),
348 new Date(4,2,1182,1),
349 new Date(4,10,5528,1),
352 new Date(19,6,4101,1),
353 new Date(19,6,2311,1));
354 RowCheck(new Date(2,8,1819,1),
355 new Date(21,7,1819,1),
356 new Date(11,10,1234,1),
357 new Date(11,11,5579,1),
360 new Date(2,8,4152,1),
361 new Date(2,8,2362,1));
362 RowCheck(new Date(27,3,1839,1),
363 new Date(15,3,1839,1),
364 new Date(12,1,1255,1),
365 new Date(12,7,5599,1),
368 new Date(27,3,4172,1),
369 new Date(27,3,2382,1));
370 RowCheck(new Date(19,4,1903,1),
371 new Date(6,4,1903,1),
372 new Date(22,1,1321,1),
373 new Date(22,7,5663,1),
376 new Date(19,4,4236,1),
377 new Date(19,4,2446,1));
378 RowCheck(new Date(25,8,1929,1),
379 new Date(12,8,1929,1),
380 new Date(20,3,1348,1),
381 new Date(19,12,5689,1),
384 new Date(25,8,4262,1),
385 new Date(25,8,2472,1));
386 RowCheck(new Date(29,9,1941,1),
387 new Date(16,9,1941,1),
388 new Date(9,9,1360,1),
389 new Date(8,1,5702,1),
392 new Date(29,9,4274,1),
393 new Date(29,9,2484,1));
394 RowCheck(new Date(19,4,1943,1),
395 new Date(6,4,1943,1),
396 new Date(14,4,1362,1),
397 new Date(14,8,5703,1),
400 new Date(19,4,4276,1),
401 new Date(19,4,2486,1));
402 RowCheck(new Date(7,10,1943,1),
403 new Date(24,9,1943,1),
404 new Date(8,10,1362,1),
405 new Date(8,1,5704,1),
408 new Date(7,10,4276,1),
409 new Date(7,10,2486,1));
410 RowCheck(new Date(17,3,1992,1),
411 new Date(4,3,1992,1),
412 new Date(14,9,1412,1),
413 new Date(12,7,5752,1),
416 new Date(17,3,4325,1),
417 new Date(17,3,2535,1));
418 RowCheck(new Date(25,5,1996,1),
419 new Date(12,5,1996,1),
420 new Date(8,1,1417,1),
421 new Date(7,9,5756,1),
424 new Date(25,5,4329,1),
425 new Date(25,5,2539,1));
426 RowCheck(new Date(10,11,2038,1),
427 new Date(28,10,2038,1),
428 new Date(13,10,1460,1),
429 new Date(12,2,5799,1),
430 new Date(10,11,50,4),
431 new Date(10,11,127,1),
432 new Date(10,11,4371,1),
433 new Date(10,11,2581,1));
434 RowCheck(new Date(18,7,2094,1),
435 new Date(5,7,2094,1),
436 new Date(6,3,1518,1),
437 new Date(5,11,5854,1),
438 new Date(18,7,106,4),
439 new Date(18,7,183,1),
440 new Date(18,7,4427,1),
441 new Date(18,7,2637,1));
444 public void TestCalendarType() {
445 GregorianCalendar gc = new GregorianCalendar(
446 GregorianCalendarTypes.Arabic);
447 AssertEquals("A01 Gregorian ctor " +
448 "with GregorianCalendarTypes parameter",
449 GregorianCalendarTypes.Arabic,
451 gc.CalendarType = GregorianCalendarTypes.MiddleEastFrench;
452 AssertEquals("A02 GregorianCalendar.CalendarType",
453 GregorianCalendarTypes.MiddleEastFrench,
457 public void TestStandardEras() {
458 AssertEquals("B01 ADEra", 1, GregorianCalendar.ADEra);
459 AssertEquals("B02 HebrewEra", 1, HebrewCalendar.HebrewEra);
460 AssertEquals("B03 HjriEra", 1, HijriCalendar.HijriEra);
461 AssertEquals("B04 JulianEra", 1, JulianCalendar.JulianEra);
462 AssertEquals("B05 KoreanEra", 1, KoreanCalendar.KoreanEra);
463 AssertEquals("B06 ThaiBuddhistEra", 1,
464 ThaiBuddhistCalendar.ThaiBuddhistEra);
466 AssertEquals("CNLunisor", 1, ChineseLunisolarCalendar.ChineseEra);
467 AssertEquals("JPLunisor", 1, JapaneseLunisolarCalendar.JapaneseEra);
468 AssertEquals("KRLunisor", 1, KoreanLunisolarCalendar.GregorianEra);
472 public void TestCurrentEra() {
473 AssertEquals("C01 GregorianCalendar.CurrentEra",
474 0, GregorianCalendar.CurrentEra);
475 AssertEquals("C02 HebrewCalendar.CurrentEra",
476 0, HebrewCalendar.CurrentEra);
477 AssertEquals("C03 HijriCalendar.CurrentEra",
478 0, HijriCalendar.CurrentEra);
479 AssertEquals("C04 JapaneseCalendar.CurrentEra",
480 0, JapaneseCalendar.CurrentEra);
481 AssertEquals("C05 JulianCalendar.CurrentEra",
482 0, JulianCalendar.CurrentEra);
483 AssertEquals("C06 KoreanCalendar.CurrentEra",
484 0, KoreanCalendar.CurrentEra);
485 AssertEquals("C07 TaiwanCalendar.CurrentEra",
486 0, TaiwanCalendar.CurrentEra);
487 AssertEquals("C08 ThaiBuddhistCalendar.CurrentEra",
489 ThaiBuddhistCalendar.CurrentEra);
492 public void TestErasProperty() {
493 foreach (Calendar cal in acal) {
495 if (cal is JapaneseCalendar)
497 AssertEquals(String.Format("D01 {0}.Eras.Length", cal),
498 check, cal.Eras.Length);
500 Assert(String.Format("D02 {0}.Eras readonly", cal),
506 public void TestErasProperty2() {
507 AssertEquals("cn", 1, clcal.Eras.Length);
508 AssertEquals("tw", 1, tlcal.Eras.Length);
509 AssertEquals("jp", 2, jlcal.Eras.Length);
510 AssertEquals("kr", 1, klcal.Eras.Length);
512 AssertEquals("jp.1", 4, jlcal.Eras [0]);
513 AssertEquals("jp.2", 3, jlcal.Eras [1]);
517 public void TestTwoDigitYearMax() {
518 AssertEquals("E01 TwoDigitYearMax GregorianCalendar",
519 2029, gcal.TwoDigitYearMax);
520 AssertEquals("E02 TwoDigitYearMax HebrewCalendar",
521 5790, hecal.TwoDigitYearMax);
522 AssertEquals("E03 TwoDigitYearMax HijriCalendar",
523 1451, hical.TwoDigitYearMax);
524 AssertEquals("E04 TwoDigitYearMax JapaneseCalendar",
525 99, jacal.TwoDigitYearMax);
526 AssertEquals("E05 TwoDigitYearMax JulianCalendar",
527 2029, jucal.TwoDigitYearMax);
528 AssertEquals("E06 TwoDigitYearMax KoreanCalendar",
529 4362, kcal.TwoDigitYearMax);
530 AssertEquals("E07 TwoDigitYearMax TaiwanCalendar",
531 99, tacal.TwoDigitYearMax);
532 AssertEquals("E08 TwoDigitYearMax ThaiBuddhistCalendar",
533 2572, tbcal.TwoDigitYearMax);
534 foreach (Calendar cal in acal) {
535 bool exception = false;
537 cal.TwoDigitYearMax = 99;
539 catch (ArgumentOutOfRangeException) {
542 Assert(String.Format("E09 {0}.TwoDigitYearMax 99 " +
543 " out of range exception", cal),
549 m = cal.GetYear(DateTime.MaxValue)+1;
550 cal.TwoDigitYearMax = m;
552 catch (ArgumentException) {
555 Assert(String.Format("E10 {0}.TwoDigitYearMax out " +
556 " of range exception value {1}",
562 [Test] // wrt bug #76252.
563 public void HebrewCalendarGetDaysInMonth ()
565 HebrewCalendar c = new HebrewCalendar ();
566 int year = c.GetYear (new DateTime (2005, 9, 1));
567 AssertEquals (5765, year);
568 int days = c.GetDaysInMonth (year, 13, 1);
569 AssertEquals (29, days);
573 public void GregorianAddMonth ()
575 GregorianCalendar c = new GregorianCalendar ();
576 DateTime d = new DateTime (2007, 5, 31);
577 DateTime prev = c.AddMonths (d, -1);
578 AssertEquals ("prev", 4, prev.Month);
579 DateTime next = c.AddMonths (d, 1);
580 AssertEquals ("next", 6, next.Month);
584 public void AddYearOnLeapYear ()
586 GregorianCalendar c = new GregorianCalendar ();
587 DateTime d = new DateTime (2004, 2, 29);
588 DateTime prev = c.AddYears (d, -1);
589 AssertEquals ("prev", 2, prev.Month);
590 DateTime next = c.AddYears (d, 1);
591 AssertEquals ("next", 2, next.Month);
596 [Category ("NotWorking")]
597 public void GetLeapMonth ()
599 GregorianCalendar gc = new GregorianCalendar ();
600 AssertEquals ("#1-1", 0, gc.GetLeapMonth (2007));
601 AssertEquals ("#1-2", 0, gc.GetLeapMonth (2008));
602 AssertEquals ("#1-3", 0, gc.GetLeapMonth (2100));
603 AssertEquals ("#1-4", 0, gc.GetLeapMonth (2000));
605 JulianCalendar jc = new JulianCalendar ();
606 AssertEquals ("#2-1", 0, jc.GetLeapMonth (2007));
607 AssertEquals ("#2-2", 0, jc.GetLeapMonth (2008));
608 AssertEquals ("#2-3", 0, jc.GetLeapMonth (2100));
609 AssertEquals ("#2-4", 0, jc.GetLeapMonth (2000));
610 AssertEquals ("#2-5", 0, jc.GetLeapMonth (2009));
611 AssertEquals ("#2-6", 0, jc.GetLeapMonth (2010));
613 HebrewCalendar hc = new HebrewCalendar ();
614 // 3rd, 6th, 8th, 11th 14th and 17th year in every 19 are leap.
616 AssertEquals ("#3-1", 0, hc.GetLeapMonth (5343));
617 AssertEquals ("#3-2", 0, hc.GetLeapMonth (5344));
618 AssertEquals ("#3-3", 7, hc.GetLeapMonth (5345));
619 AssertEquals ("#3-4", 0, hc.GetLeapMonth (5346));
620 AssertEquals ("#3-5", 7, hc.GetLeapMonth (5347));
621 AssertEquals ("#3-6", 0, hc.GetLeapMonth (5348));
622 AssertEquals ("#3-7", 0, hc.GetLeapMonth (5349));
624 ThaiBuddhistCalendar tc = new ThaiBuddhistCalendar ();
625 AssertEquals ("#4-1", 0, tc.GetLeapMonth (2520));
626 AssertEquals ("#4-2", 0, tc.GetLeapMonth (2521));
627 AssertEquals ("#4-3", 0, tc.GetLeapMonth (2522));
628 AssertEquals ("#4-4", 0, tc.GetLeapMonth (2523));
630 ChineseLunisolarCalendar cc = new ChineseLunisolarCalendar ();
631 AssertEquals ("#5-1", 0, cc.GetLeapMonth (2000));
632 AssertEquals ("#5-2", 5, cc.GetLeapMonth (2001));
633 AssertEquals ("#5-3", 0, cc.GetLeapMonth (2002));
634 AssertEquals ("#5-4", 0, cc.GetLeapMonth (2003));
635 AssertEquals ("#5-5", 3, cc.GetLeapMonth (2004));
636 AssertEquals ("#5-6", 0, cc.GetLeapMonth (2005));
637 AssertEquals ("#5-7", 8, cc.GetLeapMonth (2006));
638 AssertEquals ("#5-8", 0, cc.GetLeapMonth (2007));
639 AssertEquals ("#5-9", 0, cc.GetLeapMonth (2008));
640 AssertEquals ("#5-10", 6, cc.GetLeapMonth (2009));
641 AssertEquals ("#5-11", 0, cc.GetLeapMonth (2010));
642 AssertEquals ("#5-12", 0, cc.GetLeapMonth (2011));
643 AssertEquals ("#5-13", 5, cc.GetLeapMonth (2012));
644 AssertEquals ("#5-14", 0, cc.GetLeapMonth (2013));
645 AssertEquals ("#5-15", 10, cc.GetLeapMonth (2014));
646 AssertEquals ("#5-16", 0, cc.GetLeapMonth (2015));
647 AssertEquals ("#5-17", 0, cc.GetLeapMonth (2016));
648 AssertEquals ("#5-18", 7, cc.GetLeapMonth (2017));
649 AssertEquals ("#5-19", 0, cc.GetLeapMonth (2018));
650 AssertEquals ("#5-20", 0, cc.GetLeapMonth (2019));
652 KoreanLunisolarCalendar kc = new KoreanLunisolarCalendar ();
653 AssertEquals ("#6-1", 0, kc.GetLeapMonth (2000));
654 AssertEquals ("#6-2", 5, kc.GetLeapMonth (2001));
655 AssertEquals ("#6-3", 0, kc.GetLeapMonth (2002));
656 AssertEquals ("#6-4", 0, kc.GetLeapMonth (2003));
657 AssertEquals ("#6-5", 3, kc.GetLeapMonth (2004));
658 AssertEquals ("#6-6", 0, kc.GetLeapMonth (2005));
659 AssertEquals ("#6-7", 8, kc.GetLeapMonth (2006));
660 AssertEquals ("#6-8", 0, kc.GetLeapMonth (2007));
661 AssertEquals ("#6-9", 0, kc.GetLeapMonth (2008));
662 AssertEquals ("#6-10", 6, kc.GetLeapMonth (2009));
663 AssertEquals ("#6-11", 0, kc.GetLeapMonth (2010));
664 AssertEquals ("#6-12", 0, kc.GetLeapMonth (2011));
665 AssertEquals ("#6-13", 4, kc.GetLeapMonth (2012)); // off from cn by 1
666 AssertEquals ("#6-14", 0, kc.GetLeapMonth (2013));
667 AssertEquals ("#6-15", 10, kc.GetLeapMonth (2014));
668 AssertEquals ("#6-16", 0, kc.GetLeapMonth (2015));
669 AssertEquals ("#6-17", 0, kc.GetLeapMonth (2016));
670 AssertEquals ("#6-18", 6, kc.GetLeapMonth (2017)); // off from cn by 1
671 AssertEquals ("#6-19", 0, kc.GetLeapMonth (2018));
672 AssertEquals ("#6-20", 0, kc.GetLeapMonth (2019));
676 /* UK TODO: breaks with current DateTime implementation.
677 * I've a newer one that works, but that requires to much changes.
679 public void TestToFourDigitYear() {
680 foreach (Calendar cal in acal) {
683 if (cal is HebrewCalendar)
685 if (cal is KoreanCalendar)
687 if (cal is JapaneseCalendar)
689 if (cal is TaiwanCalendar)
691 cal.TwoDigitYearMax = mod + 229;
693 String.Format("F01 {0}.TwoDigitYearMax", cal),
694 mod+229 , cal.TwoDigitYearMax);
696 String.Format("F02 {0}.ToFourDigitYear(29)",
698 working ? mod+229 : 29,
699 cal.ToFourDigitYear(29));
701 String.Format("F03 {0}.ToFourDigitYear(30)",
703 working ? mod+130 : 30,
704 cal.ToFourDigitYear(30));
706 String.Format("F04 {0}.ToFourDigitYear({1})",
708 mod, cal.ToFourDigitYear(mod));
709 bool exception = false;
711 cal.ToFourDigitYear(-1);
713 catch (ArgumentOutOfRangeException) {
716 Assert(String.Format(
717 "F05 {0}.ToFourDigitYear(-1) exception",
721 cal.ToFourDigitYear(15000);
723 catch (ArgumentOutOfRangeException) {
726 Assert(String.Format(
727 "F05 {0}.ToFourDigitYear(15000) exception",
733 // TODO: more tests :-)
734 } // class CalendarTest
736 } // namespace MonoTests.System.Globalization