GenericParameter.cs: override Module properly
[mcs.git] / class / corlib / System.Globalization / PersianCalendar.cs
blob576abb7a18a81f68d9c2998b87967ac7f1b697b2
1 //
2 // System.Globalization.PersianCalendar.cs
3 //
4 // Authors:
5 // Roozbeh Pournader (roozbeh@farsiweb.info)
6 // Ulrich Kunitz
7 //
8 // Copyright (C) 2002 Ulrich Kunitz
9 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
10 // Copyright (C) 2005 Sharif FarsiWeb, Inc. (http://www.farsiweb.info)
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 namespace System.Globalization {
34 using System;
35 using System.IO;
36 using System.Runtime.InteropServices;
38 /// <summary>
39 /// This is the Persian calendar of Iran, also known as the Iranian
40 /// calendar or the Jalaali calendar. The Afghan calendar may or may
41 /// not be different, as different sources disagree about it.
42 /// </summary>
43 /// <remarks>
44 /// <para>The implemented algorithm is the simple 33-year arithmetic
45 /// calendar, which is not the same as the official Iranian calendar.
46 /// But this arithmetic calendar has been confirmed to produce the
47 /// same results as the official Iranian calendar at least
48 /// from 1925 C.E., when the calendar was officially introduced,
49 /// to 2088 C.E. This is the same algorithm that is used in .NET.
50 /// </para>
51 /// <para>The Iranian law explicitly mentions that the true solar year
52 /// should be used, which requires astronomical calculations of the
53 /// March equinox and the solar apparent noon. The exact locale for
54 /// observation of the apparent noon is not mentioned in the 1925 law,
55 /// but the current practice is using the 52.5 E meridian, which is
56 /// the meridian defining the official timezone of Iran.
57 /// </para>
58 /// <para>Also, please note that implementing the Persian calendar
59 /// using the 2820-year arithmetic algorithm, as suggested by
60 /// Ahmad Birashk and others, is less accurate than the 33-year
61 /// calendar: first, it fails earlier than the 33-year cycle in
62 /// matching the official astronomical calendar (first failure is
63 /// in 2025 C.E.), and second, the 2820-year suggested rule is based
64 /// on the mean tropical year, not the mean March equinoctial year.
65 /// </para>
66 /// </remarks>
67 [Serializable]
68 public class PersianCalendar : Calendar {
69 /// <summary>
70 /// Constructor.
71 /// </summary>
72 public PersianCalendar() {
73 M_AbbrEraNames = new string[] {"A.P."};
74 M_EraNames = new string[] {"Anno Persico"};
75 if (twoDigitYearMax == 99)
76 // FIXME: the .NET documentation does not mention the default value,
77 // This is the value mentioned in the .NET documentation example result.
78 twoDigitYearMax = 1410;
81 /// <summary>
82 /// The era number for the Anno Persico (A.P.) era, called
83 /// plain PersianEra.
84 /// </summary>
85 public static readonly int PersianEra = 1;
87 /// <summary>
88 /// The
89 /// <see cref="T:System.DateTime"/> ticks for first day of
90 /// year 1 A.P.
91 /// </summary>
92 internal const long M_MinTicks = 196036416000000000L;
94 /// <summary>
95 /// The minimum year in the A.P. era supported.
96 /// </summary>
97 internal const int M_MinYear = 1;
99 /// <value>Overridden. Gives the eras supported by the Persian
100 /// calendar as an array of integers.
101 /// </value>
102 public override int[] Eras {
103 get {
104 return new int[] { PersianEra };
108 public override int TwoDigitYearMax {
109 get {
110 return twoDigitYearMax;
112 set {
113 CheckReadOnly ();
114 M_ArgumentInRange ("value", value, 100, M_MaxYear);
116 twoDigitYearMax = value;
120 /// <summary>
121 /// A protected member checking a
122 /// <see cref="T:System.DateTime"/> value.
123 /// </summary>
124 /// <param name="time">The
125 /// <see cref="T:System.DateTime"/>
126 /// to check.
127 /// </param>
128 /// <exception cref="T:System.ArgumentOutOfRangeException">
129 /// The exception is thrown if the
130 /// <see cref="T:System.DateTime"/> parameter is before the
131 /// year 1 A.P.
132 /// </exception>
133 internal void M_CheckDateTime(DateTime time)
135 if (time.Ticks < M_MinTicks)
136 throw new ArgumentOutOfRangeException(
137 "time",
138 "Only positive Persian years are supported.");
141 /// <summary>
142 /// A protected method checking the era number.
143 /// </summary>
144 /// <param name="era">The era number.</param>
145 /// <exception name="T:System.ArgumentException">
146 /// The exception is thrown if the era is not equal
147 /// <see cref="F:PersianEra"/>.
148 /// </exception>
149 internal void M_CheckEra(ref int era)
151 if (era == CurrentEra)
152 era = PersianEra;
153 if (era != PersianEra)
154 throw new ArgumentException("Era value was not valid.");
157 /// <summary>
158 /// A protected method checking calendar year and the era number.
159 /// </summary>
160 /// <param name="year">An integer representing the calendar year.
161 /// </param>
162 /// <param name="era">The era number.</param>
163 /// <exception cref="T:System.ArgumentException">
164 /// The exception is thrown if the era is not equal
165 /// <see cref="F:PersianEra"/>.
166 /// </exception>
167 /// <exception cref="T:System.ArgumentOutOfRangeException">
168 /// The exception is thrown if the calendar year is outside of
169 /// the allowed range.
170 /// </exception>
171 internal override void M_CheckYE(int year, ref int era)
173 M_CheckEra(ref era);
174 if (year < M_MinYear || year > M_MaxYear)
175 throw new ArgumentOutOfRangeException(
176 "year",
177 "Only Persian years between 1 and 9378," +
178 " inclusive, are supported.");
181 /// <summary>
182 /// A protected method checking the calendar year, month, and
183 /// era number.
184 /// </summary>
185 /// <param name="year">An integer representing the calendar year.
186 /// </param>
187 /// <param name="month">An integer giving the calendar month.
188 /// </param>
189 /// <param name="era">The era number.</param>
190 /// <exception cref="T:System.ArgumentException">
191 /// The exception is thrown if the era is not equal
192 /// <see cref="F:PersianEra"/>.
193 /// </exception>
194 /// <exception cref="T:System.ArgumentOutOfRangeException">
195 /// The exception is thrown if the calendar year or month is
196 /// outside of the allowed range.
197 /// </exception>
198 internal void M_CheckYME(int year, int month, ref int era)
200 M_CheckYE(year, ref era);
201 if (month < 1 || month > 12)
202 throw new ArgumentOutOfRangeException("month",
203 "Month must be between one and twelve.");
204 else if (year == M_MaxYear && month > 10)
205 throw new ArgumentOutOfRangeException("month",
206 "Months in year 9378 must be between one and ten.");
209 /// <summary>
210 /// A protected method checking the calendar day, month, and year
211 /// and the era number.
212 /// </summary>
213 /// <param name="year">An integer representing the calendar year.
214 /// </param>
215 /// <param name="month">An integer giving the calendar month.
216 /// </param>
217 /// <param name="day">An integer giving the calendar day.
218 /// </param>
219 /// <param name="era">The era number.</param>
220 /// <exception cref="T:System.ArgumentException">
221 /// The exception is thrown if the era is not equal
222 /// <see cref="F:PersianEra"/>.
223 /// </exception>
224 /// <exception cref="T:System.ArgumentOutOfRangeException">
225 /// The exception is thrown if the calendar year, month, or day is
226 /// outside of the allowed range.
227 /// </exception>
228 internal void M_CheckYMDE(int year, int month, int day,
229 ref int era)
231 M_CheckYME(year, month, ref era);
232 M_ArgumentInRange("day",
233 day, 1, GetDaysInMonth(year, month, era));
234 if (year == M_MaxYear && month == 10 && day > 10)
235 throw new ArgumentOutOfRangeException("day",
236 "Days in month 10 of year 9378 must" +
237 " be between one and ten.");
240 internal const int epoch = 226895;
242 // FIXME: this may need a "static". I don't know enough C#.
243 internal int fixed_from_dmy(int day, int month, int year)
245 int k = epoch - 1;
247 k += 365 * (year - 1);
248 k += (8 * year + 21) / 33;
249 if (month <= 7)
250 k += 31 * (month - 1);
251 else
252 k += 30 * (month - 1) + 6;
253 k += day;
255 return k;
258 // FIXME: this may need a "static". I don't know enough C#.
259 internal int year_from_fixed(int date)
261 return (33 * (date - epoch) + 3) / 12053 + 1;
264 // FIXME: this may need a "static". I don't know enough C#.
265 internal void my_from_fixed(out int month, out int year,
266 int date)
268 int day;
270 year = year_from_fixed(date);
271 day = date - fixed_from_dmy (1, 1, year);
272 if (day < 216)
273 month = day / 31 + 1;
274 else
275 month = (day - 6) / 30 + 1;
278 // FIXME: this may need a "static". I don't know enough C#.
279 internal void dmy_from_fixed(out int day, out int month,
280 out int year, int date)
282 year = year_from_fixed(date);
283 day = date - fixed_from_dmy (1, 1, year);
284 if (day < 216) {
285 month = day / 31 + 1;
286 day = day % 31 + 1;
287 } else {
288 month = (day-6) / 30 + 1;
289 day = (day-6) % 30 + 1;
293 // FIXME: this may need a "static". I don't know enough C#.
294 internal bool is_leap_year(int year)
296 return (25 * year + 11) % 33 < 8;
299 /// <summary>
300 /// Overrideden. Adds months to a given date.
301 /// </summary>
302 /// <param name="time">The
303 /// <see cref="T:System.DateTime"/> to which to add
304 /// months.
305 /// </param>
306 /// <param name="months">The number of months to add.</param>
307 /// <returns>A new <see cref="T:System.DateTime"/> value, that
308 /// results from adding <paramref name="months"/> to the specified
309 /// DateTime.</returns>
310 /// <exception cref="T:System.ArgumentOutOfRangeException">
311 /// The exception is thrown if the
312 /// <see cref="T:System.DateTime"/> return value is not in the years
313 /// between 1 A.P. and 9999 C.E., inclusive.
314 /// </exception>
315 public override DateTime AddMonths(DateTime time, int months)
317 int rd = CCFixed.FromDateTime(time);
318 int day, month, year;
320 dmy_from_fixed(out day, out month, out year, rd);
321 month += months;
322 year += CCMath.div_mod(out month, month, 12);
323 rd = fixed_from_dmy(day, month, year);
324 DateTime t = CCFixed.ToDateTime(rd);
325 t = t.Add(time.TimeOfDay);
326 M_CheckDateTime(t);
327 return t;
330 /// <summary>
331 /// Overridden. Adds years to a given date.
332 /// </summary>
333 /// <param name="time">The
334 /// <see cref="T:System.DateTime"/> to which to add
335 /// years.
336 /// </param>
337 /// <param name="years">The number of years to add.</param>
338 /// <returns>A new <see cref="T:System.DateTime"/> value, that
339 /// results from adding <paramref name="years"/> to the specified
340 /// DateTime.</returns>
341 /// <exception cref="T:System.ArgumentOutOfRangeException">
342 /// The exception is thrown if the
343 /// <see cref="T:System.DateTime"/> return value is not in the years
344 /// between 1 A.P. and 9999 C.E., inclusive.
345 /// </exception>
346 public override DateTime AddYears(DateTime time, int years)
348 int rd = CCFixed.FromDateTime(time);
349 int day, month, year;
351 dmy_from_fixed(out day, out month, out year, rd);
352 year += years;
353 rd = fixed_from_dmy(day, month, year);
354 DateTime t = CCFixed.ToDateTime(rd);
355 t = t.Add(time.TimeOfDay);
356 M_CheckDateTime(t);
357 return t;
360 /// <summary>
361 /// Overriden. Gets the day of the month from
362 /// <paramref name="time"/>.
363 /// </summary>
364 /// <param name="time">The
365 /// <see cref="T:System.DateTime"/> that specifies a
366 /// date.
367 /// </param>
368 /// <returns>An integer giving the day of months, starting with 1.
369 /// </returns>
370 /// <exception cref="T:System.ArgumentOutOfRangeException">
371 /// The exception is thrown if the
372 /// <see cref="T:System.DateTime"/> parameter is not in the years
373 /// between 1 A.P. and 9999 C.E., inclusive.
374 /// </exception>
375 public override int GetDayOfMonth(DateTime time)
377 int day, month, year;
379 M_CheckDateTime(time);
380 int rd = CCFixed.FromDateTime(time);
381 dmy_from_fixed(out day, out month, out year, rd);
382 return day;
385 /// <summary>
386 /// Overriden. Gets the day of the week from the specified date.
387 /// </summary>
388 /// <param name="time">The
389 /// <see cref="T:System.DateTime"/> that specifies a
390 /// date.
391 /// </param>
392 /// <returns>An integer giving the day of months, starting with 1.
393 /// </returns>
394 /// <exception cref="T:System.ArgumentOutOfRangeException">
395 /// The exception is thrown if the
396 /// <see cref="T:System.DateTime"/> parameter is not in the years
397 /// between 1 A.P. and 9999 C.E., inclusive.
398 /// </exception>
399 public override DayOfWeek GetDayOfWeek(DateTime time)
401 M_CheckDateTime(time);
402 int rd = CCFixed.FromDateTime(time);
403 return (DayOfWeek)CCFixed.day_of_week(rd);
406 /// <summary>
407 /// Overridden. Gives the number of the day in the year.
408 /// </summary>
409 /// <param name="time">The
410 /// <see cref="T:System.DateTime"/> that specifies a
411 /// date.
412 /// </param>
413 /// <returns>An integer representing the day of the year,
414 /// starting with 1.</returns>
415 /// <exception cref="T:System.ArgumentOutOfRangeException">
416 /// The exception is thrown if the
417 /// <see cref="T:System.DateTime"/> parameter is not in the years
418 /// between 1 A.P. and 9999 C.E., inclusive.
419 /// </exception>
420 public override int GetDayOfYear(DateTime time)
422 M_CheckDateTime(time);
423 int rd = CCFixed.FromDateTime(time);
424 int year = year_from_fixed(rd);
425 int rd1_1 = fixed_from_dmy(1, 1, year);
426 return rd - rd1_1 + 1;
429 /// <summary>
430 /// Overridden. Gives the number of days in the specified month
431 /// of the given year and era.
432 /// </summary>
433 /// <param name="year">An integer that gives the year.
434 /// </param>
435 /// <param name="month">An integer that gives the month, starting
436 /// with 1.</param>
437 /// <param name="era">An integer that gives the era of the specified
438 /// year.</param>
439 /// <returns>An integer that gives the number of days of the
440 /// specified month.</returns>
441 /// <exception cref="T:System.ArgumentOutOfRangeException">
442 /// The exception is thrown, if <paramref name="month"/>,
443 /// <paramref name="year"/> ,or <paramref name="era"/> is outside
444 /// the allowed range.
445 /// </exception>
446 public override int GetDaysInMonth(int year, int month, int era)
448 M_CheckYME(year, month, ref era);
449 if (month <= 6) {
450 return 31;
451 } else if (month == 12 && !is_leap_year(year)) {
452 return 29;
453 } else {
454 return 30;
458 /// <summary>
459 /// Overridden. Gives the number of days of the specified
460 /// year of the given era.
461 /// </summary>
462 /// <param name="year">An integer that specifies the year.
463 /// </param>
464 /// <param name="era">An ineger that specifies the era.
465 /// </param>
466 /// <returns>An integer that gives the number of days of the
467 /// specified year.</returns>
468 /// <exception cref="T:System.ArgumentOutOfRangeExceiption">
469 /// The exception is thrown, if
470 /// <paramref name="year"/> or <paramref name="era"/> are outside the
471 /// allowed range.
472 /// </exception>
473 public override int GetDaysInYear(int year, int era)
475 M_CheckYE(year, ref era);
476 return is_leap_year(year) ? 366 : 365;
480 /// <summary>
481 /// Overridden. Gives the era of the specified date.
482 /// </summary>
483 /// <param name="time">The
484 /// <see cref="T:System.DateTime"/> that specifies a
485 /// date.
486 /// </param>
487 /// <returns>An integer representing the era of the calendar.
488 /// </returns>
489 /// <exception cref="T:System.ArgumentOutOfRangeException">
490 /// The exception is thrown if the
491 /// <see cref="T:System.DateTime"/> parameter is not in the years
492 /// between 1 A.P. and 9999 C.E., inclusive.
493 /// </exception>
494 public override int GetEra(DateTime time)
496 M_CheckDateTime(time);
497 return PersianEra;
500 public override int GetLeapMonth (int year, int era)
502 return 0;
505 /// <summary>
506 /// Overridden. Gives the number of the month of the specified
507 /// date.
508 /// </summary>
509 /// <param name="time">The
510 /// <see cref="T:System.DateTime"/> that specifies a
511 /// date.
512 /// </param>
513 /// <returns>An integer representing the month,
514 /// starting with 1.</returns>
515 /// <exception cref="T:System.ArgumentOutOfRangeException">
516 /// The exception is thrown if the
517 /// <see cref="T:System.DateTime"/> parameter is not in the years
518 /// between 1 A.P. and 9999 C.E., inclusive.
519 /// </exception>
520 public override int GetMonth(DateTime time)
522 M_CheckDateTime(time);
523 int rd = CCFixed.FromDateTime(time);
524 int month, year;
525 my_from_fixed(out month, out year, rd);
526 return month;
529 /// <summary>
530 /// Overridden. Gives the number of months in the specified year
531 /// and era.
532 /// </summary>
533 /// <param name="year">An integer that specifies the year.
534 /// </param>
535 /// <param name="era">An integer that specifies the era.
536 /// </param>
537 /// <returns>An integer that gives the number of the months in the
538 /// specified year.</returns>
539 /// <exception cref="T:System.ArgumentOutOfRangeException">
540 /// The exception is thrown, if the year or the era are not valid.
541 /// </exception>
542 public override int GetMonthsInYear(int year, int era)
544 M_CheckYE(year, ref era);
545 return 12;
548 /// <summary>
549 /// Overridden. Gives the number of the year of the specified
550 /// date.
551 /// </summary>
552 /// <param name="time">The
553 /// <see cref="T:System.DateTime"/> that specifies a
554 /// date.
555 /// </param>
556 /// <returns>An integer representing the year,
557 /// starting with 1.</returns>
558 /// <exception cref="T:System.ArgumentOutOfRangeException">
559 /// The exception is thrown if the
560 /// <see cref="T:System.DateTime"/> parameter is not in the years
561 /// between 1 A.P. and 9999 C.E., inclusive.
562 /// </exception>
563 public override int GetYear(DateTime time)
565 M_CheckDateTime(time);
566 int rd = CCFixed.FromDateTime(time);
567 return year_from_fixed(rd);
570 /// <summary>
571 /// Overridden. Tells whether the given day
572 /// is a leap day.
573 /// </summary>
574 /// <param name="year">An integer that specifies the year in the
575 /// given era.
576 /// </param>
577 /// <param name="month">An integer that specifies the month.
578 /// </param>
579 /// <param name="day">An integer that specifies the day.
580 /// </param>
581 /// <param name="era">An integer that specifies the era.
582 /// </param>
583 /// <returns>A boolean that tells whether the given day is a leap
584 /// day.
585 /// </returns>
586 /// <exception cref="T:System.ArgumentOutOfRangeException">
587 /// The exception is thrown, if the year, month, day, or era is not
588 /// valid.
589 /// </exception>
590 public override bool IsLeapDay(int year, int month, int day,
591 int era)
593 M_CheckYMDE(year, month, day, ref era);
594 return is_leap_year(year) && month == 12 && day == 30;
597 /// <summary>
598 /// Overridden. Tells whether the given month
599 /// is a leap month.
600 /// </summary>
601 /// <param name="year">An integer that specifies the year in the
602 /// given era.
603 /// </param>
604 /// <param name="month">An integer that specifies the month.
605 /// </param>
606 /// <param name="era">An integer that specifies the era.
607 /// </param>
608 /// <returns>A boolean that tells whether the given month is a leap
609 /// month.
610 /// </returns>
611 /// <exception cref="T:System.ArgumentOutOfRangeException">
612 /// The exception is thrown, if the year, month, or era is not
613 /// valid.
614 /// </exception>
615 public override bool IsLeapMonth(int year, int month, int era)
617 M_CheckYME(year, month, ref era);
618 return false;
621 /// <summary>
622 /// Overridden. Tells whether the given year
623 /// is a leap year.
624 /// </summary>
625 /// <param name="year">An integer that specifies the year in the
626 /// given era.
627 /// </param>
628 /// <param name="era">An integer that specifies the era.
629 /// </param>
630 /// <returns>A boolean that tells whether the given year is a leap
631 /// year.
632 /// </returns>
633 /// <exception cref="T:System.ArgumentOutOfRangeException">
634 /// The exception is thrown, if the year or era is not
635 /// valid.
636 /// </exception>
637 public override bool IsLeapYear(int year, int era)
639 M_CheckYE(year, ref era);
640 return is_leap_year(year);
643 /// <summary>
644 /// Overridden. Creates the
645 /// <see cref="T:System.DateTime"/> from the parameters.
646 /// </summary>
647 /// <param name="year">An integer that gives the year in the
648 /// <paramref name="era"/>.
649 /// </param>
650 /// <param name="month">An integer that specifies the month.
651 /// </param>
652 /// <param name="day">An integer that specifies the day.
653 /// </param>
654 /// <param name="hour">An integer that specifies the hour.
655 /// </param>
656 /// <param name="minute">An integer that specifies the minute.
657 /// </param>
658 /// <param name="second">An integer that gives the second.
659 /// </param>
660 /// <param name="milliseconds">An integer that gives the
661 /// milliseconds.
662 /// </param>
663 /// <param name="era">An integer that specifies the era.
664 /// </param>
665 /// <returns>A
666 /// <see cref="T:system.DateTime"/> representig the date and time.
667 /// </returns>
668 /// <exception cref="T:System.ArgumentOutOfRangeException">
669 /// The exception is thrown, if at least one of the parameters
670 /// is out of range.
671 /// </exception>
672 public override DateTime ToDateTime(int year, int month, int day,
673 int hour, int minute,
674 int second, int millisecond,
675 int era)
677 M_CheckYMDE(year, month, day, ref era);
678 M_CheckHMSM(hour, minute, second, millisecond);
679 int rd = fixed_from_dmy(day, month, year);
680 return CCFixed.ToDateTime(rd,
681 hour, minute, second, millisecond);
684 // FIXME: Calendar.cs and HebrewCalendar.cs are different in
685 // how they handle this. I have randomly chosen the
686 // HebrewCalendar.cs implementation.
687 public override int ToFourDigitYear (int year)
689 M_ArgumentInRange ("year", year, 0, 99);
691 int baseExtra = this.twoDigitYearMax % 100;
692 int baseCentury = this.twoDigitYearMax - baseExtra;
694 if (year <= baseExtra)
695 return baseCentury + year;
696 else
697 return baseCentury + year - 100;
700 public override CalendarAlgorithmType AlgorithmType {
701 get {
702 return CalendarAlgorithmType.SolarCalendar;
706 static DateTime PersianMin = new DateTime (622, 3, 21, 0, 0, 0);
707 static DateTime PersianMax = new DateTime (9999, 12, 31, 11, 59, 59);
709 public override DateTime MinSupportedDateTime {
710 get {
711 return PersianMin;
715 public override DateTime MaxSupportedDateTime {
716 get {
717 return PersianMax;
720 } // class PersianCalendar
722 } // namespace System.Globalization