This commit was manufactured by cvs2svn to create branch 'mono-1-0'.
[mono.git] / mcs / class / corlib / System.Globalization / HebrewCalendar.cs
1 // 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
34 /// <summary>
35 /// This is the Hebrew calendar.
36 /// </summary>
37 /// <remarks>
38 /// <para>The Hebrew calendar supports only years between 5343 A.M. and
39 /// 6000 A.M. This has been done to be compatible with .NET.
40 /// </para>
41 /// <para>The implementation uses the
42 /// <see cref="N:CalendricalCalculations"/> namespace.
43 /// </para>
44 /// </remarks>
45 [Serializable]
46 [MonoTODO ("Fix serialization compatibility with MS.NET")]
47 public class HebrewCalendar : Calendar {
48         /// <summary>
49         /// Constructor.
50         /// </summary>
51         public HebrewCalendar() {
52                 M_AbbrEraNames = new string[] {"A.M."};
53                 M_EraNames = new string[] {"Anno Mundi"};
54                 if (M_TwoDigitYearMax == 99)
55                         M_TwoDigitYearMax = 5790;
56         }
57
58         /// <summary>
59         /// The era number for the Anno Mundi (A.M.) era, called
60         /// plain HebrewEra.
61         /// </summary>
62         public static readonly int HebrewEra = 1;
63
64         /// <summary>
65         /// The
66         /// <see cref="T:System.DateTime"/> ticks for first day of year
67         /// 5343 A.M.
68         /// </summary>
69         internal const long M_MinTicks = 499147488000000000L;
70         /// <summary>
71         /// The number of
72         /// <see cref="T:System.DateTime"/> ticks for the last day of year
73         /// 6000 A.M.
74         /// </summary>
75         internal const long M_MaxTicks = 706783967999999999L;
76         /// <summary>
77         /// The minimum year in the A.M. era supported.
78         /// </summary>
79         internal const int M_MinYear = 5343;
80         /// <summary>
81         /// The maximum year supported in the A.M. era.
82         /// </summary>
83         internal override int M_MaxYear {
84                 get { return 6000; }
85         }
86
87         /// <value>Overridden. Gives the eras supported by the Gregorian
88         /// calendar as an array of integers.
89         /// </value>
90         public override int[] Eras {
91                 get {
92                         return new int[] { HebrewEra }; 
93                 }
94         }
95
96         int twoDigitYearMax = 5790;
97         
98         public override int TwoDigitYearMax 
99         {
100                 get {
101                         return twoDigitYearMax;
102                 }
103                 set {
104                         M_ArgumentInRange ("value", value, 100, 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 #if false
225         //
226         // The following routines are commented out as they do not appear on the .NET Framework 1.1
227         //
228         
229         /// <summary>
230         /// Overridden. Adds days to a given date.
231         /// </summary>
232         /// <param name="time">The
233         /// <see cref="T:System.DateTime"/> to which to add
234         /// days.
235         /// </param>
236         /// <param name="days">The number of days to add.</param>
237         /// <returns>A new <see cref="T:System.DateTime"/> value, that
238         /// results from adding <paramref name="days"/> to the specified
239         /// DateTime.</returns>
240         /// <exception cref="T:System.ArgumentOutOfRangeException">
241         /// The exception is thrown if the
242         /// <see cref="T:System.DateTime"/> return value is not in the years
243         /// between 5343 A.M. and 6000 A.M., inclusive.
244         /// </exception>
245         public override DateTime AddDays(DateTime time, int days) {
246                 DateTime t = base.AddDays(time, days);
247                 M_CheckDateTime(t);
248                 return t;
249         }
250
251         /// <summary>
252         /// Overridden. Adds hours to a given date.
253         /// </summary>
254         /// <param name="time">The
255         /// <see cref="T:System.DateTime"/> to which to add
256         /// hours.
257         /// </param>
258         /// <param name="hours">The number of hours to add.</param>
259         /// <returns>A new <see cref="T:System.DateTime"/> value, that
260         /// results from adding <paramref name="hours"/> to the specified
261         /// DateTime.</returns>
262         /// <exception cref="T:System.ArgumentOutOfRangeException">
263         /// The exception is thrown if the
264         /// <see cref="T:System.DateTime"/> return value is not in the years
265         /// between 5343 A.M. and 6000 A.M., inclusive.
266         /// </exception>
267         public override DateTime AddHours(DateTime time, int hours) {
268                 DateTime t = base.AddHours(time, hours);
269                 M_CheckDateTime(t);
270                 return t;
271         }
272
273         /// <summary>
274         /// Overridden. Adds milliseconds to a given date.
275         /// </summary>
276         /// <param name="time">The
277         /// <see cref="T:System.DateTime"/> to which to add
278         /// milliseconds.
279         /// </param>
280         /// <param name="milliseconds">The number of milliseconds given as
281         /// double to add. Keep in mind the 100 nanosecond resolution of 
282         /// <see cref="T:System.DateTime"/>.
283         /// </param>
284         /// <returns>A new <see cref="T:System.DateTime"/> value, that
285         /// results from adding <paramref name="milliseconds"/> to the specified
286         /// DateTime.</returns>
287         /// <exception cref="T:System.ArgumentOutOfRangeException">
288         /// The exception is thrown if the
289         /// <see cref="T:System.DateTime"/> return value is not in the years
290         /// between 5343 A.M. and 6000 A.M., inclusive.
291         /// </exception>
292         public override DateTime AddMilliseconds(DateTime time,
293                 double milliseconds)
294         {
295                 DateTime t = base.AddMilliseconds(time, milliseconds);
296                 M_CheckDateTime(t);
297                 return t;
298         }
299
300         /// <summary>
301         /// Overridden. Adds minutes to a given date.
302         /// </summary>
303         /// <param name="time">The
304         /// <see cref="T:System.DateTime"/> to which to add
305         /// minutes.
306         /// </param>
307         /// <param name="minutes">The number of minutes to add.</param>
308         /// <returns>A new <see cref="T:System.DateTime"/> value, that
309         /// results from adding <paramref name="minutes"/> to the specified
310         /// DateTime.</returns>
311         /// <exception cref="T:System.ArgumentOutOfRangeException">
312         /// The exception is thrown if the
313         /// <see cref="T:System.DateTime"/> return value is not in the years
314         /// between 5343 A.M. and 6000 A.M., inclusive.
315         /// </exception>
316         public override DateTime AddMinutes(DateTime time, int minutes) {
317                 DateTime t = base.AddMinutes(time, minutes);
318                 M_CheckDateTime(t);
319                 return t;
320         }
321
322         /// <summary>
323         /// Overridden. Adds seconds to a given date.
324         /// </summary>
325         /// <param name="time">The
326         /// <see cref="T:System.DateTime"/> to which to add
327         /// seconds.
328         /// </param>
329         /// <param name="seconds">The number of seconds to add.</param>
330         /// <returns>A new <see cref="T:System.DateTime"/> value, that
331         /// results from adding <paramref name="seconds"/> to the specified
332         /// DateTime.</returns>
333         /// <exception cref="T:System.ArgumentOutOfRangeException">
334         /// The exception is thrown if the
335         /// <see cref="T:System.DateTime"/> return value is not in the years
336         /// between 5343 A.M. and 6000 A.M., inclusive.
337         /// </exception>
338         public override DateTime AddSeconds(DateTime time, int seconds) {
339                 DateTime t = base.AddSeconds(time, seconds);
340                 M_CheckDateTime(t);
341                 return t;
342         }
343
344         /// <summary>
345         /// Overridden. Adds weeks to a given date.
346         /// </summary>
347         /// <param name="time">The
348         /// <see cref="T:System.DateTime"/> to which to add
349         /// weeks.
350         /// </param>
351         /// <param name="weeks">The number of weeks to add.</param>
352         /// <returns>A new <see cref="T:System.DateTime"/> value, that
353         /// results from adding <paramref name="weeks"/> to the specified
354         /// DateTime.</returns>
355         /// <exception cref="T:System.ArgumentOutOfRangeException">
356         /// The exception is thrown if the
357         /// <see cref="T:System.DateTime"/> return value is not in the years
358         /// between 5343 A.M. and 6000 A.M., inclusive.
359         /// </exception>
360         public override DateTime AddWeeks(DateTime time, int weeks) {
361                 DateTime t = base.AddWeeks(time, weeks);
362                 M_CheckDateTime(t);
363                 return t;
364         }
365
366         /// <summary>
367         /// Overridden. Gives the hour of the specified time.
368         /// </summary>
369         /// <param name="time">The
370         /// <see cref="T:System.DateTime"/> that specifies the
371         /// time.
372         /// </param>
373         /// <returns>An integer that gives the hour of the specified time,
374         /// starting with 0.</returns>
375         /// <exception cref="T:System.ArgumentOutOfRangeException">
376         /// The exception is thrown if the
377         /// <see cref="T:System.DateTime"/> parameter is not in the years
378         /// between 5343 A.M. and 6000 A.M., inclusive.
379         /// </exception>
380         public override int GetHour(DateTime time) {
381                 M_CheckDateTime(time);
382                 return base.GetHour(time);
383         }
384
385         /// <summary>
386         /// Overridden. Gives the milliseconds in the current second
387         /// of the specified time.
388         /// </summary>
389         /// <param name="time">The
390         /// <see cref="T:System.DateTime"/> that specifies the
391         /// time.
392         /// </param>
393         /// <returns>An integer that gives the milliseconds in the seconds
394         /// of the specified time, starting with 0.</returns>
395         /// <exception cref="T:System.ArgumentOutOfRangeException">
396         /// The exception is thrown if the
397         /// <see cref="T:System.DateTime"/> parameter is not in the years
398         /// between 5343 A.M. and 6000 A.M., inclusive.
399         /// </exception>
400         public override double GetMilliseconds(DateTime time) {
401                 M_CheckDateTime(time);
402                 return base.GetMilliseconds(time);
403         }
404
405         /// <summary>
406         /// Overridden. Gives the minute of the specified time.
407         /// </summary>
408         /// <param name="time">The
409         /// <see cref="T:System.DateTime"/> that specifies the
410         /// time.
411         /// </param>
412         /// <returns>An integer that gives the minute of the specified time,
413         /// starting with 0.</returns>
414         /// <exception cref="T:System.ArgumentOutOfRangeException">
415         /// The exception is thrown if the
416         /// <see cref="T:System.DateTime"/> parameter is not in the years
417         /// between 5343 A.M. and 6000 A.M., inclusive.
418         /// </exception>
419         public override int GetMinute(DateTime time) {
420                 M_CheckDateTime(time);
421                 return base.GetMinute(time);
422         }
423
424         /// <summary>
425         /// Overridden. Gives the second of the specified time.
426         /// </summary>
427         /// <param name="time">The
428         /// <see cref="T:System.DateTime"/> that specifies the
429         /// time.
430         /// </param>
431         /// <returns>An integer that gives the second of the specified time,
432         /// starting with 0.</returns>
433         /// <exception cref="T:System.ArgumentOutOfRangeException">
434         /// The exception is thrown if the
435         /// <see cref="T:System.DateTime"/> parameter is not in the years
436         /// between 5343 A.M. and 6000 A.M., inclusive.
437         /// </exception>
438         public override int GetSecond(DateTime time) {
439                 M_CheckDateTime(time);
440                 return base.GetMinute(time);
441         }
442 #endif
443         
444         /// <summary>
445         /// Overrideden. Adds months to a given date.
446         /// </summary>
447         /// <param name="time">The
448         /// <see cref="T:System.DateTime"/> to which to add
449         /// months.
450         /// </param>
451         /// <param name="months">The number of months to add.</param>
452         /// <returns>A new <see cref="T:System.DateTime"/> value, that
453         /// results from adding <paramref name="months"/> to the specified
454         /// DateTime.</returns>
455         /// <exception cref="T:System.ArgumentOutOfRangeException">
456         /// The exception is thrown if the
457         /// <see cref="T:System.DateTime"/> return value is not in the years
458         /// between 5343 A.M. and 6000 A.M., inclusive.
459         /// </exception>
460         public override DateTime AddMonths(DateTime time, int months) {
461                 int y, m, d;
462                 DateTime t;
463
464                 if (months == 0) {
465                         t = time;
466                 } else {
467                         int rd = CCFixed.FromDateTime(time);
468                         CCHebrewCalendar.dmy_from_fixed(
469                                 out d, out m, out y, rd);
470                         m = M_Month(m, y);
471                         if (months < 0) {
472                                 while (months < 0) {
473                                         if (m+months > 0) {
474                                                 m += months;
475                                                 months = 0;
476                                         } else {
477                                                 months += m;
478                                                 y -= 1;
479                                                 m = GetMonthsInYear(y);
480                                         }
481                                 }
482                         }
483                         else {
484                                 while (months > 0) {
485                                         int my = GetMonthsInYear(y);
486                                         if (m+months <= my) {
487                                                 m += months;
488                                                 months = 0;
489                                         } else {
490                                                 months -= my-m+1;
491                                                 m = 1;
492                                                 y += 1;
493                                         }
494                                 }
495                         }
496                         t = ToDateTime(y, m, d, 0, 0, 0, 0);
497                         t = t.Add(time.TimeOfDay);
498                 }
499                 M_CheckDateTime(t);
500                 return t;
501         }
502
503         /// <summary>
504         /// Overridden. Adds years to a given date.
505         /// </summary>
506         /// <param name="time">The
507         /// <see cref="T:System.DateTime"/> to which to add
508         /// years.
509         /// </param>
510         /// <param name="years">The number of years to add.</param>
511         /// <returns>A new <see cref="T:System.DateTime"/> value, that
512         /// results from adding <paramref name="years"/> to the specified
513         /// DateTime.</returns>
514         /// <exception cref="T:System.ArgumentOutOfRangeException">
515         /// The exception is thrown if the
516         /// <see cref="T:System.DateTime"/> return value is not in the years
517         /// between 5343 A.M. and 6000 A.M., inclusive.
518         /// </exception>
519         public override DateTime AddYears(DateTime time, int years) {
520                 int rd = CCFixed.FromDateTime(time);
521                 int day, month, year;
522                 CCHebrewCalendar.dmy_from_fixed(
523                         out day, out month, out year, rd);
524                 year += years;
525                 rd = CCHebrewCalendar.fixed_from_dmy(day, month, year);
526                 DateTime t = CCFixed.ToDateTime(rd);
527                 t = t.Add(time.TimeOfDay);
528                 M_CheckDateTime(t);
529                 return t;
530         }
531                 
532         /// <summary>
533         /// Overriden. Gets the day of the month from
534         /// <paramref name="time"/>.
535         /// </summary>
536         /// <param name="time">The
537         /// <see cref="T:System.DateTime"/> that specifies a
538         /// date.
539         /// </param>
540         /// <returns>An integer giving the day of months, starting with 1.
541         /// </returns>
542         /// <exception cref="T:System.ArgumentOutOfRangeException">
543         /// The exception is thrown if the
544         /// <see cref="T:System.DateTime"/> parameter is not in the years
545         /// between 5343 A.M. and 6000 A.M., inclusive.
546         /// </exception>
547         public override int GetDayOfMonth(DateTime time) {
548                 M_CheckDateTime(time);
549                 int rd = CCFixed.FromDateTime(time);
550                 return CCHebrewCalendar.day_from_fixed(rd);
551         }
552
553         /// <summary>
554         /// Overriden. Gets the day of the week from the specified date.
555         /// </summary>
556         /// <param name="time">The
557         /// <see cref="T:System.DateTime"/> that specifies a
558         /// date.
559         /// </param>
560         /// <returns>An integer giving the day of months, starting with 1.
561         /// </returns>
562         /// <exception cref="T:System.ArgumentOutOfRangeException">
563         /// The exception is thrown if the
564         /// <see cref="T:System.DateTime"/> parameter is not in the years
565         /// between 5343 A.M. and 6000 A.M., inclusive.
566         /// </exception>
567         public override DayOfWeek GetDayOfWeek(DateTime time) {
568                 M_CheckDateTime(time);
569                 int rd = CCFixed.FromDateTime(time);
570                 return (DayOfWeek)CCFixed.day_of_week(rd);
571         }
572
573         /// <summary>
574         /// Overridden. Gives the number of the day in the year.
575         /// </summary>
576         /// <param name="time">The
577         /// <see cref="T:System.DateTime"/> that specifies a
578         /// date.
579         /// </param>
580         /// <returns>An integer representing the day of the year,
581         /// starting with 1.</returns>
582         /// <exception cref="T:System.ArgumentOutOfRangeException">
583         /// The exception is thrown if the
584         /// <see cref="T:System.DateTime"/> parameter is not in the years
585         /// between 5343 A.M. and 6000 A.M., inclusive.
586         /// </exception>
587         public override int GetDayOfYear(DateTime time) {
588                 M_CheckDateTime(time);
589                 int rd = CCFixed.FromDateTime(time);
590                 int year = CCHebrewCalendar.year_from_fixed(rd);
591                 int rd1_7 = CCHebrewCalendar.fixed_from_dmy(1, 7, year);
592                 return rd - rd1_7 + 1;
593         }
594
595         /// <summary>
596         /// The method maps a .NET Hebrew month to a Calencdrical
597         /// Calculations Hebrew month. 
598         /// </summary>
599         /// <param name="month">An integer representing a month in .NET
600         /// counting (starting with Tishri).
601         /// </param>
602         /// <param name="year">An integer representing the Hebrew year.
603         /// </param>
604         /// <returns>The Hebrew month in Calendrical Calculations counting,
605         /// staring with the Hebrew month Nisan.
606         /// </returns>
607         /// <remarks>
608         /// <para>
609         /// In .NET the month counting starts with the Hebrew month Tishri.
610         /// Calendrical Calculations starts with the month Tisan. So we must
611         /// map here.
612         /// </para>
613         /// </remarks>
614         internal int M_CCMonth(int month, int year) {
615                 if (month <= 6) {
616                         return 6+month;
617                 }
618                 else {
619                         int l = CCHebrewCalendar.last_month_of_year(year);
620                         if (l == 12) {
621                                 return month-6;
622                         }
623                         else {
624                                 return month <= 7 ? 6+month : month-7;  
625                         }
626                 }
627         }
628
629         /// <summary>
630         /// The method maps a Calendrical Calculations Hebrew month
631         /// to a .NET Hebrew month. 
632         /// </summary>
633         /// <param name="ccmonth">An integer representing a month in
634         /// Calendrical Calculations counting, starting with Nisan.
635         /// </param>
636         /// <param name="year">An integer representing the Hebrew year.
637         /// </param>
638         /// <returns>The Hebrew month in .NET counting,
639         /// staring with the Hebrew month Tishri.
640         /// </returns>
641         /// <remarks>
642         /// <para>
643         /// In .NET the month counting starts with the Hebrew month Tishri.
644         /// Calendrical Calculations starts with the month Tisan. So we must
645         /// map here.
646         /// </para>
647         /// </remarks>
648         internal int M_Month(int ccmonth, int year) {
649                 if (ccmonth >= 7) {
650                         return ccmonth - 6;
651                 } else {
652                         int l = CCHebrewCalendar.last_month_of_year(year);
653                         return ccmonth + (l == 12 ? 6 : 7);
654                 }
655         }
656
657         /// <summary>
658         /// Overridden. Gives the number of days in the specified month
659         /// of the given year and era.
660         /// </summary>
661         /// <param name="year">An integer that gives the year.
662         /// </param>
663         /// <param name="month">An integer that gives the month, starting
664         /// with 1.</param>
665         /// <param name="era">An integer that gives the era of the specified
666         /// year.</param>
667         /// <returns>An integer that gives the number of days of the
668         /// specified month.</returns>
669         /// <exception cref="T:System.ArgumentOutOfRangeException">
670         /// The exception is thrown, if <paramref name="month"/>,
671         /// <paramref name="year"/> ,or <paramref name="era"/> is outside
672         /// the allowed range.
673         /// </exception>
674         public override int GetDaysInMonth(int year, int month, int era) {
675                 M_CheckYME(year, month, ref era);
676                 int ccmonth = M_CCMonth(month, year); 
677                 int rd1 = CCHebrewCalendar.fixed_from_dmy(1, ccmonth, year);
678                 int rd2 = CCHebrewCalendar.fixed_from_dmy(1, ccmonth+1, year);
679                 return rd2 - rd1;
680         }
681
682         /// <summary>
683         /// Overridden. Gives the number of days of the specified
684         /// year of the given era. 
685         /// </summary>
686         /// <param name="year">An integer that specifies the year. 
687         /// </param>
688         /// <param name="era">An ineger that specifies the era.
689         /// </param>
690         /// <returns>An integer that gives the number of days of the
691         /// specified year.</returns>
692         /// <exception cref="T:System.ArgumentOutOfRangeExceiption">
693         /// The exception is thrown, if
694         /// <paramref name="year"/> or <paramref name="era"/> are outside the
695         /// allowed range.
696         /// </exception>
697         public override int GetDaysInYear(int year, int era) {
698                 M_CheckYE(year, ref era);
699                 int rd1 = CCHebrewCalendar.fixed_from_dmy(1, 7, year);
700                 int rd2 = CCHebrewCalendar.fixed_from_dmy(1, 7, year+1);
701                 return rd2 - rd1;
702         }
703                 
704
705         /// <summary>
706         /// Overridden. Gives the era of the specified date.
707         /// </summary>
708         /// <param name="time">The
709         /// <see cref="T:System.DateTime"/> that specifies a
710         /// date.
711         /// </param>
712         /// <returns>An integer representing the era of the calendar.
713         /// </returns>
714         /// <exception cref="T:System.ArgumentOutOfRangeException">
715         /// The exception is thrown if the
716         /// <see cref="T:System.DateTime"/> parameter is not in the years
717         /// between 5343 A.M. and 6000 A.M., inclusive.
718         /// </exception>
719         public override int GetEra(DateTime time) {
720                 M_CheckDateTime(time);
721                 return HebrewEra;
722         }
723
724         /// <summary>
725         /// Overridden. Gives the number of the month of the specified
726         /// date.
727         /// </summary>
728         /// <param name="time">The
729         /// <see cref="T:System.DateTime"/> that specifies a
730         /// date.
731         /// </param>
732         /// <returns>An integer representing the month, 
733         /// starting with 1.</returns>
734         /// <exception cref="T:System.ArgumentOutOfRangeException">
735         /// The exception is thrown if the
736         /// <see cref="T:System.DateTime"/> parameter is not in the years
737         /// between 5343 A.M. and 6000 A.M., inclusive.
738         /// </exception>
739         public override int GetMonth(DateTime time) {
740                 M_CheckDateTime(time);
741                 int rd = CCFixed.FromDateTime(time);
742                 int ccmonth, year;
743                 CCHebrewCalendar.my_from_fixed(out ccmonth, out year, rd);
744                 return M_Month(ccmonth, year);
745         }
746
747         /// <summary>
748         /// Overridden. Gives the number of months in the specified year 
749         /// and era.
750         /// </summary>
751         /// <param name="year">An integer that specifies the year.
752         /// </param>
753         /// <param name="era">An integer that specifies the era.
754         /// </param>
755         /// <returns>An integer that gives the number of the months in the
756         /// specified year.</returns>
757         /// <exception cref="T:System.ArgumentOutOfRangeException">
758         /// The exception is thrown, if the year or the era are not valid.
759         /// </exception>
760         public override int GetMonthsInYear(int year, int era) {
761                 M_CheckYE(year, ref era);
762                 return CCHebrewCalendar.last_month_of_year(year);
763         }
764
765         /// <summary>
766         /// Overridden. Gives the number of the year of the specified
767         /// date.
768         /// </summary>
769         /// <param name="time">The
770         /// <see cref="T:System.DateTime"/> that specifies a
771         /// date.
772         /// </param>
773         /// <returns>An integer representing the year, 
774         /// starting with 1.</returns>
775         /// <exception cref="T:System.ArgumentOutOfRangeException">
776         /// The exception is thrown if the
777         /// <see cref="T:System.DateTime"/> parameter is not in the years
778         /// between 5343 A.M. and 6000 A.M., inclusive.
779         /// </exception>
780         public override int GetYear(DateTime time) {
781                 M_CheckDateTime(time);
782                 int rd = CCFixed.FromDateTime(time);
783                 return CCHebrewCalendar.year_from_fixed(rd);
784         }
785
786         /// <summary>
787         /// Overridden. Tells whether the given day 
788         /// is a leap day.
789         /// </summary>
790         /// <param name="year">An integer that specifies the year in the
791         /// given era.
792         /// </param>
793         /// <param name="month">An integer that specifies the month.
794         /// </param>
795         /// <param name="day">An integer that specifies the day.
796         /// </param>
797         /// <param name="era">An integer that specifies the era.
798         /// </param>
799         /// <returns>A boolean that tells whether the given day is a leap
800         /// day.
801         /// </returns>
802         /// <exception cref="T:System.ArgumentOutOfRangeException">
803         /// The exception is thrown, if the year, month, day, or era is not
804         /// valid.
805         /// </exception>
806         /// <remarks>All days in Adar II are viewed as leap days and the
807         /// last day of Adar I.
808         /// </remarks>
809         public override bool IsLeapDay(int year, int month, int day, int era)
810         {
811                 M_CheckYMDE(year, month, day, ref era);
812                 return IsLeapYear(year) &&
813                         (month == 7 || (month == 6 && day == 30)); 
814         }
815
816         /// <summary>
817         /// Overridden. Tells whether the given month 
818         /// is a leap month.
819         /// </summary>
820         /// <param name="year">An integer that specifies the year in the
821         /// given era.
822         /// </param>
823         /// <param name="month">An integer that specifies the month.
824         /// </param>
825         /// <param name="era">An integer that specifies the era.
826         /// </param>
827         /// <returns>A boolean that tells whether the given month is a leap
828         /// month.
829         /// </returns>
830         /// <exception cref="T:System.ArgumentOutOfRangeException">
831         /// The exception is thrown, if the year, month, or era is not
832         /// valid.
833         /// </exception>
834         /// <remarks>
835         /// Adar II is viewed as leap month.
836         /// </remarks>
837         public override bool IsLeapMonth(int year, int month, int era) {
838                 M_CheckYME(year, month, ref era);
839                 return IsLeapYear(year) && month == 7; 
840         }
841
842         /// <summary>
843         /// Overridden. Tells whether the given year
844         /// is a leap year.
845         /// </summary>
846         /// <param name="year">An integer that specifies the year in the
847         /// given era.
848         /// </param>
849         /// <param name="era">An integer that specifies the era.
850         /// </param>
851         /// <returns>A boolean that tells whether the given year is a leap
852         /// year.
853         /// </returns>
854         /// <exception cref="T:System.ArgumentOutOfRangeException">
855         /// The exception is thrown, if the year or era is not
856         /// valid.
857         /// </exception>
858         public override bool IsLeapYear(int year, int era) {
859                 M_CheckYE(year, ref era);
860                 return CCHebrewCalendar.is_leap_year(year);
861         }
862
863         /// <summary>
864         /// Overridden. Creates the
865         /// <see cref="T:System.DateTime"/> from the parameters.
866         /// </summary>
867         /// <param name="year">An integer that gives the year in the
868         /// <paramref name="era"/>.
869         /// </param>
870         /// <param name="month">An integer that specifies the month.
871         /// </param>
872         /// <param name="day">An integer that specifies the day.
873         /// </param>
874         /// <param name="hour">An integer that specifies the hour.
875         /// </param>
876         /// <param name="minute">An integer that specifies the minute.
877         /// </param>
878         /// <param name="second">An integer that gives the second.
879         /// </param>
880         /// <param name="milliseconds">An integer that gives the
881         /// milliseconds.
882         /// </param>
883         /// <param name="era">An integer that specifies the era.
884         /// </param>
885         /// <returns>A
886         /// <see cref="T:system.DateTime"/> representig the date and time.
887         /// </returns>
888         /// <exception cref="T:System.ArgumentOutOfRangeException">
889         /// The exception is thrown, if at least one of the parameters
890         /// is out of range.
891         /// </exception>
892         public override DateTime ToDateTime(int year, int month, int day,
893                 int hour, int minute, int second, int milliseconds,
894                 int era)
895         {
896                 M_CheckYMDE(year, month, day, ref era);
897                 M_CheckHMSM(hour, minute, second, milliseconds);
898                 int ccm = M_CCMonth(month, year);
899                 int rd = CCHebrewCalendar.fixed_from_dmy(day, ccm, year);
900                 return CCFixed.ToDateTime(rd,
901                         hour, minute, second, milliseconds);
902         }
903
904         [MonoTODO]
905         public override int ToFourDigitYear (int year)
906         {
907                 throw new NotImplementedException ();
908         }
909
910 } // class HebrewCalendar
911         
912 } // namespace System.Globalization