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