Merge pull request #726 from pruiz/xamarin-bug-13708
[mono.git] / mcs / class / corlib / System.Globalization / HebrewCalendar.cs
1 // System.Globalization.HebrewCalendar.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 /// <summary>
36 /// This is the Hebrew calendar.
37 /// </summary>
38 /// <remarks>
39 /// <para>The Hebrew calendar supports only years between 5343 A.M. and
40 /// 6000 A.M. This has been done to be compatible with .NET.
41 /// </para>
42 /// <para>The implementation uses the
43 /// <see cref="N:CalendricalCalculations"/> namespace.
44 /// </para>
45 /// </remarks>
46 [Serializable]
47 [MonoLimitation ("Serialization format not compatible with.NET")]
48 public class HebrewCalendar : Calendar {
49         /// <summary>
50         /// Constructor.
51         /// </summary>
52         public HebrewCalendar() {
53                 M_AbbrEraNames = new string[] {"A.M."};
54                 M_EraNames = new string[] {"Anno Mundi"};
55                 if (twoDigitYearMax == 99)
56                         twoDigitYearMax = 5790;
57         }
58
59         /// <summary>
60         /// The era number for the Anno Mundi (A.M.) era, called
61         /// plain HebrewEra.
62         /// </summary>
63         public static readonly int HebrewEra = 1;
64
65         /// <summary>
66         /// The
67         /// <see cref="T:System.DateTime"/> ticks for first day of year
68         /// 5343 A.M.
69         /// </summary>
70         internal const long M_MinTicks = 499147488000000000L;
71         /// <summary>
72         /// The number of
73         /// <see cref="T:System.DateTime"/> ticks for the last day of year
74         /// 6000 A.M.
75         /// </summary>
76         internal const long M_MaxTicks = 706783967999999999L;
77         /// <summary>
78         /// The minimum year in the A.M. era supported.
79         /// </summary>
80         internal const int M_MinYear = 5343;
81         /// <summary>
82         /// The maximum year supported in the A.M. era.
83         /// </summary>
84         internal override int M_MaxYear {
85                 get { return 6000; }
86         }
87
88         /// <value>Overridden. Gives the eras supported by the Gregorian
89         /// calendar as an array of integers.
90         /// </value>
91         public override int[] Eras {
92                 get {
93                         return new int[] { HebrewEra }; 
94                 }
95         }
96
97         public override int TwoDigitYearMax 
98         {
99                 get {
100                         return twoDigitYearMax;
101                 }
102                 set {
103                         CheckReadOnly ();
104                         M_ArgumentInRange ("value", value, M_MinYear, M_MaxYear);
105
106                         twoDigitYearMax = value;
107                 }
108         }
109
110         /// <summary>
111         /// A protected member checking a
112         /// <see cref="T:System.DateTime"/> value.
113         /// </summary>
114         /// <param name="time">The
115         /// <see cref="T:System.DateTime"/>
116         /// to check.
117         /// </param>
118         /// <exception cref="T:System.ArgumentOutOfRangeException">
119         /// The exception is thrown if the
120         /// <see cref="T:System.DateTime"/> parameter is not in the years
121         /// between 5343 A.M. and 6000 A.M., inclusive.
122         /// </exception>
123         internal void M_CheckDateTime(DateTime time) {
124                 if (time.Ticks < M_MinTicks || time.Ticks > M_MaxTicks)
125                         throw new ArgumentOutOfRangeException(
126                                 "time",
127                                 "Only hebrew years between 5343 and 6000," +
128                                 " inclusive, are supported.");
129         }
130
131         /// <summary>
132         /// A protected method checking the era number.
133         /// </summary>
134         /// <param name="era">The era number.</param>
135         /// <exception name="T:System.ArgumentException">
136         /// The exception is thrown if the era is not equal
137         /// <see cref="F:HebrewEra"/>.
138         /// </exception>
139         internal void M_CheckEra(ref int era) {
140                 if (era == CurrentEra)
141                         era = HebrewEra;
142                 if (era != HebrewEra)
143                         throw new ArgumentException("Era value was not valid.");
144         }
145
146         /// <summary>
147         /// A protected method checking calendar year and the era number.
148         /// </summary>
149         /// <param name="year">An integer representing the calendar year.
150         /// </param>
151         /// <param name="era">The era number.</param>
152         /// <exception cref="T:System.ArgumentException">
153         /// The exception is thrown if the era is not equal
154         /// <see cref="F:HebrewEra"/>.
155         /// </exception>
156         /// <exception cref="T:System.ArgumentOutOfRangeException">
157         /// The exception is thrown if the calendar year is outside of
158         /// the allowed range.
159         /// </exception>
160         internal override void M_CheckYE(int year, ref int era) {
161                 M_CheckEra(ref era);
162                 if (year < M_MinYear || year > M_MaxYear)
163                         throw new ArgumentOutOfRangeException(
164                                 "year",
165                                 "Only hebrew years between 5343 and 6000," +
166                                 " inclusive, are supported.");
167         }
168
169         /// <summary>
170         /// A protected method checking the calendar year, month, and
171         /// era number.
172         /// </summary>
173         /// <param name="year">An integer representing the calendar year.
174         /// </param>
175         /// <param name="month">An integer giving the calendar month.
176         /// </param>
177         /// <param name="era">The era number.</param>
178         /// <exception cref="T:System.ArgumentException">
179         /// The exception is thrown if the era is not equal
180         /// <see cref="F:HebrewEra"/>.
181         /// </exception>
182         /// <exception cref="T:System.ArgumentOutOfRangeException">
183         /// The exception is thrown if the calendar year or month is
184         /// outside of the allowed range.
185         /// </exception>
186         internal void M_CheckYME(int year, int month, ref int era) {
187                 M_CheckYE(year, ref era);
188                 int l = CCHebrewCalendar.last_month_of_year(year);
189                 if (month < 1 || month > l) {
190                         StringWriter sw = new StringWriter();
191                         sw.Write("Month must be between 1 and {0}.", l);
192                         throw new ArgumentOutOfRangeException("month",
193                                 sw.ToString());
194                 }
195         }
196
197         /// <summary>
198         /// A protected method checking the calendar day, month, and year
199         /// and the era number.
200         /// </summary>
201         /// <param name="year">An integer representing the calendar year.
202         /// </param>
203         /// <param name="month">An integer giving the calendar month.
204         /// </param>
205         /// <param name="day">An integer giving the calendar day.
206         /// </param>
207         /// <param name="era">The era number.</param>
208         /// <exception cref="T:System.ArgumentException">
209         /// The exception is thrown if the era is not equal
210         /// <see cref="F:HebrewEra"/>.
211         /// </exception>
212         /// <exception cref="T:System.ArgumentOutOfRangeException">
213         /// The exception is thrown if the calendar year, month, or day is
214         /// outside of the allowed range.
215         /// </exception>
216         internal void M_CheckYMDE(int year, int month, int day,
217                 ref int era)
218         {
219                 M_CheckYME(year, month, ref era);
220                 M_ArgumentInRange("day", day, 1, GetDaysInMonth(year, month,
221                         era));
222         }
223
224         
225         /// <summary>
226         /// Overrideden. Adds months to a given date.
227         /// </summary>
228         /// <param name="time">The
229         /// <see cref="T:System.DateTime"/> to which to add
230         /// months.
231         /// </param>
232         /// <param name="months">The number of months to add.</param>
233         /// <returns>A new <see cref="T:System.DateTime"/> value, that
234         /// results from adding <paramref name="months"/> to the specified
235         /// DateTime.</returns>
236         /// <exception cref="T:System.ArgumentOutOfRangeException">
237         /// The exception is thrown if the
238         /// <see cref="T:System.DateTime"/> return value is not in the years
239         /// between 5343 A.M. and 6000 A.M., inclusive.
240         /// </exception>
241         public override DateTime AddMonths(DateTime time, int months) {
242                 int y, m, d;
243                 DateTime t;
244
245                 if (months == 0) {
246                         t = time;
247                 } else {
248                         int rd = CCFixed.FromDateTime(time);
249                         CCHebrewCalendar.dmy_from_fixed(
250                                 out d, out m, out y, rd);
251                         m = M_Month(m, y);
252                         if (months < 0) {
253                                 while (months < 0) {
254                                         if (m+months > 0) {
255                                                 m += months;
256                                                 months = 0;
257                                         } else {
258                                                 months += m;
259                                                 y -= 1;
260                                                 m = GetMonthsInYear(y);
261                                         }
262                                 }
263                         }
264                         else {
265                                 while (months > 0) {
266                                         int my = GetMonthsInYear(y);
267                                         if (m+months <= my) {
268                                                 m += months;
269                                                 months = 0;
270                                         } else {
271                                                 months -= my-m+1;
272                                                 m = 1;
273                                                 y += 1;
274                                         }
275                                 }
276                         }
277                         t = ToDateTime(y, m, d, 0, 0, 0, 0);
278                         t = t.Add(time.TimeOfDay);
279                 }
280                 M_CheckDateTime(t);
281                 return t;
282         }
283
284         /// <summary>
285         /// Overridden. Adds years to a given date.
286         /// </summary>
287         /// <param name="time">The
288         /// <see cref="T:System.DateTime"/> to which to add
289         /// years.
290         /// </param>
291         /// <param name="years">The number of years to add.</param>
292         /// <returns>A new <see cref="T:System.DateTime"/> value, that
293         /// results from adding <paramref name="years"/> to the specified
294         /// DateTime.</returns>
295         /// <exception cref="T:System.ArgumentOutOfRangeException">
296         /// The exception is thrown if the
297         /// <see cref="T:System.DateTime"/> return value is not in the years
298         /// between 5343 A.M. and 6000 A.M., inclusive.
299         /// </exception>
300         public override DateTime AddYears(DateTime time, int years) {
301                 int rd = CCFixed.FromDateTime(time);
302                 int day, month, year;
303                 CCHebrewCalendar.dmy_from_fixed(
304                         out day, out month, out year, rd);
305                 year += years;
306                 rd = CCHebrewCalendar.fixed_from_dmy(day, month, year);
307                 DateTime t = CCFixed.ToDateTime(rd);
308                 t = t.Add(time.TimeOfDay);
309                 M_CheckDateTime(t);
310                 return t;
311         }
312                 
313         /// <summary>
314         /// Overriden. Gets the day of the month from
315         /// <paramref name="time"/>.
316         /// </summary>
317         /// <param name="time">The
318         /// <see cref="T:System.DateTime"/> that specifies a
319         /// date.
320         /// </param>
321         /// <returns>An integer giving the day of months, starting with 1.
322         /// </returns>
323         /// <exception cref="T:System.ArgumentOutOfRangeException">
324         /// The exception is thrown if the
325         /// <see cref="T:System.DateTime"/> parameter is not in the years
326         /// between 5343 A.M. and 6000 A.M., inclusive.
327         /// </exception>
328         public override int GetDayOfMonth(DateTime time) {
329                 M_CheckDateTime(time);
330                 int rd = CCFixed.FromDateTime(time);
331                 return CCHebrewCalendar.day_from_fixed(rd);
332         }
333
334         /// <summary>
335         /// Overriden. Gets the day of the week from the specified date.
336         /// </summary>
337         /// <param name="time">The
338         /// <see cref="T:System.DateTime"/> that specifies a
339         /// date.
340         /// </param>
341         /// <returns>An integer giving the day of months, starting with 1.
342         /// </returns>
343         /// <exception cref="T:System.ArgumentOutOfRangeException">
344         /// The exception is thrown if the
345         /// <see cref="T:System.DateTime"/> parameter is not in the years
346         /// between 5343 A.M. and 6000 A.M., inclusive.
347         /// </exception>
348         public override DayOfWeek GetDayOfWeek(DateTime time) {
349                 M_CheckDateTime(time);
350                 int rd = CCFixed.FromDateTime(time);
351                 return (DayOfWeek)CCFixed.day_of_week(rd);
352         }
353
354         /// <summary>
355         /// Overridden. Gives the number of the day in the year.
356         /// </summary>
357         /// <param name="time">The
358         /// <see cref="T:System.DateTime"/> that specifies a
359         /// date.
360         /// </param>
361         /// <returns>An integer representing the day of the year,
362         /// starting with 1.</returns>
363         /// <exception cref="T:System.ArgumentOutOfRangeException">
364         /// The exception is thrown if the
365         /// <see cref="T:System.DateTime"/> parameter is not in the years
366         /// between 5343 A.M. and 6000 A.M., inclusive.
367         /// </exception>
368         public override int GetDayOfYear(DateTime time) {
369                 M_CheckDateTime(time);
370                 int rd = CCFixed.FromDateTime(time);
371                 int year = CCHebrewCalendar.year_from_fixed(rd);
372                 int rd1_7 = CCHebrewCalendar.fixed_from_dmy(1, 7, year);
373                 return rd - rd1_7 + 1;
374         }
375
376         /// <summary>
377         /// The method maps a .NET Hebrew month to a Calencdrical
378         /// Calculations Hebrew month. 
379         /// </summary>
380         /// <param name="month">An integer representing a month in .NET
381         /// counting (starting with Tishri).
382         /// </param>
383         /// <param name="year">An integer representing the Hebrew year.
384         /// </param>
385         /// <returns>The Hebrew month in Calendrical Calculations counting,
386         /// staring with the Hebrew month Nisan.
387         /// </returns>
388         /// <remarks>
389         /// <para>
390         /// In .NET the month counting starts with the Hebrew month Tishri.
391         /// Calendrical Calculations starts with the month Nisan. So we must
392         /// map here.
393         /// </para>
394         /// </remarks>
395         internal int M_CCMonth(int month, int year) {
396                 if (month <= 6) {
397                         return 6+month;
398                 }
399                 else {
400                         int l = CCHebrewCalendar.last_month_of_year(year);
401                         if (l == 12) {
402                                 return month-6;
403                         }
404                         else {
405                                 return month <= 7 ? 6+month : month-7;  
406                         }
407                 }
408         }
409
410         /// <summary>
411         /// The method maps a Calendrical Calculations Hebrew month
412         /// to a .NET Hebrew month. 
413         /// </summary>
414         /// <param name="ccmonth">An integer representing a month in
415         /// Calendrical Calculations counting, starting with Nisan.
416         /// </param>
417         /// <param name="year">An integer representing the Hebrew year.
418         /// </param>
419         /// <returns>The Hebrew month in .NET counting,
420         /// staring with the Hebrew month Tishri.
421         /// </returns>
422         /// <remarks>
423         /// <para>
424         /// In .NET the month counting starts with the Hebrew month Tishri.
425         /// Calendrical Calculations starts with the month Tisan. So we must
426         /// map here.
427         /// </para>
428         /// </remarks>
429         internal int M_Month(int ccmonth, int year) {
430                 if (ccmonth >= 7) {
431                         return ccmonth - 6;
432                 } else {
433                         int l = CCHebrewCalendar.last_month_of_year(year);
434                         return ccmonth + (l == 12 ? 6 : 7);
435                 }
436         }
437
438         /// <summary>
439         /// Overridden. Gives the number of days in the specified month
440         /// of the given year and era.
441         /// </summary>
442         /// <param name="year">An integer that gives the year.
443         /// </param>
444         /// <param name="month">An integer that gives the month, starting
445         /// with 1.</param>
446         /// <param name="era">An integer that gives the era of the specified
447         /// year.</param>
448         /// <returns>An integer that gives the number of days of the
449         /// specified month.</returns>
450         /// <exception cref="T:System.ArgumentOutOfRangeException">
451         /// The exception is thrown, if <paramref name="month"/>,
452         /// <paramref name="year"/> ,or <paramref name="era"/> is outside
453         /// the allowed range.
454         /// </exception>
455         public override int GetDaysInMonth(int year, int month, int era) {
456                 M_CheckYME(year, month, ref era);
457                 int ccmonth = M_CCMonth(month, year); 
458                 return CCHebrewCalendar.last_day_of_month(ccmonth, year);
459         }
460
461         /// <summary>
462         /// Overridden. Gives the number of days of the specified
463         /// year of the given era. 
464         /// </summary>
465         /// <param name="year">An integer that specifies the year. 
466         /// </param>
467         /// <param name="era">An ineger that specifies the era.
468         /// </param>
469         /// <returns>An integer that gives the number of days of the
470         /// specified year.</returns>
471         /// <exception cref="T:System.ArgumentOutOfRangeExceiption">
472         /// The exception is thrown, if
473         /// <paramref name="year"/> or <paramref name="era"/> are outside the
474         /// allowed range.
475         /// </exception>
476         public override int GetDaysInYear(int year, int era) {
477                 M_CheckYE(year, ref era);
478                 int rd1 = CCHebrewCalendar.fixed_from_dmy(1, 7, year);
479                 int rd2 = CCHebrewCalendar.fixed_from_dmy(1, 7, year+1);
480                 return rd2 - rd1;
481         }
482                 
483
484         /// <summary>
485         /// Overridden. Gives the era of the specified date.
486         /// </summary>
487         /// <param name="time">The
488         /// <see cref="T:System.DateTime"/> that specifies a
489         /// date.
490         /// </param>
491         /// <returns>An integer representing the era of the calendar.
492         /// </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 years
496         /// between 5343 A.M. and 6000 A.M., inclusive.
497         /// </exception>
498         public override int GetEra(DateTime time) {
499                 M_CheckDateTime(time);
500                 return HebrewEra;
501         }
502
503         public override int GetLeapMonth (int year, int era)
504         {
505                 return IsLeapMonth (year, 7, era) ? 7 : 0;
506         }
507
508         /// <summary>
509         /// Overridden. Gives the number of the month of the specified
510         /// date.
511         /// </summary>
512         /// <param name="time">The
513         /// <see cref="T:System.DateTime"/> that specifies a
514         /// date.
515         /// </param>
516         /// <returns>An integer representing the month, 
517         /// starting with 1.</returns>
518         /// <exception cref="T:System.ArgumentOutOfRangeException">
519         /// The exception is thrown if the
520         /// <see cref="T:System.DateTime"/> parameter is not in the years
521         /// between 5343 A.M. and 6000 A.M., inclusive.
522         /// </exception>
523         public override int GetMonth(DateTime time) {
524                 M_CheckDateTime(time);
525                 int rd = CCFixed.FromDateTime(time);
526                 int ccmonth, year;
527                 CCHebrewCalendar.my_from_fixed(out ccmonth, out year, rd);
528                 return M_Month(ccmonth, year);
529         }
530
531         /// <summary>
532         /// Overridden. Gives the number of months in the specified year 
533         /// and era.
534         /// </summary>
535         /// <param name="year">An integer that specifies the year.
536         /// </param>
537         /// <param name="era">An integer that specifies the era.
538         /// </param>
539         /// <returns>An integer that gives the number of the months in the
540         /// specified year.</returns>
541         /// <exception cref="T:System.ArgumentOutOfRangeException">
542         /// The exception is thrown, if the year or the era are not valid.
543         /// </exception>
544         public override int GetMonthsInYear(int year, int era) {
545                 M_CheckYE(year, ref era);
546                 return CCHebrewCalendar.last_month_of_year(year);
547         }
548
549         /// <summary>
550         /// Overridden. Gives the number of the year of the specified
551         /// date.
552         /// </summary>
553         /// <param name="time">The
554         /// <see cref="T:System.DateTime"/> that specifies a
555         /// date.
556         /// </param>
557         /// <returns>An integer representing the year, 
558         /// starting with 1.</returns>
559         /// <exception cref="T:System.ArgumentOutOfRangeException">
560         /// The exception is thrown if the
561         /// <see cref="T:System.DateTime"/> parameter is not in the years
562         /// between 5343 A.M. and 6000 A.M., inclusive.
563         /// </exception>
564         public override int GetYear(DateTime time) {
565                 M_CheckDateTime(time);
566                 int rd = CCFixed.FromDateTime(time);
567                 return CCHebrewCalendar.year_from_fixed(rd);
568         }
569
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         /// <remarks>All days in Adar II are viewed as leap days and the
591         /// last day of Adar I.
592         /// </remarks>
593         public override bool IsLeapDay(int year, int month, int day, int era)
594         {
595                 M_CheckYMDE(year, month, day, ref era);
596                 return IsLeapYear(year) &&
597                         (month == 7 || (month == 6 && day == 30)); 
598         }
599
600         /// <summary>
601         /// Overridden. Tells whether the given month 
602         /// is a leap month.
603         /// </summary>
604         /// <param name="year">An integer that specifies the year in the
605         /// given era.
606         /// </param>
607         /// <param name="month">An integer that specifies the month.
608         /// </param>
609         /// <param name="era">An integer that specifies the era.
610         /// </param>
611         /// <returns>A boolean that tells whether the given month is a leap
612         /// month.
613         /// </returns>
614         /// <exception cref="T:System.ArgumentOutOfRangeException">
615         /// The exception is thrown, if the year, month, or era is not
616         /// valid.
617         /// </exception>
618         /// <remarks>
619         /// Adar II is viewed as leap month.
620         /// </remarks>
621         public override bool IsLeapMonth(int year, int month, int era) {
622                 M_CheckYME(year, month, ref era);
623                 return IsLeapYear(year) && month == 7; 
624         }
625
626         /// <summary>
627         /// Overridden. Tells whether the given year
628         /// is a leap year.
629         /// </summary>
630         /// <param name="year">An integer that specifies the year in the
631         /// given era.
632         /// </param>
633         /// <param name="era">An integer that specifies the era.
634         /// </param>
635         /// <returns>A boolean that tells whether the given year is a leap
636         /// year.
637         /// </returns>
638         /// <exception cref="T:System.ArgumentOutOfRangeException">
639         /// The exception is thrown, if the year or era is not
640         /// valid.
641         /// </exception>
642         public override bool IsLeapYear(int year, int era) {
643                 M_CheckYE(year, ref era);
644                 return CCHebrewCalendar.is_leap_year(year);
645         }
646
647         /// <summary>
648         /// Overridden. Creates the
649         /// <see cref="T:System.DateTime"/> from the parameters.
650         /// </summary>
651         /// <param name="year">An integer that gives the year in the
652         /// <paramref name="era"/>.
653         /// </param>
654         /// <param name="month">An integer that specifies the month.
655         /// </param>
656         /// <param name="day">An integer that specifies the day.
657         /// </param>
658         /// <param name="hour">An integer that specifies the hour.
659         /// </param>
660         /// <param name="minute">An integer that specifies the minute.
661         /// </param>
662         /// <param name="second">An integer that gives the second.
663         /// </param>
664         /// <param name="milliseconds">An integer that gives the
665         /// milliseconds.
666         /// </param>
667         /// <param name="era">An integer that specifies the era.
668         /// </param>
669         /// <returns>A
670         /// <see cref="T:system.DateTime"/> representig the date and time.
671         /// </returns>
672         /// <exception cref="T:System.ArgumentOutOfRangeException">
673         /// The exception is thrown, if at least one of the parameters
674         /// is out of range.
675         /// </exception>
676         public override DateTime ToDateTime(int year, int month, int day,
677                 int hour, int minute, int second, int millisecond,
678                 int era)
679         {
680                 M_CheckYMDE(year, month, day, ref era);
681                 M_CheckHMSM(hour, minute, second, millisecond);
682                 int ccm = M_CCMonth(month, year);
683                 int rd = CCHebrewCalendar.fixed_from_dmy(day, ccm, year);
684                 return CCFixed.ToDateTime(rd,
685                         hour, minute, second, millisecond);
686         }
687
688         public override int ToFourDigitYear (int year)
689         {
690                 M_ArgumentInRange ("year", year, 0, M_MaxYear - 1);
691                 
692                 int baseExtra = this.twoDigitYearMax % 100;
693                 int baseCentury = this.twoDigitYearMax - baseExtra;
694                 
695                 if (year >= 100)
696                         return year;
697                 if (year <= baseExtra)
698                         return baseCentury + year;
699                 else
700                         return baseCentury + year - 100;
701         }
702 #if !NET_2_1
703         public override CalendarAlgorithmType AlgorithmType {
704                 get {
705                         return CalendarAlgorithmType.LunisolarCalendar;
706                 }
707         }
708 #endif
709
710         static DateTime Min = new DateTime (1583, 1, 1, 0, 0, 0);
711         static DateTime Max = new DateTime (2239, 9, 29, 11, 59, 59);
712                 
713         public override DateTime MinSupportedDateTime {
714                 get {
715                         return Min;
716                 }
717         }
718
719         public override DateTime MaxSupportedDateTime {
720                 get {
721                         return Max;
722                 }
723         }
724 } // class HebrewCalendar
725         
726 } // namespace System.Globalization