Add unit test for AggregateException.GetBaseException that works on .net but is broke...
[mono.git] / mcs / class / corlib / System.Globalization / HijriCalendar.cs
1 // System.Globalization.HijriCalendar.cs
2 //
3 // (C) Ulrich Kunitz 2002
4 //
5
6 //
7 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 namespace System.Globalization {
30
31 using System;
32 using System.IO;
33 using System.Runtime.InteropServices;
34
35
36 /// <summary>
37 /// This is the Hijri calendar which might be called Islamic calendar. 
38 /// </summary>
39 /// <remarks>
40 /// <para>The calendar supports only dates in the HijriEra starting with the 
41 /// epoch.
42 /// </para>
43 /// <para>
44 /// The epoch of the Hijri Calendar might be adjusted by the 
45 /// <see cref="F:System.Globalization.HijriCalendar.AddHijriDate"/>
46 /// property. See the discussion of the
47 /// <see cref="F:CalendricalCalculations.HijriCalendar.epoch">
48 /// epoch
49 /// </see>
50 /// of the Hijri calendar.
51 /// </para>
52 /// <para>The implementation uses the
53 /// <see cref="N:CalendricalCalculations"/> namespace.
54 /// </para>
55 /// </remarks>
56 [Serializable]
57 [ComVisible (true)]
58 [MonoLimitation ("Serialization format not compatible with .NET")]
59 public class HijriCalendar : Calendar {
60         /// <summary>
61         /// Constructor.
62         /// </summary>
63         public HijriCalendar() {
64                 M_AbbrEraNames = new string[] {"A.H."};
65                 M_EraNames = new string[] {"Anno Hegirae"};
66                 if (twoDigitYearMax == 99)
67                         twoDigitYearMax = 1451;
68         }
69
70         /// <summary>
71         /// The era number for the Anno Hegirae (A.H.) era.
72         /// </summary>
73         public static readonly int HijriEra = 1;
74
75         /// <summary>
76         /// The minimum fixed day number supported by the Hijri calendar.
77         /// </summary>
78         internal static readonly int M_MinFixed =
79                 CCHijriCalendar.fixed_from_dmy(1, 1, 1);
80         /// <summary>
81         /// The maximum fixed day number supported by the Hijri calendar.
82         /// </summary>
83         internal static readonly int M_MaxFixed =
84                 CCGregorianCalendar.fixed_from_dmy(31, 12, 9999);
85
86         /// <value>Overridden. Gives the eras supported by the Gregorian
87         /// calendar as an array of integers.
88         /// </value>
89         public override int[] Eras {
90                 get {
91                         return new int[] { HijriEra }; 
92                 }
93         }
94
95         // FIXME: [MonoTODO ("Add call into operating system")]
96         public override int TwoDigitYearMax 
97         {
98                 get {
99                         return twoDigitYearMax;
100                 }
101                 set {
102                         CheckReadOnly ();
103                         M_ArgumentInRange ("value", value, 100, M_MaxYear);
104
105                         twoDigitYearMax = value;
106                 }
107         }
108
109         /// <summary>
110         /// Protected field storing the
111         /// <see cref="F:AddHijriDate"/>.
112         /// </summary>
113         internal int M_AddHijriDate = 0;
114
115         // TODO: I don't know currently, which sign to use with the parameter.
116         /// <value>An integer property representing the adjustment to the epoch
117         /// of the Hijri calendar. Not supported by .NET.
118         /// </value>
119         internal virtual int AddHijriDate {
120                 get {
121                         return M_AddHijriDate;
122                 }
123                 set {
124                         CheckReadOnly ();
125                         if (value < -3 && value > 3)
126                                 throw new ArgumentOutOfRangeException(
127                                         "AddHijriDate",
128                                         "Value should be between -3 and 3.");
129                         M_AddHijriDate = value;
130                 }
131         }
132         
133         /// <summary>
134         /// A protected method checking an
135         /// <see cref="F:AddHijriDate"/> adjusted fixed day number.
136         /// </summary>
137         /// <param name="param">A string giving the name of the parameter
138         /// to check.</param>
139         /// <param name="rdHijri">An integer giving the AddHijriDate adjusted
140         /// fixed day number.
141         /// </param>
142         /// <exception cref="T:System.ArgumentOutOfRangeException">
143         /// Exception is thrown, if the AddHijriDate adjusted fixed day
144         /// number is outside the supported range.
145         /// </exception>
146         internal void M_CheckFixedHijri(string param, int rdHijri) {
147                 if (rdHijri < M_MinFixed || rdHijri > M_MaxFixed-AddHijriDate) {
148                         StringWriter sw = new StringWriter();
149                         int day, month, year;
150                         CCHijriCalendar.dmy_from_fixed(out day, out month,
151                                 out year, M_MaxFixed-AddHijriDate);
152                         if (AddHijriDate != 0) {
153                                 sw.Write("This HijriCalendar " +
154                                         "(AddHijriDate {0})" +
155                                         " allows dates from 1. 1. 1 to " +
156                                         "{1}. {2}. {3}.",
157                                         AddHijriDate,
158                                         day, month, year);
159                         } else {
160                                 sw.Write("HijriCalendar allows dates from " +
161                                         "1.1.1 to {0}.{1}.{2}.",
162                                         day, month, year);
163                         }
164                         throw new ArgumentOutOfRangeException(param,
165                                 sw.ToString());
166                 }
167         }
168
169         /// <summary>
170         /// A protected member checking a
171         /// <see cref="T:System.DateTime"/> value.
172         /// </summary>
173         /// <param name="time">The
174         /// <see cref="T:System.DateTime"/>
175         /// to check.
176         /// </param>
177         /// <exception cref="T:System.ArgumentOutOfRangeException">
178         /// The exception is thrown if the
179         /// <see cref="T:System.DateTime"/> parameter is not in the supported 
180         /// range of the Hijri calendar.
181         /// </exception>
182         internal void M_CheckDateTime(DateTime time) {
183                 int rd = CCFixed.FromDateTime(time) - AddHijriDate;
184                 M_CheckFixedHijri("time", rd);
185         }
186
187         /// <summary>
188         /// Protected member which computes the
189         /// <see cref="F:AddHijriDate"/>
190         /// adjusted fixed day number from a
191         /// <see cref="T:System.DateTime"/>.
192         /// </summary>
193         /// <param name="time">The
194         /// <see cref="T:System.DateTime"/>
195         /// to convert.
196         /// </param>
197         /// <returns>The
198         /// <see cref="F:AddHijriDate"/> adjusted fixed day number.
199         /// </returns>
200         internal int M_FromDateTime(DateTime time) {
201                 return CCFixed.FromDateTime(time) - AddHijriDate;
202         }
203
204         /// <summary>
205         /// Protected member which converts the
206         /// <see cref="F:AddHijriDate"/>
207         /// adjusted fixed day number the a
208         /// <see cref="T:System.DateTime"/> value.
209         /// </summary>
210         /// <param name="rd">The
211         /// <see cref="F:AddHijriDate"/> adjusted fixed day number.
212         /// </param>
213         /// <returns>The converted
214         /// <see cref="T:System.DateTime"/> value.
215         /// </returns>
216         internal DateTime M_ToDateTime(int rd) {
217                 return CCFixed.ToDateTime(rd+AddHijriDate);
218         }
219
220         /// <summary>
221         /// Protected member which converts the
222         /// <see cref="F:AddHijriDate"/>
223         /// adjusted fixed day number the a
224         /// <see cref="T:System.DateTime"/> value using a number
225         /// of time parameters.
226         /// </summary>
227         /// <param name="date">The
228         /// <see cref="F:AddHijriDate"/> adjusted fixed day number.
229         /// </param>
230         /// <param name="hour">An integer that specifies the hour.
231         /// </param>
232         /// <param name="minute">An integer that specifies the minute.
233         /// </param>
234         /// <param name="second">An integer that gives the second.
235         /// </param>
236         /// <param name="milliseconds">An integer that gives the
237         /// milliseconds.
238         /// </param>
239         /// <returns>The converted
240         /// <see cref="T:System.DateTime"/> value.
241         /// </returns>
242         internal DateTime M_ToDateTime(int date,
243                 int hour, int minute, int second, int milliseconds)
244         {
245                 return CCFixed.ToDateTime(date+AddHijriDate,
246                         hour, minute, second, milliseconds);
247         }
248
249         /// <summary>
250         /// A protected method checking the era number.
251         /// </summary>
252         /// <param name="era">The era number.</param>
253         /// <exception name="T:System.ArgumentException">
254         /// The exception is thrown if the era is not equal
255         /// <see cref="F:HijriEra"/>.
256         /// </exception>
257         internal void M_CheckEra(ref int era) {
258                 if (era == CurrentEra)
259                         era = HijriEra;
260                 if (era != HijriEra)
261                         throw new ArgumentException("Era value was not valid.");
262         }
263
264         /// <summary>
265         /// A protected method checking calendar year and the era number.
266         /// </summary>
267         /// <param name="year">An integer representing the calendar year.
268         /// </param>
269         /// <param name="era">The era number.</param>
270         /// <exception cref="T:System.ArgumentException">
271         /// The exception is thrown if the era is not equal
272         /// <see cref="F:HijriEra"/>.
273         /// </exception>
274         /// <exception cref="T:System.ArgumentOutOfRangeException">
275         /// The exception is thrown if the calendar year is outside of
276         /// the allowed range.
277         /// </exception>
278         internal override void M_CheckYE(int year, ref int era) {
279                 M_CheckEra(ref era);
280                 M_ArgumentInRange("year", year, 1, 9666);
281         }
282
283         /// <summary>
284         /// A protected method checking the calendar year, month, and
285         /// era number.
286         /// </summary>
287         /// <param name="year">An integer representing the calendar year.
288         /// </param>
289         /// <param name="month">An integer giving the calendar month.
290         /// </param>
291         /// <param name="era">The era number.</param>
292         /// <exception cref="T:System.ArgumentException">
293         /// The exception is thrown if the era is not equal
294         /// <see cref="F:HijriEra"/>.
295         /// </exception>
296         /// <exception cref="T:System.ArgumentOutOfRangeException">
297         /// The exception is thrown if the calendar year or month is
298         /// outside of the allowed range.
299         /// </exception>
300         internal void M_CheckYME(int year, int month, ref int era) {
301                 M_CheckYE(year, ref era);
302                 if (month < 1 || month > 12)
303                         throw new ArgumentOutOfRangeException("month",
304                                 "Month must be between one and twelve.");
305                 if (year == 9666) {
306                         int rd = CCHijriCalendar.fixed_from_dmy(1, month, year);
307                         M_CheckFixedHijri("month", rd);
308                 }
309         }
310
311         /// <summary>
312         /// A protected method checking the calendar day, month, and year
313         /// and the era number.
314         /// </summary>
315         /// <param name="year">An integer representing the calendar year.
316         /// </param>
317         /// <param name="month">An integer giving the calendar month.
318         /// </param>
319         /// <param name="day">An integer giving the calendar day.
320         /// </param>
321         /// <param name="era">The era number.</param>
322         /// <exception cref="T:System.ArgumentException">
323         /// The exception is thrown if the era is not equal
324         /// <see cref="F:HijriEra"/>.
325         /// </exception>
326         /// <exception cref="T:System.ArgumentOutOfRangeException">
327         /// The exception is thrown if the calendar year, month, or day is
328         /// outside of the allowed range.
329         /// </exception>
330         internal void M_CheckYMDE(int year, int month, int day, ref int era)
331         {
332                 M_CheckYME(year, month, ref era);
333                 M_ArgumentInRange("day", day, 1,
334                         GetDaysInMonth(year, month, HijriEra));
335                 if (year == 9666) {
336                         int rd = CCHijriCalendar.fixed_from_dmy(day, month,
337                                 year);
338                         M_CheckFixedHijri("day", rd);
339                 }
340         }
341
342 #if false
343         //
344         // The following routines are commented out as they do not appear on the .NET Framework 1.1
345         //
346
347         /// <summary>
348         /// Overridden. Adds days to a given date.
349         /// </summary>
350         /// <param name="time">The
351         /// <see cref="T:System.DateTime"/> to which to add
352         /// days.
353         /// </param>
354         /// <param name="days">The number of days to add.</param>
355         /// <returns>A new <see cref="T:System.DateTime"/> value, that
356         /// results from adding <paramref name="days"/> to the specified
357         /// DateTime.</returns>
358         /// <exception cref="T:System.ArgumentOutOfRangeException">
359         /// The exception is thrown if the
360         /// <see cref="T:System.DateTime"/> return value is not in the
361         /// supported range of the Hijri calendar.
362         /// </exception>
363         public override DateTime AddDays(DateTime time, int days) {
364                 DateTime t = base.AddDays(time, days);
365                 M_CheckDateTime(t);
366                 return t;
367         }
368
369         /// <summary>
370         /// Overridden. Adds hours to a given date.
371         /// </summary>
372         /// <param name="time">The
373         /// <see cref="T:System.DateTime"/> to which to add
374         /// hours.
375         /// </param>
376         /// <param name="hours">The number of hours to add.</param>
377         /// <returns>A new <see cref="T:System.DateTime"/> value, that
378         /// results from adding <paramref name="hours"/> to the specified
379         /// DateTime.</returns>
380         /// <exception cref="T:System.ArgumentOutOfRangeException">
381         /// The exception is thrown if the
382         /// <see cref="T:System.DateTime"/> return value is not in the
383         /// supported range of the Hijri calendar.
384         /// </exception>
385         public override DateTime AddHours(DateTime time, int hours) {
386                 DateTime t = base.AddHours(time, hours);
387                 M_CheckDateTime(t);
388                 return t;
389         }
390
391         /// <summary>
392         /// Overridden. Adds milliseconds to a given date.
393         /// </summary>
394         /// <param name="time">The
395         /// <see cref="T:System.DateTime"/> to which to add
396         /// milliseconds.
397         /// </param>
398         /// <param name="milliseconds">The number of milliseconds given as
399         /// double to add. Keep in mind the 100 nanosecond resolution of 
400         /// <see cref="T:System.DateTime"/>.
401         /// </param>
402         /// <returns>A new <see cref="T:System.DateTime"/> value, that
403         /// results from adding <paramref name="milliseconds"/> to the specified
404         /// DateTime.</returns>
405         /// <exception cref="T:System.ArgumentOutOfRangeException">
406         /// The exception is thrown if the
407         /// <see cref="T:System.DateTime"/> return value is not in the
408         /// supported range of the Hijri calendar.
409         /// </exception>
410         public override DateTime AddMilliseconds(DateTime time,
411                 double milliseconds)
412         {
413                 DateTime t = base.AddMilliseconds(time, milliseconds);
414                 M_CheckDateTime(t);
415                 return t;
416         }
417
418         /// <summary>
419         /// Overridden. Adds minutes to a given date.
420         /// </summary>
421         /// <param name="time">The
422         /// <see cref="T:System.DateTime"/> to which to add
423         /// minutes.
424         /// </param>
425         /// <param name="minutes">The number of minutes to add.</param>
426         /// <returns>A new <see cref="T:System.DateTime"/> value, that
427         /// results from adding <paramref name="minutes"/> to the specified
428         /// DateTime.</returns>
429         /// <exception cref="T:System.ArgumentOutOfRangeException">
430         /// The exception is thrown if the
431         /// <see cref="T:System.DateTime"/> return value is not in the
432         /// supported range of the Hijri calendar.
433         /// </exception>
434         public override DateTime AddMinutes(DateTime time, int minutes) {
435                 DateTime t = base.AddMinutes(time, minutes);
436                 M_CheckDateTime(t);
437                 return t;
438         }
439
440         /// <summary>
441         /// Overridden. Adds seconds to a given date.
442         /// </summary>
443         /// <param name="time">The
444         /// <see cref="T:System.DateTime"/> to which to add
445         /// seconds.
446         /// </param>
447         /// <param name="seconds">The number of seconds to add.</param>
448         /// <returns>A new <see cref="T:System.DateTime"/> value, that
449         /// results from adding <paramref name="seconds"/> to the specified
450         /// DateTime.</returns>
451         /// <exception cref="T:System.ArgumentOutOfRangeException">
452         /// The exception is thrown if the
453         /// <see cref="T:System.DateTime"/> return value is not in the
454         /// supported range of the Hijri calendar.
455         /// </exception>
456         public override DateTime AddSeconds(DateTime time, int seconds) {
457                 DateTime t = base.AddSeconds(time, seconds);
458                 M_CheckDateTime(t);
459                 return t;
460         }
461
462         /// <summary>
463         /// Overridden. Adds weeks to a given date.
464         /// </summary>
465         /// <param name="time">The
466         /// <see cref="T:System.DateTime"/> to which to add
467         /// weeks.
468         /// </param>
469         /// <param name="weeks">The number of weeks to add.</param>
470         /// <returns>A new <see cref="T:System.DateTime"/> value, that
471         /// results from adding <paramref name="weeks"/> to the specified
472         /// DateTime.</returns>
473         /// <exception cref="T:System.ArgumentOutOfRangeException">
474         /// The exception is thrown if the
475         /// <see cref="T:System.DateTime"/> return value is not in the
476         /// supported range of the Hijri calendar.
477         /// </exception>
478         public override DateTime AddWeeks(DateTime time, int weeks) {
479                 DateTime t = base.AddWeeks(time, weeks);
480                 M_CheckDateTime(t);
481                 return t;
482         }
483
484         /// <summary>
485         /// Overridden. Gives the hour of the specified time.
486         /// </summary>
487         /// <param name="time">The
488         /// <see cref="T:System.DateTime"/> that specifies the
489         /// time.
490         /// </param>
491         /// <returns>An integer that gives the hour of the specified time,
492         /// starting with 0.</returns>
493         /// <exception cref="T:System.ArgumentOutOfRangeException">
494         /// The exception is thrown if the
495         /// <see cref="T:System.DateTime"/> parameter is not in the
496         /// supported range of the Hijri calendar.
497         /// </exception>
498         public override int GetHour(DateTime time) {
499                 M_CheckDateTime(time);
500                 return base.GetHour(time);
501         }
502
503         /// <summary>
504         /// Overridden. Gives the milliseconds in the current second
505         /// of the specified time.
506         /// </summary>
507         /// <param name="time">The
508         /// <see cref="T:System.DateTime"/> that specifies the
509         /// time.
510         /// </param>
511         /// <returns>An integer that gives the milliseconds in the seconds
512         /// of the specified time, starting with 0.</returns>
513         /// <exception cref="T:System.ArgumentOutOfRangeException">
514         /// The exception is thrown if the
515         /// <see cref="T:System.DateTime"/> parameter is not in the
516         /// supported range of the Hijri calendar.
517         /// </exception>
518         public override double GetMilliseconds(DateTime time) {
519                 M_CheckDateTime(time);
520                 return base.GetMilliseconds(time);
521         }
522
523         /// <summary>
524         /// Overridden. Gives the minute of the specified time.
525         /// </summary>
526         /// <param name="time">The
527         /// <see cref="T:System.DateTime"/> that specifies the
528         /// time.
529         /// </param>
530         /// <returns>An integer that gives the minute of the specified time,
531         /// starting with 0.</returns>
532         /// <exception cref="T:System.ArgumentOutOfRangeException">
533         /// The exception is thrown if the
534         /// <see cref="T:System.DateTime"/> parameter is not in the
535         /// supported range of the Hijri calendar.
536         /// </exception>
537         public override int GetMinute(DateTime time) {
538                 M_CheckDateTime(time);
539                 return base.GetMinute(time);
540         }
541
542         /// <summary>
543         /// Overridden. Gives the second of the specified time.
544         /// </summary>
545         /// <param name="time">The
546         /// <see cref="T:System.DateTime"/> that specifies the
547         /// time.
548         /// </param>
549         /// <returns>An integer that gives the second of the specified time,
550         /// starting with 0.</returns>
551         /// <exception cref="T:System.ArgumentOutOfRangeException">
552         /// The exception is thrown if the
553         /// <see cref="T:System.DateTime"/> parameter is not in the
554         /// supported range of the Hijri calendar.
555         /// </exception>
556         public override int GetSecond(DateTime time) {
557                 M_CheckDateTime(time);
558                 return base.GetMinute(time);
559         }
560 #endif
561         
562         /// <summary>
563         /// Overrideden. Adds months to a given date.
564         /// </summary>
565         /// <param name="time">The
566         /// <see cref="T:System.DateTime"/> to which to add
567         /// months.
568         /// </param>
569         /// <param name="months">The number of months to add.</param>
570         /// <returns>A new <see cref="T:System.DateTime"/> value, that
571         /// results from adding <paramref name="months"/> to the specified
572         /// DateTime.</returns>
573         /// <exception cref="T:System.ArgumentOutOfRangeException">
574         /// The exception is thrown if the
575         /// <see cref="T:System.DateTime"/> return value is not in the
576         /// supported range of the Hijri calendar.
577         /// </exception>
578         public override DateTime AddMonths(DateTime time, int months) {
579                 int rd = M_FromDateTime(time);
580                 int day, month, year;
581                 CCHijriCalendar.dmy_from_fixed(
582                         out day, out month, out year, rd);
583                 month += months;
584                 year += CCMath.div_mod(out month, month, 12);
585                 rd = CCHijriCalendar.fixed_from_dmy(day, month, year);
586                 M_CheckFixedHijri("time", rd);
587                 DateTime t = M_ToDateTime(rd);
588                 return t.Add(time.TimeOfDay);
589         }
590
591         /// <summary>
592         /// Overrideden. Adds years to a given date.
593         /// </summary>
594         /// <param name="time">The
595         /// <see cref="T:System.DateTime"/> to which to add
596         /// years.
597         /// </param>
598         /// <param name="years">The number of years to add.</param>
599         /// <returns>A new <see cref="T:System.DateTime"/> value, that
600         /// results from adding <paramref name="years"/> to the specified
601         /// DateTime.</returns>
602         /// <exception cref="T:System.ArgumentOutOfRangeException">
603         /// The exception is thrown if the
604         /// <see cref="T:System.DateTime"/> return value is not in the
605         /// supported range of the Hijri calendar.
606         /// </exception>
607         public override DateTime AddYears(DateTime time, int years) {
608                 int rd = M_FromDateTime(time);
609                 int day, month, year;
610                 CCHijriCalendar.dmy_from_fixed(
611                         out day, out month, out year, rd);
612                 year += years;
613                 rd = CCHijriCalendar.fixed_from_dmy(day, month, year);
614                 M_CheckFixedHijri("time", rd);
615                 DateTime t = M_ToDateTime(rd);
616                 return t.Add(time.TimeOfDay);
617         }
618                 
619         /// <summary>
620         /// Overriden. Gets the day of the month from
621         /// <paramref name="time"/>.
622         /// </summary>
623         /// <param name="time">The
624         /// <see cref="T:System.DateTime"/> that specifies a
625         /// date.
626         /// </param>
627         /// <returns>An integer giving the day of months, starting with 1.
628         /// </returns>
629         /// <exception cref="T:System.ArgumentOutOfRangeException">
630         /// The exception is thrown if the
631         /// <see cref="T:System.DateTime"/> parameter is not in the
632         /// supported range of the Hijri calendar.
633         /// </exception>
634         public override int GetDayOfMonth(DateTime time) {
635                 int rd = M_FromDateTime(time);
636                 M_CheckFixedHijri("time", rd);
637                 return CCHijriCalendar.day_from_fixed(rd);
638         }
639
640         /// <summary>
641         /// Overriden. Gets the day of the week from the specified date.
642         /// </summary>
643         /// <param name="time">The
644         /// <see cref="T:System.DateTime"/> that specifies a
645         /// date.
646         /// </param>
647         /// <returns>An integer giving the day of months, starting with 1.
648         /// </returns>
649         /// <exception cref="T:System.ArgumentOutOfRangeException">
650         /// The exception is thrown if the
651         /// <see cref="T:System.DateTime"/> parameter is not in the
652         /// supported range of the Hijri calendar.
653         /// </exception>
654         public override DayOfWeek GetDayOfWeek(DateTime time) {
655                 int rd = M_FromDateTime(time);
656                 M_CheckFixedHijri("time", rd);
657                 return (DayOfWeek)CCFixed.day_of_week(rd);
658         }
659
660         /// <summary>
661         /// Overridden. Gives the number of the day in the year.
662         /// </summary>
663         /// <param name="time">The
664         /// <see cref="T:System.DateTime"/> that specifies a
665         /// date.
666         /// </param>
667         /// <returns>An integer representing the day of the year,
668         /// starting with 1.</returns>
669         /// <exception cref="T:System.ArgumentOutOfRangeException">
670         /// The exception is thrown if the
671         /// <see cref="T:System.DateTime"/> parameter is not in the
672         /// supported range of the Hijri calendar.
673         /// </exception>
674         public override int GetDayOfYear(DateTime time) {
675                 int rd = M_FromDateTime(time);
676                 M_CheckFixedHijri("time", rd);
677                 int year = CCHijriCalendar.year_from_fixed(rd);
678                 int rd1_1 = CCHijriCalendar.fixed_from_dmy(1, 1, year);
679                 return rd - rd1_1 + 1;
680         }
681
682         /// <summary>
683         /// Overridden. Gives the number of days in the specified month
684         /// of the given year and era.
685         /// </summary>
686         /// <param name="year">An integer that gives the year.
687         /// </param>
688         /// <param name="month">An integer that gives the month, starting
689         /// with 1.</param>
690         /// <param name="era">An intger that gives the era of the specified
691         /// year.</param>
692         /// <returns>An integer that gives the number of days of the
693         /// specified month.</returns>
694         /// <exception cref="T:System.ArgumentOutOfRangeException">
695         /// The exception is thrown, if <paramref name="month"/>,
696         /// <paramref name="year"/> ,or <paramref name="era"/> is outside
697         /// the allowed range.
698         /// </exception>
699         public override int GetDaysInMonth(int year, int month, int era) {
700                 M_CheckYME(year, month, ref era);
701                 int rd1 = CCHijriCalendar.fixed_from_dmy(1, month, year);
702                 int rd2 = CCHijriCalendar.fixed_from_dmy(1, month+1, year);
703                 return rd2 - rd1;
704         }
705
706         /// <summary>
707         /// Overridden. Gives the number of days of the specified
708         /// year of the given era. 
709         /// </summary>
710         /// <param name="year">An integer that specifies the year. 
711         /// </param>
712         /// <param name="era">An ineger that specifies the era.
713         /// </param>
714         /// <returns>An integer that gives the number of days of the
715         /// specified year.</returns>
716         /// <exception cref="T:System.ArgumentOutOfRangeExceiption">
717         /// The exception is thrown, if
718         /// <paramref name="year"/> is outside the allowed range.
719         /// </exception>
720         public override int GetDaysInYear(int year, int era) {
721                 M_CheckYE(year, ref era);
722                 int rd1 = CCHijriCalendar.fixed_from_dmy(1, 1, year);
723                 int rd2 = CCHijriCalendar.fixed_from_dmy(1, 1, year+1);
724                 return rd2 - rd1;
725         }
726                 
727
728         /// <summary>
729         /// Overridden. Gives the era of the specified date.
730         /// </summary>
731         /// <param name="time">The
732         /// <see cref="T:System.DateTime"/> that specifies a
733         /// date.
734         /// </param>
735         /// <returns>An integer representing the era of the calendar.
736         /// </returns>
737         /// <exception cref="T:System.ArgumentOutOfRangeException">
738         /// The exception is thrown if the
739         /// <see cref="T:System.DateTime"/> parameter is not in the
740         /// supported range of the Hijri calendar.
741         /// </exception>
742         public override int GetEra(DateTime time) {
743                 M_CheckDateTime(time);
744                 return HijriEra;
745         }
746
747         [ComVisible (false)]
748         public override int GetLeapMonth (int year, int era)
749         {
750                 return 0;
751         }
752
753         /// <summary>
754         /// Overridden. Gives the number of the month of the specified
755         /// date.
756         /// </summary>
757         /// <param name="time">The
758         /// <see cref="T:System.DateTime"/> that specifies a
759         /// date.
760         /// </param>
761         /// <returns>An integer representing the month, 
762         /// starting with 1.</returns>
763         /// <exception cref="T:System.ArgumentOutOfRangeException">
764         /// The exception is thrown if the
765         /// <see cref="T:System.DateTime"/> parameter is not in the
766         /// supported range of the Hijri calendar.
767         /// </exception>
768         public override int GetMonth(DateTime time) {
769                 int rd = M_FromDateTime(time);
770                 M_CheckFixedHijri("time", rd);
771                 return CCHijriCalendar.month_from_fixed(rd);
772         }
773
774         /// <summary>
775         /// Overridden. Gives the number of months in the specified year 
776         /// and era.
777         /// </summary>
778         /// <param name="year">An integer that specifies the year.
779         /// </param>
780         /// <param name="era">An integer that specifies the era.
781         /// </param>
782         /// <returns>An integer that gives the number of the months in the
783         /// specified year.</returns>
784         /// <exception cref="T:System.ArgumentOutOfRangeException">
785         /// The exception is thrown, if the year or the era are not valid.
786         /// </exception>
787         public override int GetMonthsInYear(int year, int era) {
788                 M_CheckYE(year, ref era);
789                 return 12;
790         }
791
792         /// <summary>
793         /// Overridden. Gives the number of the year of the specified
794         /// date.
795         /// </summary>
796         /// <param name="time">The
797         /// <see cref="T:System.DateTime"/> that specifies a
798         /// date.
799         /// </param>
800         /// <returns>An integer representing the year, 
801         /// starting with 1.</returns>
802         /// <exception cref="T:System.ArgumentOutOfRangeException">
803         /// The exception is thrown if the
804         /// <see cref="T:System.DateTime"/> parameter is not in the
805         /// supported range of the Hijri calendar.
806         /// </exception>
807         public override int GetYear(DateTime time) {
808                 int rd = M_FromDateTime(time);
809                 M_CheckFixedHijri("time", rd);
810                 return CCHijriCalendar.year_from_fixed(rd);
811         }
812
813         /// <summary>
814         /// Overridden. Tells whether the given day 
815         /// is a leap day.
816         /// </summary>
817         /// <param name="year">An integer that specifies the year in the
818         /// given era.
819         /// </param>
820         /// <param name="month">An integer that specifies the month.
821         /// </param>
822         /// <param name="day">An integer that specifies the day.
823         /// </param>
824         /// <param name="era">An integer that specifies the era.
825         /// </param>
826         /// <returns>A boolean that tells whether the given day is a leap
827         /// day.
828         /// </returns>
829         /// <exception cref="T:System.ArgumentOutOfRangeException">
830         /// The exception is thrown, if the year, month, day, or era is not
831         /// valid.
832         /// </exception>
833         public override bool IsLeapDay(int year, int month, int day, int era)
834         {
835                 M_CheckYMDE(year, month, day, ref era);
836                 return IsLeapYear(year) && month == 12 && day == 30;
837         }
838
839         /// <summary>
840         /// Overridden. Tells whether the given month 
841         /// is a leap month.
842         /// </summary>
843         /// <param name="year">An integer that specifies the year in the
844         /// given era.
845         /// </param>
846         /// <param name="month">An integer that specifies the month.
847         /// </param>
848         /// <param name="era">An integer that specifies the era.
849         /// </param>
850         /// <returns>A boolean that tells whether the given month is a leap
851         /// month.
852         /// </returns>
853         /// <exception cref="T:System.ArgumentOutOfRangeException">
854         /// The exception is thrown, if the year, month, or era is not
855         /// valid.
856         /// </exception>
857         public override bool IsLeapMonth(int year, int month, int era) {
858                 M_CheckYME(year, month, ref era);
859                 return false;
860         }
861
862         /// <summary>
863         /// Overridden. Tells whether the given year
864         /// is a leap year.
865         /// </summary>
866         /// <param name="year">An integer that specifies the year in the
867         /// given era.
868         /// </param>
869         /// <param name="era">An integer that specifies the era.
870         /// </param>
871         /// <returns>A boolean that tells whether the given year is a leap
872         /// year.
873         /// </returns>
874         /// <exception cref="T:System.ArgumentOutOfRangeException">
875         /// The exception is thrown, if the year or era is not
876         /// valid.
877         /// </exception>
878         public override bool IsLeapYear(int year, int era) {
879                 M_CheckYE(year, ref era);
880                 return CCHijriCalendar.is_leap_year(year);
881         }
882
883         /// <summary>
884         /// Overridden. Creates the
885         /// <see cref="T:System.DateTime"/> from the parameters.
886         /// </summary>
887         /// <param name="year">An integer that gives the year in the
888         /// <paramref name="era"/>.
889         /// </param>
890         /// <param name="month">An integer that specifies the month.
891         /// </param>
892         /// <param name="day">An integer that specifies the day.
893         /// </param>
894         /// <param name="hour">An integer that specifies the hour.
895         /// </param>
896         /// <param name="minute">An integer that specifies the minute.
897         /// </param>
898         /// <param name="second">An integer that gives the second.
899         /// </param>
900         /// <param name="milliseconds">An integer that gives the
901         /// milliseconds.
902         /// </param>
903         /// <param name="era">An integer that specifies the era.
904         /// </param>
905         /// <returns>A
906         /// <see cref="T:system.DateTime"/> representig the date and time.
907         /// </returns>
908         /// <exception cref="T:System.ArgumentOutOfRangeException">
909         /// The exception is thrown, if at least one of the parameters
910         /// is out of range.
911         /// </exception>
912         public override DateTime ToDateTime(int year, int month, int day,
913                 int hour, int minute, int second, int millisecond,
914                 int era)
915         {
916                 M_CheckYMDE(year, month, day, ref era);
917                 M_CheckHMSM(hour, minute, second, millisecond);
918                 int rd = CCHijriCalendar.fixed_from_dmy(day, month, year);
919                 return M_ToDateTime(rd,
920                         hour, minute, second, millisecond);
921         }
922
923         public override int ToFourDigitYear(int year)
924         {
925                 return base.ToFourDigitYear (year);
926         }
927
928 #if !NET_2_1
929         [ComVisible (false)]
930         public override CalendarAlgorithmType AlgorithmType  {
931                 get {
932                         return CalendarAlgorithmType.LunarCalendar;
933                 }
934         }
935 #endif
936
937         static DateTime Min = new DateTime (622, 7, 18, 0, 0, 0);
938         static DateTime Max = new DateTime (9999, 12, 31, 11, 59, 59);
939                 
940         [ComVisible (false)]
941         public override DateTime MinSupportedDateTime {
942                 get {
943                         return Min;
944                 }
945         }
946
947         [ComVisible (false)]
948         public override DateTime MaxSupportedDateTime {
949                 get {
950                         return Max;
951                 }
952         }
953         
954         [MonoTODO ()]
955         public int HijriAdjustment {
956                 get { throw new NotImplementedException (); }
957                 set { throw new NotImplementedException (); }
958         }
959 } // class HijriCalendar
960         
961 } // namespace System.Globalization