Merge pull request #1388 from schani/fix-23401
[mono.git] / mcs / class / corlib / System.Globalization / CalendricalCalculations.cs
1 // CalendricalCalculations.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.Collections;
32
33 /// <summary>A class that provides mathematical functions.</summary>
34 /// <remarks>
35 /// <para>
36 /// We are breaking the .Net
37 /// naming conventions to be compatible to the "Calendrical Calculations"
38 /// bool. 
39 /// </para>
40 /// </remarks>
41 static class CCMath {
42         /// <summary>
43         /// A static method which rounds a double value.
44         /// </summary>
45         /// <param name="x">The double value to round.</param>
46         /// <returns>The rounded double.</returns>
47         public static double round(double x) {
48                 return System.Math.Floor(x+0.5);
49         }
50
51         /// <summary>
52         /// A static method that computes the remainder of the division
53         /// of two doubles.
54         /// </summary>
55         /// <param name="x">The double value which is divided.</param>
56         /// <param name="y">The divisor.</param>
57         /// <returns>The remainder as double value.</returns>
58         public static double mod(double x, double y) {
59                 return x - y * System.Math.Floor(x/y);
60         }
61
62         /// <summary>
63         /// The static method divides two integers.
64         /// </summary>
65         /// <param name="x">The integer x value.</param>
66         /// <param name="y">The integer y value.</param>
67         /// <returns>The qotient of x and y defined by floor(x/y).
68         /// </returns>
69         /// <remarks>
70         /// Please notify that the function is not compatible to the standard
71         /// integer divide operation /.
72         /// </remarks>
73         public static int div(int x, int y) {
74                 return (int)System.Math.Floor((double)x/(double)y);
75         }
76
77         /// <summary>
78         /// The static method computes the remainder of two integers.
79         /// </summary>
80         /// <param name="x">The integer value which will be divided.</param>
81         /// <param name="y">The divisor integer value.</param>
82         /// <returns> The remainder as integer value.</returns>
83         /// <remarks>
84         /// Please notify that the method is not compatible to the C#
85         /// remainder operation %.
86         /// </remarks>
87         public static int mod(int x, int y) {
88                 return x - y * div(x, y);
89         }
90
91         /// <summary>
92         /// A static method that combines integer division and remainder
93         /// computation.
94         /// </summary>
95         /// <param name="remainder">Remainder integer output value.
96         /// </param>
97         /// <param name="x">Integer to be divided.</param>
98         /// <param name="y">Divisor integer value.</param>
99         /// <returns>The quotient as integer.</returns>
100         /// <seealso cref="M:div"/>
101         /// <seealso cref="M:mod"/>
102         public static int div_mod(out int remainder, int x, int y) {
103                 int d = div(x, y);
104                 remainder = x - y * d;
105                 return d;
106         }
107
108         /// <summary>
109         /// A static method returning the sign of the argument.
110         /// </summary>
111         /// <param name="x">The double argument.</param>
112         /// <returns>An integer value: -1 for a negative argument;
113         /// 0 for a zero argument, and 1 for a positive argument.
114         /// </returns>
115         public static int signum(double x) {
116                 if (x < 0.0)
117                         return -1;
118                 if (x == 0.0)
119                         return 0;
120                 return 1;
121         }
122
123         /// <summary>
124         /// A static method returning the sign of the integer
125         /// argument.
126         /// </summary>
127         /// <param name="x">The integer argument.</param>
128         /// <returns>An integer value: -1 for a negative argument;
129         /// 0 for a zero argument, and 1 for a positive argument.
130         /// </returns>
131         public static int signum(int x) {
132                 if (x < 0)
133                         return -1;
134                 if (x == 0)
135                         return 0;
136                 return 1;
137         }
138
139         /// <summary>
140         /// An adjusted remainder function as defined in "Calendrical
141         /// Calculations".
142         /// </summary>
143         /// <param name="x">The double x argument.</param>
144         /// <param name="y">The double y argument, the divisor.</param>
145         /// <returns>A double value representing remainder; but instead 0.0
146         /// the divisor y is returned.
147         /// </returns>
148         public static double amod(double x, double y) {
149                 double d = mod(x, y);
150                 return (d == 0.0) ? y : d;
151         }
152
153         /// <summary>
154         /// The adjusted remainder functions for integers as defined in
155         /// "Calendrical Calculations".
156         /// </summary>
157         /// <param name="x">The integer argument to be divided.</param>
158         /// <param name="y">The integer divisor argument.</param>
159         /// <returns>The remainder as an integer; however instead 0 
160         /// is the divisor y returned.
161         /// </returns>
162         public static int amod(int x, int y) {
163                 int i = mod(x, y);
164                 return (i == 0) ? y : i;
165         }
166 }
167
168 /// <summary>The class implements methods to handle the fixed date value from
169 /// the "Calendrical Calculations" books.
170 /// </summary>
171 /// <remarks>
172 /// <para>
173 /// For implementing the Calendar classes I used the algorithms from the
174 /// book "Calendrical Calculations" by Nachum Dershowitz and Edward M.
175 /// Rheingold, second reprint 1998. Trying to prevent the introduction of new
176 /// bugs, I implemented their algorithms in the
177 /// <see cref="N:CalendricalCalculations"/>
178 /// namespace and wrapped it in the calendar classes.
179 /// </para>
180 /// <para>
181 /// The fixed day number is also known as R.D. - rata die.
182 /// Midnight at the onset of Monday,
183 /// January 1, year 1 (Gregorian) is R.D. 1.
184 /// </para>
185 /// <para>Here are all my references:</para>
186 /// <list type="table">
187 /// <item><description>
188 /// [1] Nachum Dershowitz and Edward M. Rheingold: "Calendrical Calculations";
189 /// Cambridge University Press; second reprint 1998.
190 /// </description></item>
191 /// <item><description>
192 /// [2] P. Kenneth Seidelmann (ed.): "Explanatory Supplement to the Astronomical
193 /// Almanac"; University Science Books, Sausalito; 1992 
194 /// </description></item>
195 /// <item><description>
196 /// [3] F. Richard Stephenson: "Historical Eclipses and Earth Rotation";
197 /// Cambridge University Press; 1997
198 /// </description></item>
199 /// </list>
200 /// </remarks>
201 static class CCFixed {
202         /// <summary>The method computes the
203         /// <see cref="T:System.DateTime"/>
204         /// from a fixed day number.
205         /// </summary>
206         /// <param name="date">A integer representing the fixed day number.
207         /// </param>
208         /// <returns>The <see cref="T:System.DateTime"/> representing
209         /// the date.
210         /// </returns>
211         public static System.DateTime ToDateTime(int date) {
212                 long ticks = (date - 1) * System.TimeSpan.TicksPerDay;
213                 return new System.DateTime(ticks);
214         }
215
216         /// <summary>The method computes the
217         /// <see cref="T:System.DateTime"/>
218         /// from a fixed day number and time arguments.
219         /// </summary>
220         /// <param name="date">An integer representing the fixed day number.
221         /// </param>
222         /// <param name="hour">An integer argument specifying the hour.
223         /// </param>
224         /// <param name="minute">An integer argument specifying the minute.
225         /// </param>
226         /// <param name="second">An integer argument giving the second.
227         /// </param>
228         /// <param name="milliseconds">An double argument specifying
229         /// the milliseconds. Notice that
230         /// <see cref="T:System.DateTime"/> has 100 nanosecond resolution.
231         /// </param>
232         /// <returns>The <see cref="T:System.DateTime"/> representing
233         /// the date.
234         /// </returns>
235         public static System.DateTime ToDateTime(int date,
236                 int hour, int minute, int second, double milliseconds)
237         {
238                 System.DateTime time = ToDateTime(date);
239                 time = time.AddHours(hour);
240                 time = time.AddMinutes(minute);
241                 time = time.AddSeconds(second);
242                 return time.AddMilliseconds(milliseconds);
243         }
244
245         /// <summary>
246         /// A static method computing the fixed day number from a 
247         /// <see cref="T:System.DateTime"/> value.
248         /// </summary>
249         /// <param name="time">A
250         /// <see cref="T:System.DateTime"/> value representing the date.
251         /// </param>
252         /// <returns>The fixed day number as integer representing the date.
253         /// </returns>
254         public static int FromDateTime(System.DateTime time) {
255                 return 1 + (int)(time.Ticks / System.TimeSpan.TicksPerDay);
256         }
257
258         /// <summary>
259         /// The static method computes the <see cref="T:DayOfWeek"/>.
260         /// </summary>
261         /// <param name="date">An integer representing the fixed day number.
262         /// </param>
263         /// <returns>The day of week.</returns>
264         public static DayOfWeek day_of_week(int date) {
265                 return (DayOfWeek)CCMath.mod(date, 7);
266         }
267
268         /// <summary>
269         /// The static method computes the date of a day of week on or before
270         /// a particular date.
271         /// </summary>
272         /// <param name="date">An integer representing the date as
273         /// fixed day number.
274         /// </param>
275         /// <param name="k">An integer representing the day of the week,
276         /// starting with 0 for sunday.
277         /// </param>
278         /// <returns>The fixed day number of the day of week specified by k
279         /// on or before the given date.
280         /// </returns>
281         public static int kday_on_or_before(int date, int k) {
282                 return date - (int)day_of_week(date-k);
283         }
284
285         /// <summary>
286         /// The static method computes the date of a day of week on or after
287         /// a particular date.
288         /// </summary>
289         /// <param name="date">An integer representing the date as
290         /// fixed day number.
291         /// </param>
292         /// <param name="k">An integer representing the day of the week,
293         /// starting with 0 for sunday.
294         /// </param>
295         /// <returns>The fixed day number of the day of week specified by k
296         /// on or after the given date.
297         /// </returns>
298         public static int kday_on_or_after(int date, int k) {
299                 return kday_on_or_before(date+6, k);
300         }
301
302         /// <summary>
303         /// The static method computes the date of a day of week that is
304         /// nearest to a particular date.
305         /// </summary>
306         /// <param name="date">An integer representing the date as
307         /// fixed day number.
308         /// </param>
309         /// <param name="k">An integer representing the day of the week,
310         /// starting with 0 for sunday.
311         /// </param>
312         /// <returns>The fixed day number of the day of week neares to the
313         /// given date.
314         /// </returns>
315         public static int kd_nearest(int date, int k) {
316                 return kday_on_or_before(date+3, k);
317         }
318
319         /// <summary>
320         /// The static method computes the date of a day of week after
321         /// a particular date.
322         /// </summary>
323         /// <param name="date">An integer representing the date as
324         /// fixed day number.
325         /// </param>
326         /// <param name="k">An integer representing the day of the week,
327         /// starting with 0 for sunday.
328         /// </param>
329         /// <returns>The fixed day number of the day of week specified by k
330         /// after the given date.
331         /// </returns>
332         public static int kday_after(int date, int k) {
333                 return kday_on_or_before(date+7, k);
334         }
335
336         /// <summary>
337         /// The static method computes the date of a day of week before
338         /// a particular date.
339         /// </summary>
340         /// <param name="date">An integer representing the date as
341         /// fixed day number.
342         /// </param>
343         /// <param name="k">An integer representing the day of the week,
344         /// starting with 0 for sunday.
345         /// </param>
346         /// <returns>The fixed day number of the day of week specified by k
347         /// before the given date.
348         /// </returns>
349         public static int kday_before(int date, int k) {
350                 return kday_on_or_before(date-1, k);
351         }
352 } // class CCFixed
353
354 /// <summary>
355 /// A class encapsulating the functions of the Gregorian calendar as static
356 /// methods.
357 /// </summary>
358 /// <remarks>
359 /// <para>
360 /// This class is not compatible to
361 /// <see cref="T:System.Globalization.GregorianCalendar"/>.
362 /// </para>
363 /// <para>
364 /// The fixed day number is also known as R.D. - rata die.
365 /// Midnight at the onset of Monday,
366 /// January 1, year 1 (Gregorian) is R.D. 1.
367 /// </para>
368 /// <seealso cref="T:CCFixed"/>
369 /// </remarks>
370 static class CCGregorianCalendar {
371         /// <summary>An integer defining the epoch of the Gregorian calendar
372         /// as fixed day number.</summary>
373         /// <remarks>The epoch is January 3, 1 C.E. (Julian).</remarks>
374         const int epoch = 1;
375
376         /// <summary>The enumeration defines the months of the Gregorian
377         /// calendar.
378         /// </summary>
379         public enum Month {
380                 /// <summary>
381                 /// January.
382                 /// </summary>
383                 january = 1,
384                 /// <summary>
385                 /// February.
386                 /// </summary>
387                 february,
388                 /// <summary>
389                 /// March.
390                 /// </summary>
391                 march,
392                 /// <summary>
393                 /// April.
394                 /// </summary>
395                 april,
396                 /// <summary>
397                 /// May.
398                 /// </summary>
399                 may,
400                 /// <summary>
401                 /// June.
402                 /// </summary>
403                 june,
404                 /// <summary>
405                 /// July.
406                 /// </summary>
407                 july,
408                 /// <summary>
409                 /// August.
410                 /// </summary>
411                 august,
412                 /// <summary>
413                 /// September.
414                 /// </summary>
415                 september,
416                 /// <summary>
417                 /// October.
418                 /// </summary>
419                 october,
420                 /// <summary>
421                 /// November.
422                 /// </summary>
423                 november,
424                 /// <summary>
425                 /// December.
426                 /// </summary>
427                 december
428         };
429
430
431         /// <summary>
432         /// The method tells whether the year is a leap year.
433         /// </summary>
434         /// <param name="year">An integer representing the Gregorian year.
435         /// </param>
436         /// <returns>A boolean which is true if <paramref name="year"/> is
437         /// a leap year.
438         /// </returns>
439         public static bool is_leap_year(int year) {
440                 if (CCMath.mod(year, 4) != 0)
441                         return false;
442                 switch (CCMath.mod(year, 400)) {
443                         case 100: 
444                                 return false;
445                         case 200:
446                                 return false;
447                         case 300:
448                                 return false;
449                 }
450                 return true;
451         }
452
453         /// <summary>
454         /// The method returns the fixed day number of the given Gregorian
455         /// date.
456         /// </summary>
457         /// <param name="day">An integer representing the day of the month,
458         /// counting from 1.
459         /// </param>
460         /// <param name="month">An integer representing the month in the
461         /// Gregorian year.
462         /// </param>
463         /// <param name="year">An integer representing the Gregorian year.
464         /// Non-positive values are allowed also.
465         /// </param>
466         /// <returns>An integer value representing the fixed day number.
467         /// </returns>
468         public static int fixed_from_dmy(int day, int month, int year) {
469                 if (month > 12) {
470                         year += CCMath.div_mod (out month, month - 1, 12);
471                         month++;
472                 }
473
474                 int k = epoch - 1;
475                 k += 365 * (year-1);
476                 k += CCMath.div(year-1, 4);
477                 k -= CCMath.div(year-1, 100);
478                 k += CCMath.div(year-1, 400);
479                 k += CCMath.div(367*month-362, 12);
480                 if (month > 2) {
481                         k += is_leap_year(year) ? -1 : -2;
482                 }
483
484                 k += day;
485
486                 return k;
487         }
488
489         /// <summary>
490         /// The method computes the Gregorian year from a fixed day number.
491         /// </summary>
492         /// <param name="date">The fixed day number.
493         /// </param>
494         /// <returns>An integer value giving the Gregorian year of the date.
495         /// </returns>
496         public static int year_from_fixed(int date) {
497                 int d           = date - epoch;
498                 int n_400       = CCMath.div_mod(out d, d, 146097);
499                 int n_100       = CCMath.div_mod(out d, d, 36524);
500                 int n_4         = CCMath.div_mod(out d, d, 1461);
501                 int n_1         = CCMath.div(d, 365);
502
503                 int year = 400*n_400 + 100*n_100 + 4*n_4 + n_1;
504                 return (n_100 == 4 || n_1 == 4) ? year : year + 1;
505         }
506
507         /// <summary>
508         /// The method computes the Gregorian year and month from a fixed day
509         /// number.
510         /// </summary>
511         /// <param name="month">The output value giving the Gregorian month.
512         /// </param>
513         /// <param name="year">The output value giving the Gregorian year.
514         /// </param>
515         /// <param name="date">An integer value specifying the fixed day
516         /// number.</param>
517         public static void my_from_fixed(out int month, out int year,
518                 int date)
519         {
520                 year = year_from_fixed(date);
521
522                 int prior_days = date - fixed_from_dmy(1, (int)Month.january,
523                         year);
524                 
525                 int correction;
526                 if (date < fixed_from_dmy(1, (int)Month.march, year)) {
527                         correction = 0;
528                 } else if (is_leap_year(year)) {
529                         correction = 1;
530                 } else {
531                         correction = 2;
532                 }
533
534                 month = CCMath.div(12 * (prior_days + correction) + 373, 367);
535
536         }
537
538         /// <summary>
539         /// The method computes the Gregorian year, month, and day from a
540         /// fixed day number.
541         /// </summary>
542         /// <param name="day">The output value returning the day of the
543         /// month.
544         /// </param>
545         /// <param name="month">The output value giving the Gregorian month.
546         /// </param>
547         /// <param name="year">The output value giving the Gregorian year.
548         /// </param>
549         /// <param name="date">An integer value specifying the fixed day
550         /// number.</param>
551         public static void dmy_from_fixed(out int day, out int month,
552                 out int year,
553                 int date)
554         {
555                 my_from_fixed(out month, out year, date);
556                 day = date - fixed_from_dmy(1, month, year) + 1;
557         }
558
559         /// <summary>A method computing the Gregorian month from a fixed
560         /// day number.
561         /// </summary>
562         /// <param name="date">An integer specifying the fixed day number.
563         /// </param>
564         /// <returns>An integer value representing the Gregorian month.
565         /// </returns>
566         public static int month_from_fixed(int date) {
567                 int month, year;
568
569                 my_from_fixed(out month, out year, date);
570                 return month;
571         }
572
573         /// <summary>
574         /// A method computing the day of the month from a fixed day number.
575         /// </summary>
576         /// <param name="date">An integer specifying the fixed day number.
577         /// </param>
578         /// <returns>An integer value representing the day of the month.
579         /// </returns>
580         public static int day_from_fixed(int date) {
581                 int day, month, year;
582
583                 dmy_from_fixed(out day, out month, out year, date);
584                 return day;
585         }
586
587         /// <summary>
588         /// The method computes the difference between two Gregorian dates.
589         /// </summary>
590         /// <param name="dayA">The integer parameter gives the day of month
591         /// of the first date.
592         /// </param>
593         /// <param name="monthA">The integer parameter gives the Gregorian
594         /// month of the first date.
595         /// </param>
596         /// <param name="yearA">The integer parameter gives the Gregorian
597         /// year of the first date.
598         /// </param>
599         /// <param name="dayB">The integer parameter gives the day of month
600         /// of the second date.
601         /// </param>
602         /// <param name="monthB">The integer parameter gives the Gregorian
603         /// month of the second date.
604         /// </param>
605         /// <param name="yearB">The integer parameter gives the Gregorian
606         /// year of the second date.
607         /// </param>
608         /// <returns>An integer giving the difference of days from the first
609         /// the second date.
610         /// </returns>
611         public static int date_difference(int dayA, int monthA, int yearA,
612                 int dayB, int monthB, int yearB)
613         {
614                 return  fixed_from_dmy(dayB, monthB, yearB) -
615                         fixed_from_dmy(dayA, monthA, yearA);
616         }
617
618         /// <summary>
619         /// The method computes the number of the day in the year from
620         /// a Gregorian date.
621         /// </summary>
622         /// <param name="day">An integer representing the day of the month,
623         /// counting from 1.
624         /// </param>
625         /// <param name="month">An integer representing the month in the
626         /// Gregorian year.
627         /// </param>
628         /// <param name="year">An integer representing the Gregorian year.
629         /// Non-positive values are allowed also.
630         /// </param>
631         /// <returns>An integer value giving the number of the day in the
632         /// Gregorian year, counting from 1.
633         /// </returns>
634         public static int day_number(int day, int month, int year) {
635                 return date_difference(31, (int)Month.december, year-1,
636                         day, month, year);
637         }
638
639         /// <summary>
640         /// The method computes the days remaining in the given Gregorian
641         /// year from a Gregorian date.
642         /// </summary>
643         /// <param name="day">An integer representing the day of the month,
644         /// counting from 1.
645         /// </param>
646         /// <param name="month">An integer representing the month in the
647         /// Gregorian year.
648         /// </param>
649         /// <param name="year">An integer representing the Gregorian year.
650         /// Non-positive values are allowed also.
651         /// </param>
652         /// <returns>An integer value giving the number of days remaining in
653         /// the Gregorian year.
654         /// </returns>
655         public static int days_remaining(int day, int month, int year) {
656                 return date_difference(day, month, year,
657                         31, (int)Month.december, year);
658         }
659
660         // Helper functions for the Gregorian calendars.
661
662         /// <summary>
663         /// Adds months to the given date.
664         /// </summary>
665         /// <param name="time">The
666         /// <see cref="T:System.DateTime"/> to which to add
667         /// months.
668         /// </param>
669         /// <param name="months">The number of months to add.</param>
670         /// <returns>A new <see cref="T:System.DateTime"/> value, that
671         /// results from adding <paramref name="months"/> to the specified
672         /// DateTime.</returns>
673         public static System.DateTime AddMonths(System.DateTime time,
674                 int months)
675         {
676                 int rd = CCFixed.FromDateTime(time);
677                 int day, month, year;
678                 dmy_from_fixed(out day, out month, out year, rd);
679                 month += months;
680                 year += CCMath.div_mod(out month, month, 12);
681                 int maxday = GetDaysInMonth (year, month);
682                 if (day > maxday)
683                         day = maxday;
684                 rd = fixed_from_dmy(day, month, year);
685                 System.DateTime t = CCFixed.ToDateTime(rd);
686                 return t.Add(time.TimeOfDay);
687         }
688
689         /// <summary>
690         /// Adds years to the given date.
691         /// </summary>
692         /// <param name="time">The
693         /// <see cref="T:System.DateTime"/> to which to add
694         /// months.
695         /// </param>
696         /// <param name="years">The number of years to add.</param>
697         /// <returns>A new <see cref="T:System.DateTime"/> value, that
698         /// results from adding <paramref name="years"/> to the specified
699         /// DateTime.</returns>
700         public static System.DateTime AddYears(System.DateTime time,
701                 int years)
702         {
703                 int rd = CCFixed.FromDateTime(time);
704                 int day, month, year;
705                 dmy_from_fixed(out day, out month, out year, rd);
706                 year += years;
707                 int maxday = GetDaysInMonth (year, month);
708                 if (day > maxday)
709                         day = maxday;
710                 rd = fixed_from_dmy(day, month, year);
711                 System.DateTime t = CCFixed.ToDateTime(rd);
712                 return t.Add(time.TimeOfDay);
713         }
714
715         /// <summary>
716         /// Gets the of the month from <paramref name="time"/>.
717         /// </summary>
718         /// <param name="time">The
719         /// <see cref="T:System.DateTime"/> that specifies a
720         /// date.
721         /// </param>
722         /// <returns>An integer giving the day of months, starting with 1.
723         /// </returns>
724         public static int GetDayOfMonth(System.DateTime time) {
725                 return day_from_fixed(CCFixed.FromDateTime(time));
726         }
727
728         /// <summary>
729         /// The method gives the number of the day in the year.
730         /// </summary>
731         /// <param name="time">The
732         /// <see cref="T:System.DateTime"/> that specifies a
733         /// date.
734         /// </param>
735         /// <returns>An integer representing the day of the year,
736         /// starting with 1.</returns>
737         public static int GetDayOfYear(System.DateTime time) {
738                 int rd = CCFixed.FromDateTime(time);
739                 int year = year_from_fixed(rd);
740                 int rd1_1 = fixed_from_dmy(1, 1, year);
741                 return rd - rd1_1 + 1;
742         }
743
744         /// <summary>
745         /// A method that gives the number of days of the specified
746         /// month of the <paramref name="year"/>.
747         /// </summary>
748         /// <param name="year">An integer that gives the year in the current
749         /// era.</param>
750         /// <param name="month">An integer that gives the month, starting
751         /// with 1.</param>
752         /// <returns>An integer that gives the number of days of the
753         /// specified month.</returns>
754         public static int GetDaysInMonth(int year, int month) {
755                 int rd1 = fixed_from_dmy(1, month, year);
756                 int rd2 = fixed_from_dmy(1, month+1, year);
757                 return rd2 - rd1;
758         }
759
760         /// <summary>
761         /// The method gives the number of days in the specified year.
762         /// </summary>
763         /// <param name="year">An integer that gives the year.
764         /// </param>
765         /// <returns>An integer that gives the number of days of the
766         /// specified year.</returns>
767         public static int GetDaysInYear(int year) {
768                 int rd1 = fixed_from_dmy(1, 1, year);
769                 int rd2 = fixed_from_dmy(1, 1, year+1);
770                 return rd2 - rd1;
771         }
772
773         /// <summary>
774         /// The method gives the number of the month of the specified
775         /// date.
776         /// </summary>
777         /// <param name="time">The
778         /// <see cref="T:System.DateTime"/> that specifies a
779         /// date.
780         /// </param>
781         /// <returns>An integer representing the month, 
782         /// starting with 1.</returns>
783         public static int GetMonth(System.DateTime time) {
784                 return month_from_fixed(CCFixed.FromDateTime(time));
785         }
786
787         /// <summary>
788         /// The method gives the number of the year of the specified
789         /// date.
790         /// </summary>
791         /// <param name="time">The
792         /// <see cref="T:System.DateTime"/> that specifies a
793         /// date.
794         /// </param>
795         /// <returns>An integer representing the year. 
796         /// </returns>
797         public static int GetYear(System.DateTime time) {
798                 return year_from_fixed(CCFixed.FromDateTime(time));
799         }
800
801         /// <summary>
802         /// A virtual method that tells whether the given day
803         /// is a leap day.
804         /// </summary>
805         /// <param name="year">An integer that specifies the year.
806         /// </param>
807         /// <param name="month">An integer that specifies the month.
808         /// </param>
809         /// <param name="day">An integer that specifies the day.
810         /// </param>
811         /// <returns>A boolean that tells whether the given day is a leap
812         /// day.
813         /// </returns>
814         public static bool IsLeapDay(int year, int month, int day) {
815                 return is_leap_year(year) && month == 2 && day == 29;
816         }
817
818         /// <summary>
819         /// A method that creates the
820         /// <see cref="T:System.DateTime"/> from the parameters.
821         /// </summary>
822         /// <param name="year">An integer that gives the year
823         /// </param>
824         /// <param name="month">An integer that specifies the month.
825         /// </param>
826         /// <param name="day">An integer that specifies the day.
827         /// </param>
828         /// <param name="hour">An integer that specifies the hour.
829         /// </param>
830         /// <param name="minute">An integer that specifies the minute.
831         /// </param>
832         /// <param name="second">An integer that gives the second.
833         /// </param>
834         /// <param name="milliseconds">An integer that gives the
835         /// milliseconds.
836         /// </param>
837         /// <returns>A
838         /// <see cref="T:system.DateTime"/> representig the date and time.
839         /// </returns>
840         public static System.DateTime ToDateTime(int year, int month, int day,
841                 int hour, int minute, int second, int milliseconds)
842         {
843                 return CCFixed.ToDateTime(fixed_from_dmy(day, month, year),
844                         hour, minute, second, milliseconds);
845         }
846 } // class CCGregorianCalendar
847
848 /// <summary>
849 /// A class encapsulating the functions of the Julian calendar as static
850 /// methods.
851 /// </summary>
852 /// <remarks>
853 /// <para>The algorithms don't support a year 0. Years before Common Era
854 /// (B.C.E. or B.C.) are negative and years of Common Era (C.E. or A.D.)
855 /// are positive.
856 /// </para>
857 /// <para>
858 /// This class is not compatible to
859 /// <see cref="T:System.Globalization.JulianCalendar"/>.
860 /// </para>
861 /// <seealso cref="T:CCFixed"/>
862 /// </remarks>
863 static class CCJulianCalendar {
864         /// <summary>An integer defining the epoch of the Julian calendar
865         /// as fixed day number.</summary>
866         /// <remarks>The epoch is December 30, 0 (Gregorian).</remarks>
867         const int epoch = -1; // 30. 12. 0 Gregorian
868
869         /// <summary>The enumeration defines the months of the Julian
870         /// calendar.
871         /// </summary>
872         public enum Month {
873                 /// <summary>
874                 /// January.
875                 /// </summary>
876                 january = 1,
877                 /// <summary>
878                 /// February.
879                 /// </summary>
880                 february,
881                 /// <summary>
882                 /// March.
883                 /// </summary>
884                 march,
885                 /// <summary>
886                 /// April.
887                 /// </summary>
888                 april,
889                 /// <summary>
890                 /// May.
891                 /// </summary>
892                 may,
893                 /// <summary>
894                 /// June.
895                 /// </summary>
896                 june,
897                 /// <summary>
898                 /// July.
899                 /// </summary>
900                 july,
901                 /// <summary>
902                 /// August.
903                 /// </summary>
904                 august,
905                 /// <summary>
906                 /// September.
907                 /// </summary>
908                 september,
909                 /// <summary>
910                 /// October.
911                 /// </summary>
912                 october,
913                 /// <summary>
914                 /// November.
915                 /// </summary>
916                 november,
917                 /// <summary>
918                 /// December.
919                 /// </summary>
920                 december
921         };
922
923         /// <summary>
924         /// The method tells whether the year is a leap year.
925         /// </summary>
926         /// <param name="year">An integer representing the Julian year.
927         /// </param>
928         /// <returns>A boolean which is true if <paramref name="year"/> is
929         /// a leap year.
930         /// </returns>
931         public static bool is_leap_year(int year) {
932                 return CCMath.mod(year, 4) == (year > 0 ? 0 : 3);
933         }
934
935         /// <summary>
936         /// The method returns the fixed day number of the given Julian
937         /// date.
938         /// </summary>
939         /// <param name="day">An integer representing the day of the month,
940         /// counting from 1.
941         /// </param>
942         /// <param name="month">An integer representing the month in the
943         /// Julian year.
944         /// </param>
945         /// <param name="year">An integer representing the Julian year.
946         /// Positive and Negative values are allowed.
947         /// </param>
948         /// <returns>An integer value representing the fixed day number.
949         /// </returns>
950         public static int fixed_from_dmy(int day, int month, int year) {
951                 int y = year < 0 ? year+1 : year;
952
953                 if (month > 12) {
954                         y += CCMath.div_mod (out month, month - 1, 12);
955                         month++;
956                 }
957
958                 int k = epoch - 1;
959                 k += 365 * (y-1);
960                 k += CCMath.div(y-1, 4);
961                 k += CCMath.div(367*month-362, 12);
962                 if (month > 2) {
963                         k += is_leap_year(year) ? -1 : -2;
964                 }
965                 k += day;
966
967                 return k;
968         }
969
970         /// <summary>
971         /// The method computes the Julian year from a fixed day number.
972         /// </summary>
973         /// <param name="date">The fixed day number.
974         /// </param>
975         /// <returns>An integer value giving the Julian year of the date.
976         /// </returns>
977         public static int year_from_fixed(int date) {
978                 int approx = CCMath.div(4*(date-epoch)+1464, 1461);
979                 return approx <= 0 ? approx - 1 : approx;
980         }
981
982         /// <summary>
983         /// The method computes the Julian year and month from a fixed day
984         /// number.
985         /// </summary>
986         /// <param name="month">The output value giving the Julian month.
987         /// </param>
988         /// <param name="year">The output value giving the Julian year.
989         /// </param>
990         /// <param name="date">An integer value specifying the fixed day
991         /// number.</param>
992         public static void my_from_fixed(out int month, out int year, int date)
993         {
994                 year = year_from_fixed(date);
995
996                 int prior_days = date - fixed_from_dmy(1, (int)Month.january,
997                         year);
998                 
999                 int correction;
1000                 if (date < fixed_from_dmy(1, (int)Month.march, year)) {
1001                         correction = 0;
1002                 } else if (is_leap_year(year)) {
1003                         correction = 1;
1004                 } else {
1005                         correction = 2;
1006                 }
1007
1008                 month = CCMath.div(12 * (prior_days + correction) + 373, 367);
1009         }
1010         
1011
1012         /// <summary>
1013         /// The method computes the Julian year, month, and day from a
1014         /// fixed day number.
1015         /// </summary>
1016         /// <param name="day">The output value returning the day of the
1017         /// month.
1018         /// </param>
1019         /// <param name="month">The output value giving the Julian month.
1020         /// </param>
1021         /// <param name="year">The output value giving the Julian year.
1022         /// </param>
1023         /// <param name="date">An integer value specifying the fixed day
1024         /// number.</param>
1025         public static void dmy_from_fixed(out int day, out int month,
1026                 out int year, int date)
1027         {
1028                 my_from_fixed(out month, out year, date);
1029                 day = date - fixed_from_dmy(1, month, year) + 1;
1030         }
1031
1032         /// <summary>A method computing the Julian month from a fixed
1033         /// day number.
1034         /// </summary>
1035         /// <param name="date">An integer specifying the fixed day number.
1036         /// </param>
1037         /// <returns>An integer value representing the Julian month.
1038         /// </returns>
1039         public static int month_from_fixed(int date) {
1040                 int month, year;
1041
1042                 my_from_fixed(out month, out year, date);
1043                 return month;
1044         }
1045
1046         /// <summary>
1047         /// A method computing the day of the month from a fixed day number.
1048         /// </summary>
1049         /// <param name="date">An integer specifying the fixed day number.
1050         /// </param>
1051         /// <returns>An integer value representing the day of the month.
1052         /// </returns>
1053         public static int day_from_fixed(int date) {
1054                 int day;
1055                 int month;
1056                 int year;
1057
1058                 dmy_from_fixed(out day, out month, out year, date);
1059                 return day;
1060         }
1061
1062         /// <summary>
1063         /// The method computes the difference between two Julian dates.
1064         /// </summary>
1065         /// <param name="dayA">The integer parameter gives the day of month
1066         /// of the first date.
1067         /// </param>
1068         /// <param name="monthA">The integer parameter gives the Julian
1069         /// month of the first date.
1070         /// </param>
1071         /// <param name="yearA">The integer parameter gives the Julian
1072         /// year of the first date.
1073         /// </param>
1074         /// <param name="dayB">The integer parameter gives the day of month
1075         /// of the second date.
1076         /// </param>
1077         /// <param name="monthB">The integer parameter gives the Julian
1078         /// month of the second date.
1079         /// </param>
1080         /// <param name="yearB">The integer parameter gives the Julian
1081         /// year of the second date.
1082         /// </param>
1083         /// <returns>An integer giving the difference of days from the first
1084         /// the second date.
1085         /// </returns>
1086         public static int date_difference(int dayA, int monthA, int yearA,
1087                 int dayB, int monthB, int yearB)
1088         {
1089                 return  fixed_from_dmy(dayB, monthB, yearB) -
1090                         fixed_from_dmy(dayA, monthA, yearA);
1091         }
1092
1093         /// <summary>
1094         /// The method computes the number of the day in the year from
1095         /// a Julian date.
1096         /// </summary>
1097         /// <param name="day">An integer representing the day of the month,
1098         /// counting from 1.
1099         /// </param>
1100         /// <param name="month">An integer representing the month in the
1101         /// Julian year.
1102         /// </param>
1103         /// <param name="year">An integer representing the Julian year.
1104         /// Negative values are allowed also.
1105         /// </param>
1106         /// <returns>An integer value giving the number of the day in the
1107         /// Julian year, counting from 1.
1108         /// </returns>
1109         public static int day_number(int day, int month, int year) {
1110                 return date_difference(31, (int)Month.december, year-1,
1111                         day, month, year);
1112         }
1113
1114         /// <summary>
1115         /// The method computes the days remaining in the given Julian
1116         /// year from a Julian date.
1117         /// </summary>
1118         /// <param name="day">An integer representing the day of the month,
1119         /// counting from 1.
1120         /// </param>
1121         /// <param name="month">An integer representing the month in the
1122         /// Julian year.
1123         /// </param>
1124         /// <param name="year">An integer representing the Julian year.
1125         /// Negative values are allowed also.
1126         /// </param>
1127         /// <returns>An integer value giving the number of days remaining in
1128         /// the Julian year.
1129         /// </returns>
1130         public static int days_remaining(int day, int month, int year) {
1131                 return date_difference(day, month, year,
1132                         31, (int)Month.december, year);
1133         }
1134 } // class CCJulianCalendar
1135
1136 /// <summary>
1137 /// A class encapsulating the functions of the Hebrew calendar as static
1138 /// methods.
1139 /// </summary>
1140 /// <remarks>
1141 /// <para>
1142 /// This class is not compatible to
1143 /// <see cref="T:System.Globalization.HebrewCalendar"/>.
1144 /// </para>
1145 /// <seealso cref="T:CCFixed"/>
1146 /// </remarks>
1147 static class CCHebrewCalendar {
1148         /// <summary>An integer defining the epoch of the Hebrew calendar
1149         /// as fixed day number.</summary>
1150         /// <remarks>The epoch is October 10, 3761 B.C.E. (Julian).</remarks>
1151         const int epoch = -1373427;
1152
1153         /// <summary>The enumeration defines the months of the Gregorian
1154         /// calendar.
1155         /// </summary>
1156         /// <remarks>
1157         /// The enumaration differs from .NET which defines Tishri as month 1.
1158         /// </remarks>
1159         public enum Month {
1160                 /// <summary>
1161                 /// Nisan.
1162                 /// </summary>
1163                 nisan    = 1,
1164                 /// <summary>
1165                 /// Iyyar.
1166                 /// </summary>
1167                 iyyar,
1168                 /// <summary>
1169                 /// Sivan.
1170                 /// </summary>
1171                 sivan,
1172                 /// <summary>
1173                 /// Tammuz.
1174                 /// </summary>
1175                 tammuz,
1176                 /// <summary>
1177                 /// Av.
1178                 /// </summary>
1179                 av,
1180                 /// <summary>
1181                 /// Elul.
1182                 /// </summary>
1183                 elul,
1184                 /// <summary>
1185                 /// Tishri.
1186                 /// </summary>
1187                 tishri,
1188                 /// <summary>
1189                 /// Heshvan.
1190                 /// </summary>
1191                 heshvan,
1192                 /// <summary>
1193                 /// Kislev.
1194                 /// </summary>
1195                 kislev,
1196                 /// <summary>
1197                 /// Teveth.
1198                 /// </summary>
1199                 teveth,
1200                 /// <summary>
1201                 /// Shevat.
1202                 /// </summary>
1203                 shevat,
1204                 /// <summary>
1205                 /// Adar.
1206                 /// </summary>
1207                 adar,
1208                 /// <summary>
1209                 /// Adar I. Only in years with Adar II.
1210                 /// </summary>
1211                 adar_I = 12,
1212                 /// <summary>
1213                 /// Adar II. Only in years wirh Adar I.
1214                 /// </summary>
1215                 adar_II = 13,
1216         };
1217
1218         /// <summary>
1219         /// The method tells whether the year is a leap year.
1220         /// </summary>
1221         /// <param name="year">An integer representing the Hebrew year.
1222         /// </param>
1223         /// <returns>A boolean which is true if <paramref name="year"/> is
1224         /// a leap year.
1225         /// </returns>
1226         public static bool is_leap_year(int year) {
1227                 return CCMath.mod(7*year+1, 19) < 7; 
1228         }
1229
1230         /// <summary>
1231         /// The Method gives the number of the last month in a year, which
1232         /// is equal with the number of month in a Hebrew year.
1233         /// </summary>
1234         /// <param name="year">An integer representing the Hebrew year.
1235         /// </param>
1236         /// <returns>An integer giving the number of the last month of the 
1237         /// Hebrew year, which is the same as the numbers of month in the
1238         /// year.
1239         /// </returns>
1240         public static int last_month_of_year(int year) {
1241                 return is_leap_year(year) ? 13 : 12;
1242         }
1243
1244         
1245         /// <summary>The method is a helper function.</summary>
1246         /// <param name="year">An integer specifying the Hebrew year.
1247         /// </param>
1248         /// <returns>An integer representing the number of elapsed days
1249         /// until the Hebrew year.</returns>
1250         public static int elapsed_days(int year) {
1251                 int months_elapsed = CCMath.div(235*year-234, 19);
1252                 int r;
1253                 int d = CCMath.div_mod(out r, months_elapsed, 1080);
1254                 int parts_elapsed = 204 + 793 * r;
1255                 int hours_elapsed = 11 + 12 * months_elapsed +
1256                                     793 * d + CCMath.div(parts_elapsed, 1080);
1257
1258                 int day = 29*months_elapsed + CCMath.div(hours_elapsed, 24);
1259
1260                 if (CCMath.mod(3*(day+1), 7) < 3) {
1261                         day += 1;
1262                 }
1263
1264                 return day;
1265         }
1266
1267         /// <summary>A method computing the delay of new year for the given
1268         /// Hebrew year.
1269         /// </summary>
1270         /// <param name="year">An integer that gives the Hebrew year.
1271         /// </param>
1272         /// <returns>The new year delay in days of the given Hebrew year.
1273         /// </returns>
1274         public static int new_year_delay(int year) {
1275                 int ny1 = elapsed_days(year);
1276                 int ny2 = elapsed_days(year+1);
1277
1278                 if (ny2 - ny1 == 356) {
1279                         return 2;
1280                 }
1281                 int ny0 = elapsed_days(year-1);
1282                 if (ny1 - ny0 == 382) {
1283                         return 1;
1284                 }
1285                 return 0;
1286         }
1287
1288         /// <summary>
1289         /// The method computes the last day of month (nummer of days in a
1290         /// month) of the given Hebrew year.
1291         /// </summary>
1292         /// <param name="month">The Hebrew month, allowed value between
1293         /// One and Thirteen.
1294         /// </param>
1295         /// <param name="year">An integer that gives the Hebrew year.
1296         /// </param>
1297         /// <returns>The number of the last day of the month of the given
1298         /// Hebrew year, which gives automatically the number of days in the
1299         /// month.
1300         /// </returns>
1301         /// <exception cref="T:System.ArgumentOutOfRange.Exception">
1302         /// The exception is thrown if month not between One and Thirteen.
1303         /// </exception>
1304         public static int last_day_of_month(int month, int year) {
1305                 if (month < 1 || month > 13)
1306                         throw new System.ArgumentOutOfRangeException("month",
1307                                 "Month should be between One and Thirteen.");
1308                 switch (month) {
1309                         case 2: return 29;
1310                         case 4: return 29;
1311                         case 6: return 29;
1312                         case 8:
1313                                 if (!long_heshvan(year))
1314                                         return 29;
1315                                 break;
1316                         case 9:
1317                                 if (short_kislev(year))
1318                                         return 29;
1319                                 break;
1320                         case 10: return 29;
1321                         case 12:
1322                                 if (!is_leap_year(year))
1323                                         return 29;
1324                                 break;
1325                         case 13: return 29;
1326                 }
1327                 return 30;
1328         }
1329         
1330         /// <summary>
1331         /// The functions checks whether the month Heshvan is a long one
1332         /// in the given Hebrew year.
1333         /// </summary>
1334         /// <param name="year">An integer that gives the Hebrew year.
1335         /// </param>
1336         /// <returns>A boolean value: true if there is a long Heshvan
1337         /// in the given Hebrew year; false otherwise.
1338         /// </returns>
1339         public static bool long_heshvan(int year) {
1340                 return CCMath.mod(days_in_year(year), 10) == 5;
1341         }
1342
1343         /// <summary>
1344         /// The functions checks whether the month Kislev is a short one
1345         /// in the given Hebrew year.
1346         /// </summary>
1347         /// <param name="year">An integer that gives the Hebrew year.
1348         /// </param>
1349         /// <returns>A boolean value: true if there is a short Kislev
1350         /// in the given Hebrew year; false otherwise.
1351         /// </returns>
1352         public static bool short_kislev(int year) {
1353                 return CCMath.mod(days_in_year(year), 10) == 3;
1354         }
1355
1356         /// <summary>
1357         /// The functions gives the number of days in the specified Hebrew
1358         /// year.
1359         /// </summary>
1360         /// <param name="year">An integer that gives the Hebrew year.
1361         /// </param>
1362         /// <returns>The days of the Hebrew year as integer.
1363         /// </returns>
1364         public static int days_in_year(int year) {
1365                 return  fixed_from_dmy(1, 7, year+1) -
1366                         fixed_from_dmy(1, 7, year);
1367         }
1368
1369         /// <summary>
1370         /// The method returns the fixed day number of the given Hebrew
1371         /// date.
1372         /// </summary>
1373         /// <param name="day">An integer representing the day of the month,
1374         /// counting from 1.
1375         /// </param>
1376         /// <param name="month">An integer representing the month in the
1377         /// Hebrew year.
1378         /// </param>
1379         /// <param name="year">An integer representing the Hebrew year.
1380         /// Non-positive values are allowed also.
1381         /// </param>
1382         /// <returns>An integer value representing the fixed day number.
1383         /// </returns>
1384         public static int fixed_from_dmy(int day, int month, int year) {
1385                 var lastMonth = last_month_of_year (year);
1386                 while (month > lastMonth) {
1387                         year++;
1388                         month -= lastMonth;
1389                         lastMonth = last_month_of_year (year);
1390                 }
1391
1392                 int m;
1393                 int k = epoch-1;
1394                 k += elapsed_days(year);
1395                 k += new_year_delay(year);
1396
1397                 if (month < 7) {
1398                         int l = last_month_of_year(year);
1399                         for (m = 7; m <= l; m++) {
1400                                 k += last_day_of_month(m, year);
1401                         }
1402                         for (m = 1; m < month; m++) {
1403                                 k += last_day_of_month(m, year);
1404                         }
1405                 }
1406                 else {
1407                         for (m = 7; m < month; m++) {
1408                                 k += last_day_of_month(m, year);
1409                         }
1410                 }
1411                 
1412                 k += day;
1413
1414                 return k;
1415         }
1416
1417         /// <summary>
1418         /// The method computes the Hebrew year from a fixed day number.
1419         /// </summary>
1420         /// <param name="date">The fixed day number.
1421         /// </param>
1422         /// <returns>An integer value giving the Hebrew year of the date.
1423         /// </returns>
1424         public static int year_from_fixed(int date) {
1425                 int approx = (int)System.Math.Floor(
1426                         ((double)(date - epoch))/(35975351.0/98496.0));
1427                 int y;
1428                 for (y = approx; date >= fixed_from_dmy(1, 7, y); y++) {} 
1429                 return y-1;
1430         }
1431
1432         /// <summary>
1433         /// The method computes the Hebrew year and month from a fixed day
1434         /// number.
1435         /// </summary>
1436         /// <param name="month">The output value giving the Hebrew month.
1437         /// </param>
1438         /// <param name="year">The output value giving the Hebrew year.
1439         /// </param>
1440         /// <param name="date">An integer value specifying the fixed day
1441         /// number.</param>
1442         public static void my_from_fixed(out int month, out int year,
1443                 int date)
1444         {
1445                 year = year_from_fixed(date);
1446
1447                 int start = date < fixed_from_dmy(1, 1, year) ? 7 : 1;
1448
1449                 for (month = start;
1450                      date > fixed_from_dmy(last_day_of_month(month, year),
1451                                                 month, year);
1452                      month++)
1453                 {}
1454         }
1455
1456         /// <summary>
1457         /// The method computes the Hebrew year, month, and day from a
1458         /// fixed day number.
1459         /// </summary>
1460         /// <param name="day">The output value returning the day of the
1461         /// month.
1462         /// </param>
1463         /// <param name="month">The output value giving the Hebrew month.
1464         /// </param>
1465         /// <param name="year">The output value giving the Hebrew year.
1466         /// </param>
1467         /// <param name="date">An integer value specifying the fixed day
1468         /// number.</param>
1469         public static void dmy_from_fixed(out int day, out int month,
1470                 out int year, int date)
1471         {
1472                 my_from_fixed(out month, out year, date);
1473                 day = date - fixed_from_dmy(1, month, year) + 1;
1474         }
1475
1476         /// <summary>A method computing the Hebrew month from a fixed
1477         /// day number.
1478         /// </summary>
1479         /// <param name="date">An integer specifying the fixed day number.
1480         /// </param>
1481         /// <returns>An integer value representing the Hebrew month.
1482         /// </returns>
1483         public static int month_from_fixed(int date) {
1484                 int month, year;
1485
1486                 my_from_fixed(out month, out year, date);
1487                 return month;
1488         }
1489
1490         /// <summary>
1491         /// A method computing the day of the month from a fixed day number.
1492         /// </summary>
1493         /// <param name="date">An integer specifying the fixed day number.
1494         /// </param>
1495         /// <returns>An integer value representing the day of the month.
1496         /// </returns>
1497         public static int day_from_fixed(int date) {
1498                 int day, month, year;
1499                 
1500                 dmy_from_fixed(out day, out month, out year, date);
1501                 return day;
1502         }
1503
1504         /// <summary>
1505         /// The method computes the difference between two Hebrew dates.
1506         /// </summary>
1507         /// <param name="dayA">The integer parameter gives the day of month
1508         /// of the first date.
1509         /// </param>
1510         /// <param name="monthA">The integer parameter gives the Hebrew
1511         /// month of the first date.
1512         /// </param>
1513         /// <param name="yearA">The integer parameter gives the Hebrew
1514         /// year of the first date.
1515         /// </param>
1516         /// <param name="dayB">The integer parameter gives the day of month
1517         /// of the second date.
1518         /// </param>
1519         /// <param name="monthB">The integer parameter gives the Hebrew
1520         /// month of the second date.
1521         /// </param>
1522         /// <param name="yearB">The integer parameter gives the Hebrew
1523         /// year of the second date.
1524         /// </param>
1525         /// <returns>An integer giving the difference of days from the first
1526         /// the second date.
1527         /// </returns>
1528         public static int date_difference(int dayA, int monthA, int yearA,
1529                 int dayB, int monthB, int yearB)
1530         {
1531                 return  fixed_from_dmy(dayB, monthB, yearB) -
1532                         fixed_from_dmy(dayA, monthA, yearA);
1533         }
1534
1535         /// <summary>
1536         /// The method computes the number of the day in the year from
1537         /// a Hebrew date.
1538         /// </summary>
1539         /// <param name="day">An integer representing the day of the month,
1540         /// counting from 1.
1541         /// </param>
1542         /// <param name="month">An integer representing the month in the
1543         /// Hebrew year.
1544         /// </param>
1545         /// <param name="year">An integer representing the Hebrew year.
1546         /// </param>
1547         /// <returns>An integer value giving the number of the day in the
1548         /// Hebrew year, counting from 1.
1549         /// </returns>
1550         public static int day_number(int day, int month, int year) {
1551                 return date_difference(1, 7, year,
1552                         day, month, year) + 1;
1553         }
1554
1555         /// <summary>
1556         /// The method computes the days remaining in the given Hebrew
1557         /// year from a Hebrew date.
1558         /// </summary>
1559         /// <param name="day">An integer representing the day of the month,
1560         /// counting from 1.
1561         /// </param>
1562         /// <param name="month">An integer representing the month in the
1563         /// Hebrew year.
1564         /// </param>
1565         /// <param name="year">An integer representing the Hebrew year.
1566         /// </param>
1567         /// <returns>An integer value giving the number of days remaining in
1568         /// the Hebrew year.
1569         /// </returns>
1570         public static int days_remaining(int day, int month, int year) {
1571                 return date_difference(day, month, year,
1572                         1, 7, year+1)-1;
1573         }
1574 } // class HebrewCalendar
1575
1576
1577 /// <summary>
1578 /// A class encapsulating the functions of the Islamic calendar as static
1579 /// methods.
1580 /// </summary>
1581 /// <remarks>
1582 /// <para>There is no difference here in using Hijri or Islamic calendar.
1583 /// </para>
1584 /// <para>The epoch of the Islamic calendar isn't fixed, because we cannot
1585 /// surely say today, when the crescent of the new moon has been observed 
1586 /// around the July 16, 622 C.E. Julian. Even today the start and end of 
1587 /// the month Ramadan is defined by religous authorities. So the calendar
1588 /// can be offset by two days.
1589 /// </para> 
1590 /// <para>
1591 /// We don't support the offset here, however we changed the epoch from
1592 /// "Calendrical Calculations" to value, that .Net seems to be using.
1593 /// </para>
1594 /// <para>
1595 /// This class is not compatible to
1596 /// <see cref="T:System.Globalization.HijriCalendar"/>.
1597 /// </para>
1598 /// <seealso cref="T:CCFixed"/>
1599 /// </remarks>
1600 static class CCHijriCalendar {
1601         /// <summary>An integer defining the epoch of the Gregorian calendar
1602         /// as fixed day number.</summary>
1603         /// <remarks>
1604         /// <para>
1605         /// The epoch is given as 16 July 622 C.E. Julian (R.D. 227015)
1606         /// in Calendrical Calculations, the approximate date of
1607         /// the emigration of
1608         /// Muhammed to Medina. However there is no way to determine today
1609         /// the observation of the crescent of the new moon in July 622 C.E.
1610         /// (Julian). So there is some variability in the epoch.
1611         /// Religous authorities determine the epoch by observing the
1612         /// crescent of the new moon for the month Ramadan, so there might
1613         /// be an offsets by two days of the epoch.
1614         /// </para>
1615         /// <para>Windows
1616         /// supports an AddHijriDate parameter in the registry to adapt
1617         /// for it. It seems that the .NET implementation of
1618         /// HijriCalendar uses an epoch of 227014, so we use it here. The
1619         /// ArgumentOutOfRangeException gives July, 18 622 as epoch,
1620         /// which is 227014 supporting our theory.
1621         /// </para>
1622         /// </remarks>
1623         const int epoch = 227014;
1624
1625         /// <summary>The enumeration defines the months of the Islamic
1626         /// calendar.
1627         /// </summary>
1628         public enum Month {
1629                 /// <summary>
1630                 /// Muharram.
1631                 /// </summary>
1632                 muharram = 1,
1633                 /// <summary>
1634                 /// Safar.
1635                 /// </summary>
1636                 safar,
1637                 /// <summary>
1638                 /// Rabi I.
1639                 /// </summary>
1640                 rabi_I,
1641                 /// <summary>
1642                 /// Rabi II.
1643                 /// </summary>
1644                 rabi_II,
1645                 /// <summary>
1646                 /// Jumada I.
1647                 /// </summary>
1648                 jumada_I,
1649                 /// <summary>
1650                 /// Jumada II.
1651                 /// </summary>
1652                 jumada_II,
1653                 /// <summary>
1654                 /// Rajab.
1655                 /// </summary>
1656                 rajab,
1657                 /// <summary>
1658                 /// Shaban.
1659                 /// </summary>
1660                 shaban,
1661                 /// <summary>
1662                 /// Ramadan.
1663                 /// </summary>
1664                 ramadan,
1665                 /// <summary>
1666                 /// Shawwal.
1667                 /// </summary>
1668                 shawwal,
1669                 /// <summary>
1670                 /// Dhu Al-Quada.
1671                 /// </summary>
1672                 dhu_al_quada,
1673                 /// <summary>
1674                 /// Dhu Al-Hijja.
1675                 /// </summary>
1676                 dhu_al_hijja,
1677         };
1678
1679         /// <summary>
1680         /// The method tells whether the year is a leap year.
1681         /// </summary>
1682         /// <param name="year">An integer representing the Islamic year.
1683         /// </param>
1684         /// <returns>A boolean which is true if <paramref name="year"/> is
1685         /// a leap year.
1686         /// </returns>
1687         public static bool is_leap_year(int year) {
1688                 return CCMath.mod(14+11*year, 30) < 11;
1689         }
1690
1691         /// <summary>
1692         /// The method returns the fixed day number of the given Islamic
1693         /// date.
1694         /// </summary>
1695         /// <param name="day">An integer representing the day of the month,
1696         /// counting from 1.
1697         /// </param>
1698         /// <param name="month">An integer representing the month in the
1699         /// Islamic year.
1700         /// </param>
1701         /// <param name="year">An integer representing the Islamic year.
1702         /// Non-positive values are allowed also.
1703         /// </param>
1704         /// <returns>An integer value representing the fixed day number.
1705         /// </returns>
1706         public static int fixed_from_dmy(int day, int month, int year) {
1707                 if (month > 12) {
1708                         year += CCMath.div_mod (out month, month - 1, 12);
1709                         month++;
1710                 }
1711
1712                 int k = epoch - 1;
1713                 k += 354 * (year-1);
1714                 k += CCMath.div(3+11*year, 30);
1715                 k += (int)System.Math.Ceiling(29.5 * (double)(month-1));
1716                 k += day;
1717
1718                 return k;
1719         }
1720
1721         /// <summary>
1722         /// The method computes the Islamic year from a fixed day number.
1723         /// </summary>
1724         /// <param name="date">The fixed day number.
1725         /// </param>
1726         /// <returns>An integer value giving the Islamic year of the date.
1727         /// </returns>
1728         public static int year_from_fixed(int date) {
1729                 return CCMath.div(30*(date-epoch)+10646, 10631);
1730         }
1731
1732         /// <summary>
1733         /// The method computes the Islamic year and month from a fixed day
1734         /// number.
1735         /// </summary>
1736         /// <param name="month">The output value giving the Islamic month.
1737         /// </param>
1738         /// <param name="year">The output value giving the Islamic year.
1739         /// </param>
1740         /// <param name="date">An integer value specifying the fixed day
1741         /// number.</param>
1742         public static void my_from_fixed(out int month, out int year, int date)
1743         {
1744                 year = year_from_fixed(date);
1745
1746                 int m = 1+(int)System.Math.Ceiling(
1747                         ((double)(date-29-fixed_from_dmy(1,1,year)))/29.5);
1748
1749                 month = m < 12 ? m : 12;
1750         }
1751         
1752         /// <summary>
1753         /// The method computes the Islamic year, month, and day from a
1754         /// fixed day number.
1755         /// </summary>
1756         /// <param name="day">The output value returning the day of the
1757         /// month.
1758         /// </param>
1759         /// <param name="month">The output value giving the Islamic month.
1760         /// </param>
1761         /// <param name="year">The output value giving the Islamic year.
1762         /// </param>
1763         /// <param name="date">An integer value specifying the fixed day
1764         /// number.</param>
1765         public static void dmy_from_fixed(out int day, out int month,
1766                 out int year, int date)
1767         {
1768                 my_from_fixed(out month, out year, date);
1769                 day = date - fixed_from_dmy(1, month, year) + 1;
1770         }
1771
1772         /// <summary>A method computing the Islamic month from a fixed
1773         /// day number.
1774         /// </summary>
1775         /// <param name="date">An integer specifying the fixed day number.
1776         /// </param>
1777         /// <returns>An integer value representing the Islamic month.
1778         /// </returns>
1779         public static int month_from_fixed(int date) {
1780                 int month, year;
1781
1782                 my_from_fixed(out month, out year, date);
1783                 return month;
1784         }
1785
1786         /// <summary>
1787         /// A method computing the day of the month from a fixed day number.
1788         /// </summary>
1789         /// <param name="date">An integer specifying the fixed day number.
1790         /// </param>
1791         /// <returns>An integer value representing the day of the month.
1792         /// </returns>
1793         public static int day_from_fixed(int date) {
1794                 int day;
1795                 int month;
1796                 int year;
1797
1798                 dmy_from_fixed(out day, out month, out year, date);
1799                 return day;
1800         }
1801
1802         /// <summary>
1803         /// The method computes the difference between two Islamic dates.
1804         /// </summary>
1805         /// <param name="dayA">The integer parameter gives the day of month
1806         /// of the first date.
1807         /// </param>
1808         /// <param name="monthA">The integer parameter gives the Islamic
1809         /// month of the first date.
1810         /// </param>
1811         /// <param name="yearA">The integer parameter gives the Islamic
1812         /// year of the first date.
1813         /// </param>
1814         /// <param name="dayB">The integer parameter gives the day of month
1815         /// of the second date.
1816         /// </param>
1817         /// <param name="monthB">The integer parameter gives the Islamic
1818         /// month of the second date.
1819         /// </param>
1820         /// <param name="yearB">The integer parameter gives the Islamic
1821         /// year of the second date.
1822         /// </param>
1823         /// <returns>An integer giving the difference of days from the first
1824         /// the second date.
1825         /// </returns>
1826         public static int date_difference(int dayA, int monthA, int yearA,
1827                 int dayB, int monthB, int yearB)
1828         {
1829                 return  fixed_from_dmy(dayB, monthB, yearB) -
1830                         fixed_from_dmy(dayA, monthA, yearA);
1831         }
1832
1833         /// <summary>
1834         /// The method computes the number of the day in the year from
1835         /// a Islamic date.
1836         /// </summary>
1837         /// <param name="day">An integer representing the day of the month,
1838         /// counting from 1.
1839         /// </param>
1840         /// <param name="month">An integer representing the month in the
1841         /// Islamic year.
1842         /// </param>
1843         /// <param name="year">An integer representing the Islamic year.
1844         /// </param>
1845         /// <returns>An integer value giving the number of the day in the
1846         /// Islamic year, counting from 1.
1847         /// </returns>
1848         public static int day_number(int day, int month, int year) {
1849                 return date_difference(31, 12, year-1, day, month, year);
1850         }
1851
1852         /// <summary>
1853         /// The method computes the days remaining in the given Islamic
1854         /// year from a Islamic date.
1855         /// </summary>
1856         /// <param name="day">An integer representing the day of the month,
1857         /// counting from 1.
1858         /// </param>
1859         /// <param name="month">An integer representing the month in the
1860         /// Islamic year.
1861         /// </param>
1862         /// <param name="year">An integer representing the Islamic year.
1863         /// Non-positive values are allowed also.
1864         /// </param>
1865         /// <returns>An integer value giving the number of days remaining in
1866         /// the Islamic year.
1867         /// </returns>
1868         public static int days_remaining(int day, int month, int year) {
1869                 return date_difference(day, month, year,31, 12, year);
1870         }
1871 } // class CCHijriCalendar
1872
1873 internal class CCEastAsianLunisolarCalendar
1874 {
1875         public static int fixed_from_dmy (int day, int month, int year)
1876         {
1877                 /*
1878                 int k = epoch - 1;
1879                 k += 354 * (year - 1);
1880                 k += CCMath.div (3+11*year, 30);
1881                 k += (int) Math.Ceiling(29.53 * (double)(month-1));
1882                 k += day;
1883
1884                 return k;
1885                 */
1886                 throw new Exception ("fixed_from_dmy");
1887         }
1888
1889         public static int year_from_fixed (int date)
1890         {
1891                 throw new Exception ("year_from_fixed");
1892         }
1893
1894         public static void my_from_fixed(out int month, out int year, int date)
1895         {
1896                 /*
1897                 year = year_from_fixed (date);
1898
1899                 int m = 1+(int)System.Math.Ceiling(
1900                         ((double)(date-29-fixed_from_dmy(1,1,year)))/29.5);
1901
1902                 month = m < 12 ? m : 12;
1903                 */
1904                 throw new Exception ("my_from_fixed");
1905         }
1906
1907         public static void dmy_from_fixed(out int day, out int month,
1908                 out int year, int date)
1909         {
1910                 /*
1911                 my_from_fixed (out month, out year, date);
1912                 day = date - fixed_from_dmy (1, month, year) + 1;
1913                 */
1914                 throw new Exception ("dmy_from_fixed");
1915         }
1916
1917         public static DateTime AddMonths (DateTime date, int months)
1918         {
1919                 
1920                 throw new Exception ("AddMonths");
1921         }
1922
1923         public static DateTime AddYears (DateTime date, int years)
1924         {
1925                 throw new Exception ("AddYears");
1926         }
1927
1928         public static int GetDayOfMonth (DateTime date)
1929         {
1930                 throw new Exception ("GetDayOfMonth");
1931         }
1932
1933         public static int GetDayOfYear (DateTime date)
1934         {
1935                 throw new Exception ("GetDayOfYear");
1936         }
1937
1938         public static int GetDaysInMonth (int gyear, int month)
1939         {
1940                 throw new Exception ("GetDaysInMonth");
1941         }
1942
1943         public static int GetDaysInYear (int year)
1944         {
1945                 throw new Exception ("GetDaysInYear");
1946         }
1947
1948         public static int GetMonth (DateTime date)
1949         {
1950                 throw new Exception ("GetMonth");
1951         }
1952
1953         public static bool IsLeapMonth (int gyear, int month)
1954         {
1955                 int goldenNumber = gyear % 19;
1956
1957                 bool chu = false;
1958                 bool leap = false;
1959                 double s = 0;
1960                 for (int y = 0; y < goldenNumber; y++) {
1961                         for (int l = 0, m = 1; m <= month; m++) {
1962                                 if (leap) {
1963                                         l += 30;
1964                                         leap = false;
1965                                         if (y == goldenNumber && m == month)
1966                                                 return true;
1967                                 } else {
1968                                         l += chu ? 30 : 29;
1969                                         chu = !chu;
1970                                         s += 30.44;
1971                                         if (s - l > 29)
1972                                                 leap = true;
1973                                 }
1974                         }
1975                 }
1976                 return false;
1977         }
1978
1979         public static bool IsLeapYear (int gyear)
1980         {
1981
1982                 // FIXME: it is still wrong.
1983                 int d = gyear % 19;
1984                 switch (d) {
1985                 case 0: case 3: case 6: case 9: case 11: case 14: case 17:
1986                         return true;
1987                 default:
1988                         return false;
1989                 }
1990                 /*
1991                 int goldenNumber = (gyear - 1900) % 19;
1992                 int epact = 29;
1993                 bool leap = false;
1994                 while (goldenNumber-- >= 0) {
1995                         epact += 11;
1996                         leap = epact > 30;
1997                         if (epact > 30)
1998                                 epact -= 30;
1999                 }
2000                 return leap;
2001                 */
2002         }
2003
2004         public static DateTime ToDateTime (int year, int month, int day, int hour, int minute, int second, int millisecond)
2005         {
2006                 throw new Exception ("ToDateTime");
2007         }
2008 }
2009
2010 /// <summary>
2011 /// A class that supports the Gregorian based calendars with other eras
2012 /// (e.g. <see cref="T:System.Gloablization.JapaneseCalendar"/>).
2013 /// </summary>
2014 [System.Serializable]
2015 internal class CCGregorianEraHandler {
2016         /// <summary>
2017         /// A struct that represents a single era.
2018         /// </summary>
2019         [System.Serializable]
2020         struct Era {
2021                 /// <summary>
2022                 /// The integer number identifying the era.
2023                 /// </summary>
2024                 private int _nr;
2025
2026                 /// <value>
2027                 /// A get-only property that gives the era integer number.
2028                 /// </value>
2029                 public int Nr { get { return _nr; } }
2030
2031                 /// <summary>This integer gives the first day of the era as
2032                 /// fixed day number.
2033                 /// </summary>
2034                 private int _start; // inclusive
2035                 /// <summary>
2036                 /// This integer gives the gregorian year of the
2037                 /// <see cref="M:_start"/> value.
2038                 /// </summary>
2039                 private int _gregorianYearStart;
2040                 /// <summary>
2041                 /// This integer gives the last day of the era as fixed day
2042                 /// number.
2043                 /// </summary>
2044                 private int _end;   // inclusive        
2045                 /// <summary>
2046                 /// This integer gives the largest year number of this era.
2047                 /// </summary>
2048                 private int _maxYear;
2049
2050                 /// <summary>
2051                 /// This constructor creates the era structure.
2052                 /// </summary>
2053                 /// <param name="nr">The integer number of the era.
2054                 /// </param>
2055                 /// <param name="start">The fixed day number defining the
2056                 /// first day of the era.
2057                 /// </param>
2058                 /// <param name="end">The fixed day number that defines the
2059                 /// last day of the era.
2060                 /// </param>
2061                 public Era(int nr, int start, int end) {
2062                         if (nr == 0)
2063                                 throw new System.ArgumentException(
2064                                         "Era number shouldn't be zero.");
2065                         _nr = nr;
2066                         if (start > end) {
2067                                 throw new System.ArgumentException(
2068                                         "Era should start before end.");
2069                         }
2070                         _start = start;
2071                         _end = end;
2072
2073                         _gregorianYearStart =
2074                                 CCGregorianCalendar.year_from_fixed(_start);
2075                         int gregorianYearEnd =
2076                                 CCGregorianCalendar.year_from_fixed(_end);
2077                         _maxYear = gregorianYearEnd - _gregorianYearStart + 1;
2078                 }
2079
2080                 /// <summary>
2081                 /// This method computes the Gregorian year from the year
2082                 /// of this era.
2083                 /// </summary>
2084                 /// <param name="year">An integer giving the year in the
2085                 /// era.
2086                 /// </param>
2087                 /// <returns>
2088                 /// The Gregorian year as integer.
2089                 /// </returns>
2090                 /// <exception cref="T:System.ArgumentOutOfRangeException">
2091                 /// The exception is thrown if the year isn't valid in this
2092                 /// era.
2093                 /// </exception>
2094                 public int GregorianYear(int year) {
2095                         if (year < 1 || year > _maxYear) {
2096                                 System.IO.StringWriter sw = 
2097                                         new System.IO.StringWriter();
2098                                 sw.Write(
2099                                         "Valid Values are between " +
2100                                         "{0} and {1}, inclusive.",
2101                                         1, _maxYear);
2102                                 throw new System.ArgumentOutOfRangeException(
2103                                         "year", sw.ToString());
2104                         }
2105                         return year + _gregorianYearStart - 1;
2106                 }
2107
2108                 /// <summary>
2109                 /// This function checks wether the given fixed day number is
2110                 /// ion the time span of the era.
2111                 /// </summary>
2112                 /// <param name="date">An integer giving the fixed day
2113                 /// number.
2114                 /// </param>
2115                 /// <returns>A boolean: true if the argument is in the time
2116                 /// span of the era.
2117                 /// </returns>
2118                 public bool Covers(int date) {
2119                         return _start <= date && date <= _end;
2120                 }
2121
2122                 /// <summary>
2123                 /// This function returns the year of the era and sets
2124                 /// the era in an output parameter.
2125                 /// </summary>
2126                 /// <param name="era">An output parameter returning the
2127                 /// era number.
2128                 /// </param>
2129                 /// <param name="date">An integer giving the fixed day
2130                 /// number.
2131                 /// </param>
2132                 /// <returns>An integer giving the year of the era.
2133                 /// </returns>
2134                 /// <exception cref="T:System.ArgumentOutOfRangeException">
2135                 /// The exception is thrown if date is outside of the time
2136                 /// span of the era.
2137                 /// </exception>
2138                 public int EraYear(out int era, int date) {
2139                         if (!Covers(date))
2140                                 throw new System.ArgumentOutOfRangeException(
2141                                         "date", 
2142                                         "Time was out of Era range.");
2143                         int gregorianYear =
2144                                 CCGregorianCalendar.year_from_fixed(date);
2145                         era = _nr;
2146                         return gregorianYear - _gregorianYearStart + 1;
2147                 }
2148         } // struct Era
2149
2150         /// <summary>
2151         /// A private member storing the eras in a
2152         /// <see cref="T:System.Collections.SortedList"/>.
2153         /// </summary>
2154         private SortedList _Eras;
2155
2156         /// <value>
2157         /// The property returns the era numbers as an array of integers.
2158         /// </value>
2159         public int[] Eras {
2160                 get {
2161                         int[] a = new int[_Eras.Count];
2162
2163                         for (int i = 0; i < _Eras.Count; i++) {
2164                                 Era e = (Era)_Eras.GetByIndex(i);
2165                                 a[i] = e.Nr;
2166                         }
2167
2168                         return a;
2169                 }
2170         }
2171
2172         /// <summary>
2173         /// Constructor.
2174         /// </summary>
2175         public CCGregorianEraHandler() {
2176                 _Eras = new SortedList();
2177         }
2178
2179         /// <summary>
2180         /// Method adds an era to the GregorianEraHandler instance.
2181         /// </summary>
2182         /// <param name="nr">The integer number of the era.
2183         /// </param>
2184         /// <param name="rd_start">The fixed day number defining the
2185         /// first day of the era.
2186         /// </param>
2187         /// <param name="rd_end">The fixed day number that defines the
2188         /// last day of the era.
2189         /// </param>
2190         public void appendEra(int nr, int rd_start, int rd_end) {
2191                 Era era = new Era(nr, rd_start, rd_end);
2192                 _Eras[(System.Object)nr] = era;
2193         }
2194         /// <summary>
2195         /// Method adds a yet not-ended era to the GregorianEraHandler
2196         /// instance.
2197         /// </summary>
2198         /// <param name="nr">The integer number of the era.
2199         /// </param>
2200         /// <param name="rd_start">The fixed day number defining the
2201         /// first day of the era.
2202         /// </param>
2203         public void appendEra(int nr, int rd_start) {
2204                 appendEra(nr, rd_start,
2205                         CCFixed.FromDateTime(DateTime.MaxValue));
2206         }
2207
2208         /// <summary>
2209         /// This method computes the Gregorian year from the year
2210         /// of the given era.
2211         /// </summary>
2212         /// <param name="year">An integer giving the year in the
2213         /// era.
2214         /// </param>
2215         /// <param name="era">An integer giving the era number.
2216         /// </param>
2217         /// <returns>
2218         /// The Gregorian year as integer.
2219         /// </returns>
2220         /// <exception cref="T:System.ArgumentOutOfRangeException">
2221         /// The exception is thrown if the year isn't valid in this
2222         /// era.
2223         /// </exception>
2224         public int GregorianYear(int year, int era) {
2225                 Era e = (Era)_Eras[(System.Object)era];
2226                 return e.GregorianYear(year);
2227         }
2228
2229         /// <summary>
2230         /// This function returns the year of the era and sets
2231         /// the era in an output parameter.
2232         /// </summary>
2233         /// <param name="era">An output parameter returning the
2234         /// era number.
2235         /// </param>
2236         /// <param name="date">An integer giving the fixed day
2237         /// number.
2238         /// </param>
2239         /// <returns>An integer giving the year of the era.
2240         /// </returns>
2241         /// <exception cref="T:System.ArgumentOutOfRangeException">
2242         /// The exception is thrown if the fixed day number is outside of the
2243         /// time spans of all eras.
2244         /// </exception>
2245         public int EraYear(out int era, int date)
2246         {
2247                 IList list = _Eras.GetValueList();
2248
2249                 foreach (Era e in list) {
2250                         if (e.Covers(date))
2251                                 return e.EraYear(out era, date);
2252                 }
2253
2254                 throw new System.ArgumentOutOfRangeException("date",
2255                         "Time value was out of era range.");
2256         }
2257
2258         /// <summary>
2259         /// The method checks whether a given
2260         /// <see cref="T:System.DateTime"/> is covered by any era.
2261         /// </summary>
2262         /// <param name="time">A 
2263         /// <see cref="T:System.DateTime"/> giving the date and time.
2264         /// </param>
2265         /// <exception cref="T:System.ArgumentOutOfRangeException">
2266         /// The exception is thrown if the argument isn't inside the time
2267         /// span of any era.
2268         /// </exception>
2269         public void CheckDateTime(System.DateTime time) {
2270                 int date = CCFixed.FromDateTime(time);
2271
2272                 if (!ValidDate(date))
2273                         throw new System.ArgumentOutOfRangeException("time",
2274                                 "Time value was out of era range.");
2275         }
2276                 
2277         /// <summary>
2278         /// The method tests whether a given
2279         /// fixed day number is covered by any era.
2280         /// </summary>
2281         /// <param name="date">An integer representing the fixed day number.
2282         /// </param>
2283         /// <returns> A boolean is returned: true if the argument is inside
2284         /// the time span of one era; false otherwise.
2285         /// </returns>
2286         public bool ValidDate(int date) {
2287                 IList list = _Eras.GetValueList();
2288
2289                 foreach (Era e in list) {
2290                         if (e.Covers(date))
2291                                 return true;
2292                 }
2293
2294                 return false;
2295         }
2296
2297         /// <summary>
2298         /// The method tests, whether the era number does exist.
2299         /// </summary>
2300         /// <param name="era">An integer giving the era number.
2301         /// </param>
2302         /// <returns>A boole value: True if the era number does exist;
2303         /// false otherwise.
2304         /// </returns>
2305         public bool ValidEra(int era) {
2306                 return _Eras.Contains((System.Object)era);
2307         }
2308 } // class CCGregorianEraHandler
2309
2310
2311 // FIXME: remove this class. It should be identical to CCGregorianEraHandler
2312 [System.Serializable]
2313 internal class CCEastAsianLunisolarEraHandler
2314 {
2315         [Serializable]
2316         struct Era 
2317         {
2318                 private int _nr; // era index
2319
2320                 public int Nr {
2321                         get { return _nr; }
2322                 }
2323
2324                 private int _start; // inclusive
2325                 private int _gregorianYearStart;
2326                 private int _end;   // inclusive
2327                 private int _maxYear;
2328
2329                 public Era (int nr, int start, int end)
2330                 {
2331                         if (nr == 0)
2332                                 throw new ArgumentException ("Era number shouldn't be zero.");
2333                         _nr = nr;
2334                         if (start > end)
2335                                 throw new ArgumentException ("Era should start before end.");
2336                         _start = start;
2337                         _end = end;
2338
2339                         _gregorianYearStart = CCGregorianCalendar.year_from_fixed (_start);
2340                         int gregorianYearEnd = CCGregorianCalendar.year_from_fixed (_end);
2341                         _maxYear = gregorianYearEnd - _gregorianYearStart + 1;
2342                 }
2343
2344                 public int GregorianYear (int year) 
2345                 {
2346                         if (year < 1 || year > _maxYear)
2347                                 throw new ArgumentOutOfRangeException ("year", String.Format ("Valid Values are between {0} and {1}, inclusive.", 1, _maxYear));
2348                         return year + _gregorianYearStart - 1;
2349                 }
2350
2351                 public bool Covers (int date) {
2352                         return _start <= date && date <= _end;
2353                 }
2354
2355                 public int EraYear (out int era, int date) {
2356                         if (!Covers (date))
2357                                 throw new ArgumentOutOfRangeException ("date", "Time was out of Era range.");
2358                         int gregorianYear = CCGregorianCalendar.year_from_fixed (date);
2359                         era = _nr;
2360                         return gregorianYear - _gregorianYearStart + 1;
2361                 }
2362         }
2363
2364         private SortedList _Eras;
2365
2366         public int [] Eras 
2367         {
2368                 get {
2369                         int[] a = new int [_Eras.Count];
2370                         for (int i = 0; i < _Eras.Count; i++) {
2371                                 Era e = (Era) _Eras.GetByIndex (i);
2372                                 a[i] = e.Nr;
2373                         }
2374                         return a;
2375                 }
2376         }
2377
2378         public CCEastAsianLunisolarEraHandler ()
2379         {
2380                 _Eras = new SortedList ();
2381         }
2382
2383         public void appendEra (int nr, int rd_start, int rd_end)
2384         {
2385                 Era era = new Era (nr, rd_start, rd_end);
2386                 _Eras [nr] = era;
2387         }
2388
2389         public void appendEra (int nr, int rd_start)
2390         {
2391                 appendEra (nr, rd_start, CCFixed.FromDateTime (DateTime.MaxValue));
2392         }
2393
2394         public int GregorianYear (int year, int era)
2395         {
2396                 Era e = (Era) _Eras [era];
2397                 return e.GregorianYear (year);
2398         }
2399
2400         public int EraYear (out int era, int date)
2401         {
2402                 foreach (Era e in _Eras.Values)
2403                         if (e.Covers (date))
2404                                 return e.EraYear (out era, date);
2405
2406                 throw new ArgumentOutOfRangeException ("date", "Time value was out of era range.");
2407         }
2408
2409         public void CheckDateTime (DateTime time)
2410         {
2411                 int date = CCFixed.FromDateTime (time);
2412
2413                 if (!ValidDate (date))
2414                         throw new ArgumentOutOfRangeException ("time", "Time value was out of era range.");
2415         }
2416                 
2417         public bool ValidDate (int date)
2418         {
2419                 foreach (Era e in _Eras.Values) {
2420                         if (e.Covers (date))
2421                                 return true;
2422                 }
2423                 return false;
2424         }
2425
2426         public bool ValidEra (int era)
2427         {
2428                 return _Eras.Contains (era);
2429         }
2430 }
2431
2432 } // namespace System.Globalization