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