2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[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 internal 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 internal 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 internal 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                 int k = epoch - 1;
470                 k += 365 * (year-1);
471                 k += CCMath.div(year-1, 4);
472                 k -= CCMath.div(year-1, 100);
473                 k += CCMath.div(year-1, 400);
474                 k += CCMath.div(367*month-362, 12);
475                 if (month > 2) {
476                         k += is_leap_year(year) ? -1 : -2;
477                 }
478
479                 k += day;
480
481                 return k;
482         }
483
484         /// <summary>
485         /// The method computes the Gregorian year from a fixed day number.
486         /// </summary>
487         /// <param name="date">The fixed day number.
488         /// </param>
489         /// <returns>An integer value giving the Gregorian year of the date.
490         /// </returns>
491         public static int year_from_fixed(int date) {
492                 int d           = date - epoch;
493                 int n_400       = CCMath.div_mod(out d, d, 146097);
494                 int n_100       = CCMath.div_mod(out d, d, 36524);
495                 int n_4         = CCMath.div_mod(out d, d, 1461);
496                 int n_1         = CCMath.div(d, 365);
497
498                 int year = 400*n_400 + 100*n_100 + 4*n_4 + n_1;
499                 return (n_100 == 4 || n_1 == 4) ? year : year + 1;
500         }
501
502         /// <summary>
503         /// The method computes the Gregorian year and month from a fixed day
504         /// number.
505         /// </summary>
506         /// <param name="month">The output value giving the Gregorian month.
507         /// </param>
508         /// <param name="year">The output value giving the Gregorian year.
509         /// </param>
510         /// <param name="date">An integer value specifying the fixed day
511         /// number.</param>
512         public static void my_from_fixed(out int month, out int year,
513                 int date)
514         {
515                 year = year_from_fixed(date);
516
517                 int prior_days = date - fixed_from_dmy(1, (int)Month.january,
518                         year);
519                 
520                 int correction;
521                 if (date < fixed_from_dmy(1, (int)Month.march, year)) {
522                         correction = 0;
523                 } else if (is_leap_year(year)) {
524                         correction = 1;
525                 } else {
526                         correction = 2;
527                 }
528
529                 month = CCMath.div(12 * (prior_days + correction) + 373, 367);
530
531         }
532
533         /// <summary>
534         /// The method computes the Gregorian year, month, and day from a
535         /// fixed day number.
536         /// </summary>
537         /// <param name="day">The output value returning the day of the
538         /// month.
539         /// </param>
540         /// <param name="month">The output value giving the Gregorian month.
541         /// </param>
542         /// <param name="year">The output value giving the Gregorian year.
543         /// </param>
544         /// <param name="date">An integer value specifying the fixed day
545         /// number.</param>
546         public static void dmy_from_fixed(out int day, out int month,
547                 out int year,
548                 int date)
549         {
550                 my_from_fixed(out month, out year, date);
551                 day = date - fixed_from_dmy(1, month, year) + 1;
552         }
553
554         /// <summary>A method computing the Gregorian month from a fixed
555         /// day number.
556         /// </summary>
557         /// <param name="date">An integer specifying the fixed day number.
558         /// </param>
559         /// <returns>An integer value representing the Gregorian month.
560         /// </returns>
561         public static int month_from_fixed(int date) {
562                 int month, year;
563
564                 my_from_fixed(out month, out year, date);
565                 return month;
566         }
567
568         /// <summary>
569         /// A method computing the day of the month from a fixed day number.
570         /// </summary>
571         /// <param name="date">An integer specifying the fixed day number.
572         /// </param>
573         /// <returns>An integer value representing the day of the month.
574         /// </returns>
575         public static int day_from_fixed(int date) {
576                 int day, month, year;
577
578                 dmy_from_fixed(out day, out month, out year, date);
579                 return day;
580         }
581
582         /// <summary>
583         /// The method computes the difference between two Gregorian dates.
584         /// </summary>
585         /// <param name="dayA">The integer parameter gives the day of month
586         /// of the first date.
587         /// </param>
588         /// <param name="monthA">The integer parameter gives the Gregorian
589         /// month of the first date.
590         /// </param>
591         /// <param name="yearA">The integer parameter gives the Gregorian
592         /// year of the first date.
593         /// </param>
594         /// <param name="dayB">The integer parameter gives the day of month
595         /// of the second date.
596         /// </param>
597         /// <param name="monthB">The integer parameter gives the Gregorian
598         /// month of the second date.
599         /// </param>
600         /// <param name="yearB">The integer parameter gives the Gregorian
601         /// year of the second date.
602         /// </param>
603         /// <returns>An integer giving the difference of days from the first
604         /// the second date.
605         /// </returns>
606         public static int date_difference(int dayA, int monthA, int yearA,
607                 int dayB, int monthB, int yearB)
608         {
609                 return  fixed_from_dmy(dayB, monthB, yearB) -
610                         fixed_from_dmy(dayA, monthA, yearA);
611         }
612
613         /// <summary>
614         /// The method computes the number of the day in the year from
615         /// a Gregorian date.
616         /// </summary>
617         /// <param name="day">An integer representing the day of the month,
618         /// counting from 1.
619         /// </param>
620         /// <param name="month">An integer representing the month in the
621         /// Gregorian year.
622         /// </param>
623         /// <param name="year">An integer representing the Gregorian year.
624         /// Non-positive values are allowed also.
625         /// </param>
626         /// <returns>An integer value giving the number of the day in the
627         /// Gregorian year, counting from 1.
628         /// </returns>
629         public static int day_number(int day, int month, int year) {
630                 return date_difference(31, (int)Month.december, year-1,
631                         day, month, year);
632         }
633
634         /// <summary>
635         /// The method computes the days remaining in the given Gregorian
636         /// year from a Gregorian date.
637         /// </summary>
638         /// <param name="day">An integer representing the day of the month,
639         /// counting from 1.
640         /// </param>
641         /// <param name="month">An integer representing the month in the
642         /// Gregorian year.
643         /// </param>
644         /// <param name="year">An integer representing the Gregorian year.
645         /// Non-positive values are allowed also.
646         /// </param>
647         /// <returns>An integer value giving the number of days remaining in
648         /// the Gregorian year.
649         /// </returns>
650         public static int days_remaining(int day, int month, int year) {
651                 return date_difference(day, month, year,
652                         31, (int)Month.december, year);
653         }
654
655         // Helper functions for the Gregorian calendars.
656
657         /// <summary>
658         /// Adds months 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="months">The number of months to add.</param>
665         /// <returns>A new <see cref="T:System.DateTime"/> value, that
666         /// results from adding <paramref name="months"/> to the specified
667         /// DateTime.</returns>
668         public static System.DateTime AddMonths(System.DateTime time,
669                 int months)
670         {
671                 int rd = CCFixed.FromDateTime(time);
672                 int day, month, year;
673                 dmy_from_fixed(out day, out month, out year, rd);
674                 month += months;
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         /// Adds years to the given date.
682         /// </summary>
683         /// <param name="time">The
684         /// <see cref="T:System.DateTime"/> to which to add
685         /// months.
686         /// </param>
687         /// <param name="years">The number of years to add.</param>
688         /// <returns>A new <see cref="T:System.DateTime"/> value, that
689         /// results from adding <paramref name="years"/> to the specified
690         /// DateTime.</returns>
691         public static System.DateTime AddYears(System.DateTime time,
692                 int years)
693         {
694                 int rd = CCFixed.FromDateTime(time);
695                 int day, month, year;
696                 dmy_from_fixed(out day, out month, out year, rd);
697                 year += years;
698                 rd = fixed_from_dmy(day, month, year);
699                 System.DateTime t = CCFixed.ToDateTime(rd);
700                 return t.Add(time.TimeOfDay);
701         }
702
703         /// <summary>
704         /// Gets the of the month from <paramref name="time"/>.
705         /// </summary>
706         /// <param name="time">The
707         /// <see cref="T:System.DateTime"/> that specifies a
708         /// date.
709         /// </param>
710         /// <returns>An integer giving the day of months, starting with 1.
711         /// </returns>
712         public static int GetDayOfMonth(System.DateTime time) {
713                 return day_from_fixed(CCFixed.FromDateTime(time));
714         }
715
716         /// <summary>
717         /// The method gives the number of the day in the year.
718         /// </summary>
719         /// <param name="time">The
720         /// <see cref="T:System.DateTime"/> that specifies a
721         /// date.
722         /// </param>
723         /// <returns>An integer representing the day of the year,
724         /// starting with 1.</returns>
725         public static int GetDayOfYear(System.DateTime time) {
726                 int rd = CCFixed.FromDateTime(time);
727                 int year = year_from_fixed(rd);
728                 int rd1_1 = fixed_from_dmy(1, 1, year);
729                 return rd - rd1_1 + 1;
730         }
731
732         /// <summary>
733         /// A method that gives the number of days of the specified
734         /// month of the <paramref name="year"/>.
735         /// </summary>
736         /// <param name="year">An integer that gives the year in the current
737         /// era.</param>
738         /// <param name="month">An integer that gives the month, starting
739         /// with 1.</param>
740         /// <returns>An integer that gives the number of days of the
741         /// specified month.</returns>
742         public static int GetDaysInMonth(int year, int month) {
743                 int rd1 = fixed_from_dmy(1, month, year);
744                 int rd2 = fixed_from_dmy(1, month+1, year);
745                 return rd2 - rd1;
746         }
747
748         /// <summary>
749         /// The method gives the number of days in the specified year.
750         /// </summary>
751         /// <param name="year">An integer that gives the year.
752         /// </param>
753         /// <returns>An integer that gives the number of days of the
754         /// specified year.</returns>
755         public static int GetDaysInYear(int year) {
756                 int rd1 = fixed_from_dmy(1, 1, year);
757                 int rd2 = fixed_from_dmy(1, 1, year+1);
758                 return rd2 - rd1;
759         }
760
761         /// <summary>
762         /// The method gives the number of the month of the specified
763         /// date.
764         /// </summary>
765         /// <param name="time">The
766         /// <see cref="T:System.DateTime"/> that specifies a
767         /// date.
768         /// </param>
769         /// <returns>An integer representing the month, 
770         /// starting with 1.</returns>
771         public static int GetMonth(System.DateTime time) {
772                 return month_from_fixed(CCFixed.FromDateTime(time));
773         }
774
775         /// <summary>
776         /// The method gives the number of the year of the specified
777         /// date.
778         /// </summary>
779         /// <param name="time">The
780         /// <see cref="T:System.DateTime"/> that specifies a
781         /// date.
782         /// </param>
783         /// <returns>An integer representing the year. 
784         /// </returns>
785         public static int GetYear(System.DateTime time) {
786                 return year_from_fixed(CCFixed.FromDateTime(time));
787         }
788
789         /// <summary>
790         /// A virtual method that tells whether the given day
791         /// is a leap day.
792         /// </summary>
793         /// <param name="year">An integer that specifies the year.
794         /// </param>
795         /// <param name="month">An integer that specifies the month.
796         /// </param>
797         /// <param name="day">An integer that specifies the day.
798         /// </param>
799         /// <returns>A boolean that tells whether the given day is a leap
800         /// day.
801         /// </returns>
802         public static bool IsLeapDay(int year, int month, int day) {
803                 return is_leap_year(year) && month == 2 && day == 29;
804         }
805
806         /// <summary>
807         /// A method that creates the
808         /// <see cref="T:System.DateTime"/> from the parameters.
809         /// </summary>
810         /// <param name="year">An integer that gives the year
811         /// </param>
812         /// <param name="month">An integer that specifies the month.
813         /// </param>
814         /// <param name="day">An integer that specifies the day.
815         /// </param>
816         /// <param name="hour">An integer that specifies the hour.
817         /// </param>
818         /// <param name="minute">An integer that specifies the minute.
819         /// </param>
820         /// <param name="second">An integer that gives the second.
821         /// </param>
822         /// <param name="milliseconds">An integer that gives the
823         /// milliseconds.
824         /// </param>
825         /// <returns>A
826         /// <see cref="T:system.DateTime"/> representig the date and time.
827         /// </returns>
828         public static System.DateTime ToDateTime(int year, int month, int day,
829                 int hour, int minute, int second, int milliseconds)
830         {
831                 return CCFixed.ToDateTime(fixed_from_dmy(day, month, year),
832                         hour, minute, second, milliseconds);
833         }
834 } // class CCGregorianCalendar
835
836 /// <summary>
837 /// A class encapsulating the functions of the Julian calendar as static
838 /// methods.
839 /// </summary>
840 /// <remarks>
841 /// <para>The algorithms don't support a year 0. Years before Common Era
842 /// (B.C.E. or B.C.) are negative and years of Common Era (C.E. or A.D.)
843 /// are positive.
844 /// </para>
845 /// <para>
846 /// This class is not compatible to
847 /// <see cref="T:System.Globalization.JulianCalendar"/>.
848 /// </para>
849 /// <seealso cref="T:CCFixed"/>
850 /// </remarks>
851 internal class CCJulianCalendar {
852         /// <summary>An integer defining the epoch of the Julian calendar
853         /// as fixed day number.</summary>
854         /// <remarks>The epoch is December 30, 0 (Gregorian).</remarks>
855         const int epoch = -1; // 30. 12. 0 Gregorian
856
857         /// <summary>The enumeration defines the months of the Julian
858         /// calendar.
859         /// </summary>
860         public enum Month {
861                 /// <summary>
862                 /// January.
863                 /// </summary>
864                 january = 1,
865                 /// <summary>
866                 /// February.
867                 /// </summary>
868                 february,
869                 /// <summary>
870                 /// March.
871                 /// </summary>
872                 march,
873                 /// <summary>
874                 /// April.
875                 /// </summary>
876                 april,
877                 /// <summary>
878                 /// May.
879                 /// </summary>
880                 may,
881                 /// <summary>
882                 /// June.
883                 /// </summary>
884                 june,
885                 /// <summary>
886                 /// July.
887                 /// </summary>
888                 july,
889                 /// <summary>
890                 /// August.
891                 /// </summary>
892                 august,
893                 /// <summary>
894                 /// September.
895                 /// </summary>
896                 september,
897                 /// <summary>
898                 /// October.
899                 /// </summary>
900                 october,
901                 /// <summary>
902                 /// November.
903                 /// </summary>
904                 november,
905                 /// <summary>
906                 /// December.
907                 /// </summary>
908                 december
909         };
910
911         /// <summary>
912         /// The method tells whether the year is a leap year.
913         /// </summary>
914         /// <param name="year">An integer representing the Julian year.
915         /// </param>
916         /// <returns>A boolean which is true if <paramref name="year"/> is
917         /// a leap year.
918         /// </returns>
919         public static bool is_leap_year(int year) {
920                 return CCMath.mod(year, 4) == (year > 0 ? 0 : 3);
921         }
922
923         /// <summary>
924         /// The method returns the fixed day number of the given Julian
925         /// date.
926         /// </summary>
927         /// <param name="day">An integer representing the day of the month,
928         /// counting from 1.
929         /// </param>
930         /// <param name="month">An integer representing the month in the
931         /// Julian year.
932         /// </param>
933         /// <param name="year">An integer representing the Julian year.
934         /// Positive and Negative values are allowed.
935         /// </param>
936         /// <returns>An integer value representing the fixed day number.
937         /// </returns>
938         public static int fixed_from_dmy(int day, int month, int year) {
939                 int y = year < 0 ? year+1 : year;
940                 int k = epoch - 1;
941                 k += 365 * (y-1);
942                 k += CCMath.div(y-1, 4);
943                 k += CCMath.div(367*month-362, 12);
944                 if (month > 2) {
945                         k += is_leap_year(year) ? -1 : -2;
946                 }
947                 k += day;
948
949                 return k;
950         }
951
952         /// <summary>
953         /// The method computes the Julian year from a fixed day number.
954         /// </summary>
955         /// <param name="date">The fixed day number.
956         /// </param>
957         /// <returns>An integer value giving the Julian year of the date.
958         /// </returns>
959         public static int year_from_fixed(int date) {
960                 int approx = CCMath.div(4*(date-epoch)+1464, 1461);
961                 return approx <= 0 ? approx - 1 : approx;
962         }
963
964         /// <summary>
965         /// The method computes the Julian year and month from a fixed day
966         /// number.
967         /// </summary>
968         /// <param name="month">The output value giving the Julian month.
969         /// </param>
970         /// <param name="year">The output value giving the Julian year.
971         /// </param>
972         /// <param name="date">An integer value specifying the fixed day
973         /// number.</param>
974         public static void my_from_fixed(out int month, out int year, int date)
975         {
976                 year = year_from_fixed(date);
977
978                 int prior_days = date - fixed_from_dmy(1, (int)Month.january,
979                         year);
980                 
981                 int correction;
982                 if (date < fixed_from_dmy(1, (int)Month.march, year)) {
983                         correction = 0;
984                 } else if (is_leap_year(year)) {
985                         correction = 1;
986                 } else {
987                         correction = 2;
988                 }
989
990                 month = CCMath.div(12 * (prior_days + correction) + 373, 367);
991         }
992         
993
994         /// <summary>
995         /// The method computes the Julian year, month, and day from a
996         /// fixed day number.
997         /// </summary>
998         /// <param name="day">The output value returning the day of the
999         /// month.
1000         /// </param>
1001         /// <param name="month">The output value giving the Julian month.
1002         /// </param>
1003         /// <param name="year">The output value giving the Julian year.
1004         /// </param>
1005         /// <param name="date">An integer value specifying the fixed day
1006         /// number.</param>
1007         public static void dmy_from_fixed(out int day, out int month,
1008                 out int year, int date)
1009         {
1010                 my_from_fixed(out month, out year, date);
1011                 day = date - fixed_from_dmy(1, month, year) + 1;
1012         }
1013
1014         /// <summary>A method computing the Julian month from a fixed
1015         /// day number.
1016         /// </summary>
1017         /// <param name="date">An integer specifying the fixed day number.
1018         /// </param>
1019         /// <returns>An integer value representing the Julian month.
1020         /// </returns>
1021         public static int month_from_fixed(int date) {
1022                 int month, year;
1023
1024                 my_from_fixed(out month, out year, date);
1025                 return month;
1026         }
1027
1028         /// <summary>
1029         /// A method computing the day of the month from a fixed day number.
1030         /// </summary>
1031         /// <param name="date">An integer specifying the fixed day number.
1032         /// </param>
1033         /// <returns>An integer value representing the day of the month.
1034         /// </returns>
1035         public static int day_from_fixed(int date) {
1036                 int day;
1037                 int month;
1038                 int year;
1039
1040                 dmy_from_fixed(out day, out month, out year, date);
1041                 return day;
1042         }
1043
1044         /// <summary>
1045         /// The method computes the difference between two Julian dates.
1046         /// </summary>
1047         /// <param name="dayA">The integer parameter gives the day of month
1048         /// of the first date.
1049         /// </param>
1050         /// <param name="monthA">The integer parameter gives the Julian
1051         /// month of the first date.
1052         /// </param>
1053         /// <param name="yearA">The integer parameter gives the Julian
1054         /// year of the first date.
1055         /// </param>
1056         /// <param name="dayB">The integer parameter gives the day of month
1057         /// of the second date.
1058         /// </param>
1059         /// <param name="monthB">The integer parameter gives the Julian
1060         /// month of the second date.
1061         /// </param>
1062         /// <param name="yearB">The integer parameter gives the Julian
1063         /// year of the second date.
1064         /// </param>
1065         /// <returns>An integer giving the difference of days from the first
1066         /// the second date.
1067         /// </returns>
1068         public static int date_difference(int dayA, int monthA, int yearA,
1069                 int dayB, int monthB, int yearB)
1070         {
1071                 return  fixed_from_dmy(dayB, monthB, yearB) -
1072                         fixed_from_dmy(dayA, monthA, yearA);
1073         }
1074
1075         /// <summary>
1076         /// The method computes the number of the day in the year from
1077         /// a Julian date.
1078         /// </summary>
1079         /// <param name="day">An integer representing the day of the month,
1080         /// counting from 1.
1081         /// </param>
1082         /// <param name="month">An integer representing the month in the
1083         /// Julian year.
1084         /// </param>
1085         /// <param name="year">An integer representing the Julian year.
1086         /// Negative values are allowed also.
1087         /// </param>
1088         /// <returns>An integer value giving the number of the day in the
1089         /// Julian year, counting from 1.
1090         /// </returns>
1091         public static int day_number(int day, int month, int year) {
1092                 return date_difference(31, (int)Month.december, year-1,
1093                         day, month, year);
1094         }
1095
1096         /// <summary>
1097         /// The method computes the days remaining in the given Julian
1098         /// year from a Julian date.
1099         /// </summary>
1100         /// <param name="day">An integer representing the day of the month,
1101         /// counting from 1.
1102         /// </param>
1103         /// <param name="month">An integer representing the month in the
1104         /// Julian year.
1105         /// </param>
1106         /// <param name="year">An integer representing the Julian year.
1107         /// Negative values are allowed also.
1108         /// </param>
1109         /// <returns>An integer value giving the number of days remaining in
1110         /// the Julian year.
1111         /// </returns>
1112         public static int days_remaining(int day, int month, int year) {
1113                 return date_difference(day, month, year,
1114                         31, (int)Month.december, year);
1115         }
1116 } // class CCJulianCalendar
1117
1118 /// <summary>
1119 /// A class encapsulating the functions of the Hebrew calendar as static
1120 /// methods.
1121 /// </summary>
1122 /// <remarks>
1123 /// <para>
1124 /// This class is not compatible to
1125 /// <see cref="T:System.Globalization.HebrewCalendar"/>.
1126 /// </para>
1127 /// <seealso cref="T:CCFixed"/>
1128 /// </remarks>
1129 internal class CCHebrewCalendar {
1130         /// <summary>An integer defining the epoch of the Hebrew calendar
1131         /// as fixed day number.</summary>
1132         /// <remarks>The epoch is October 10, 3761 B.C.E. (Julian).</remarks>
1133         const int epoch = -1373427;
1134
1135         /// <summary>The enumeration defines the months of the Gregorian
1136         /// calendar.
1137         /// </summary>
1138         /// <remarks>
1139         /// The enumaration differs from .NET which defines Tishri as month 1.
1140         /// </remarks>
1141         public enum Month {
1142                 /// <summary>
1143                 /// Nisan.
1144                 /// </summary>
1145                 nisan    = 1,
1146                 /// <summary>
1147                 /// Iyyar.
1148                 /// </summary>
1149                 iyyar,
1150                 /// <summary>
1151                 /// Sivan.
1152                 /// </summary>
1153                 sivan,
1154                 /// <summary>
1155                 /// Tammuz.
1156                 /// </summary>
1157                 tammuz,
1158                 /// <summary>
1159                 /// Av.
1160                 /// </summary>
1161                 av,
1162                 /// <summary>
1163                 /// Elul.
1164                 /// </summary>
1165                 elul,
1166                 /// <summary>
1167                 /// Tishri.
1168                 /// </summary>
1169                 tishri,
1170                 /// <summary>
1171                 /// Heshvan.
1172                 /// </summary>
1173                 heshvan,
1174                 /// <summary>
1175                 /// Kislev.
1176                 /// </summary>
1177                 kislev,
1178                 /// <summary>
1179                 /// Teveth.
1180                 /// </summary>
1181                 teveth,
1182                 /// <summary>
1183                 /// Shevat.
1184                 /// </summary>
1185                 shevat,
1186                 /// <summary>
1187                 /// Adar.
1188                 /// </summary>
1189                 adar,
1190                 /// <summary>
1191                 /// Adar I. Only in years with Adar II.
1192                 /// </summary>
1193                 adar_I = 12,
1194                 /// <summary>
1195                 /// Adar II. Only in years wirh Adar I.
1196                 /// </summary>
1197                 adar_II = 13,
1198         };
1199
1200         /// <summary>
1201         /// The method tells whether the year is a leap year.
1202         /// </summary>
1203         /// <param name="year">An integer representing the Hebrew year.
1204         /// </param>
1205         /// <returns>A boolean which is true if <paramref name="year"/> is
1206         /// a leap year.
1207         /// </returns>
1208         public static bool is_leap_year(int year) {
1209                 return CCMath.mod(7*year+1, 19) < 7; 
1210         }
1211
1212         /// <summary>
1213         /// The Method gives the number of the last month in a year, which
1214         /// is equal with the number of month in a Hebrew year.
1215         /// </summary>
1216         /// <param name="year">An integer representing the Hebrew year.
1217         /// </param>
1218         /// <returns>An integer giving the number of the last month of the 
1219         /// Hebrew year, which is the same as the numbers of month in the
1220         /// year.
1221         /// </returns>
1222         public static int last_month_of_year(int year) {
1223                 return is_leap_year(year) ? 13 : 12;
1224         }
1225
1226         
1227         /// <summary>The method is a helper function.</summary>
1228         /// <param name="year">An integer specifying the Hebrew year.
1229         /// </param>
1230         /// <returns>An integer representing the number of elapsed days
1231         /// until the Hebrew year.</returns>
1232         public static int elapsed_days(int year) {
1233                 int months_elapsed = CCMath.div(235*year-234, 19);
1234                 int r;
1235                 int d = CCMath.div_mod(out r, months_elapsed, 1080);
1236                 int parts_elapsed = 204 + 793 * r;
1237                 int hours_elapsed = 11 + 12 * months_elapsed +
1238                                     793 * d + CCMath.div(parts_elapsed, 1080);
1239
1240                 int day = 29*months_elapsed + CCMath.div(hours_elapsed, 24);
1241
1242                 if (CCMath.mod(3*(day+1), 7) < 3) {
1243                         day += 1;
1244                 }
1245
1246                 return day;
1247         }
1248
1249         /// <summary>A method computing the delay of new year for the given
1250         /// Hebrew year.
1251         /// </summary>
1252         /// <param name="year">An integer that gives the Hebrew year.
1253         /// </param>
1254         /// <returns>The new year delay in days of the given Hebrew year.
1255         /// </returns>
1256         public static int new_year_delay(int year) {
1257                 int ny1 = elapsed_days(year);
1258                 int ny2 = elapsed_days(year+1);
1259
1260                 if (ny2 - ny1 == 356) {
1261                         return 2;
1262                 }
1263                 int ny0 = elapsed_days(year-1);
1264                 if (ny1 - ny0 == 382) {
1265                         return 1;
1266                 }
1267                 return 0;
1268         }
1269
1270         /// <summary>
1271         /// The method computes the last day of month (nummer of days in a
1272         /// month) of the given Hebrew year.
1273         /// </summary>
1274         /// <param name="month">The Hebrew month, allowed value between
1275         /// One and Thirteen.
1276         /// </param>
1277         /// <param name="year">An integer that gives the Hebrew year.
1278         /// </param>
1279         /// <returns>The number of the last day of the month of the given
1280         /// Hebrew year, which gives automatically the number of days in the
1281         /// month.
1282         /// </returns>
1283         /// <exception cref="T:System.ArgumentOutOfRange.Exception">
1284         /// The exception is thrown if month not between One and Thirteen.
1285         /// </exception>
1286         public static int last_day_of_month(int month, int year) {
1287                 if (month < 1 || month > 13)
1288                         throw new System.ArgumentOutOfRangeException("month",
1289                                 "Month should be between One and Thirteen.");
1290                 switch (month) {
1291                         case 2: return 29;
1292                         case 4: return 29;
1293                         case 6: return 29;
1294                         case 8:
1295                                 if (!long_heshvan(year))
1296                                         return 29;
1297                                 break;
1298                         case 9:
1299                                 if (short_kislev(year))
1300                                         return 29;
1301                                 break;
1302                         case 10: return 29;
1303                         case 12:
1304                                 if (!is_leap_year(year))
1305                                         return 29;
1306                                 break;
1307                         case 13: return 29;
1308                 }
1309                 return 30;
1310         }
1311         
1312         /// <summary>
1313         /// The functions checks whether the month Heshvan is a long one
1314         /// in the given Hebrew year.
1315         /// </summary>
1316         /// <param name="year">An integer that gives the Hebrew year.
1317         /// </param>
1318         /// <returns>A boolean value: true if there is a long Heshvan
1319         /// in the given Hebrew year; false otherwise.
1320         /// </returns>
1321         public static bool long_heshvan(int year) {
1322                 return CCMath.mod(days_in_year(year), 10) == 5;
1323         }
1324
1325         /// <summary>
1326         /// The functions checks whether the month Kislev is a short one
1327         /// in the given Hebrew year.
1328         /// </summary>
1329         /// <param name="year">An integer that gives the Hebrew year.
1330         /// </param>
1331         /// <returns>A boolean value: true if there is a short Kislev
1332         /// in the given Hebrew year; false otherwise.
1333         /// </returns>
1334         public static bool short_kislev(int year) {
1335                 return CCMath.mod(days_in_year(year), 10) == 3;
1336         }
1337
1338         /// <summary>
1339         /// The functions gives the number of days in the specified Hebrew
1340         /// year.
1341         /// </summary>
1342         /// <param name="year">An integer that gives the Hebrew year.
1343         /// </param>
1344         /// <returns>The days of the Hebrew year as integer.
1345         /// </returns>
1346         public static int days_in_year(int year) {
1347                 return  fixed_from_dmy(1, 7, year+1) -
1348                         fixed_from_dmy(1, 7, year);
1349         }
1350
1351         /// <summary>
1352         /// The method returns the fixed day number of the given Hebrew
1353         /// date.
1354         /// </summary>
1355         /// <param name="day">An integer representing the day of the month,
1356         /// counting from 1.
1357         /// </param>
1358         /// <param name="month">An integer representing the month in the
1359         /// Hebrew year.
1360         /// </param>
1361         /// <param name="year">An integer representing the Hebrew year.
1362         /// Non-positive values are allowed also.
1363         /// </param>
1364         /// <returns>An integer value representing the fixed day number.
1365         /// </returns>
1366         public static int fixed_from_dmy(int day, int month, int year) {
1367                 int m;
1368                 int k = epoch-1;
1369                 k += elapsed_days(year);
1370                 k += new_year_delay(year);
1371
1372                 if (month < 7) {
1373                         int l = last_month_of_year(year);
1374                         for (m = 7; m <= l; m++) {
1375                                 k += last_day_of_month(m, year);
1376                         }
1377                         for (m = 1; m < month; m++) {
1378                                 k += last_day_of_month(m, year);
1379                         }
1380                 }
1381                 else {
1382                         for (m = 7; m < month; m++) {
1383                                 k += last_day_of_month(m, year);
1384                         }
1385                 }
1386                 
1387                 k += day;
1388
1389                 return k;
1390         }
1391
1392         /// <summary>
1393         /// The method computes the Hebrew year from a fixed day number.
1394         /// </summary>
1395         /// <param name="date">The fixed day number.
1396         /// </param>
1397         /// <returns>An integer value giving the Hebrew year of the date.
1398         /// </returns>
1399         public static int year_from_fixed(int date) {
1400                 int approx = (int)System.Math.Floor(
1401                         ((double)(date - epoch))/(35975351.0/98496.0));
1402                 int y;
1403                 for (y = approx; date >= fixed_from_dmy(1, 7, y); y++) {} 
1404                 return y-1;
1405         }
1406
1407         /// <summary>
1408         /// The method computes the Hebrew year and month from a fixed day
1409         /// number.
1410         /// </summary>
1411         /// <param name="month">The output value giving the Hebrew month.
1412         /// </param>
1413         /// <param name="year">The output value giving the Hebrew year.
1414         /// </param>
1415         /// <param name="date">An integer value specifying the fixed day
1416         /// number.</param>
1417         public static void my_from_fixed(out int month, out int year,
1418                 int date)
1419         {
1420                 year = year_from_fixed(date);
1421
1422                 int start = date < fixed_from_dmy(1, 1, year) ? 7 : 1;
1423
1424                 for (month = start;
1425                      date > fixed_from_dmy(last_day_of_month(month, year),
1426                                                 month, year);
1427                      month++)
1428                 {}
1429         }
1430
1431         /// <summary>
1432         /// The method computes the Hebrew year, month, and day from a
1433         /// fixed day number.
1434         /// </summary>
1435         /// <param name="day">The output value returning the day of the
1436         /// month.
1437         /// </param>
1438         /// <param name="month">The output value giving the Hebrew month.
1439         /// </param>
1440         /// <param name="year">The output value giving the Hebrew year.
1441         /// </param>
1442         /// <param name="date">An integer value specifying the fixed day
1443         /// number.</param>
1444         public static void dmy_from_fixed(out int day, out int month,
1445                 out int year, int date)
1446         {
1447                 my_from_fixed(out month, out year, date);
1448                 day = date - fixed_from_dmy(1, month, year) + 1;
1449         }
1450
1451         /// <summary>A method computing the Hebrew month from a fixed
1452         /// day number.
1453         /// </summary>
1454         /// <param name="date">An integer specifying the fixed day number.
1455         /// </param>
1456         /// <returns>An integer value representing the Hebrew month.
1457         /// </returns>
1458         public static int month_from_fixed(int date) {
1459                 int month, year;
1460
1461                 my_from_fixed(out month, out year, date);
1462                 return month;
1463         }
1464
1465         /// <summary>
1466         /// A method computing the day of the month from a fixed day number.
1467         /// </summary>
1468         /// <param name="date">An integer specifying the fixed day number.
1469         /// </param>
1470         /// <returns>An integer value representing the day of the month.
1471         /// </returns>
1472         public static int day_from_fixed(int date) {
1473                 int day, month, year;
1474                 
1475                 dmy_from_fixed(out day, out month, out year, date);
1476                 return day;
1477         }
1478
1479         /// <summary>
1480         /// The method computes the difference between two Hebrew dates.
1481         /// </summary>
1482         /// <param name="dayA">The integer parameter gives the day of month
1483         /// of the first date.
1484         /// </param>
1485         /// <param name="monthA">The integer parameter gives the Hebrew
1486         /// month of the first date.
1487         /// </param>
1488         /// <param name="yearA">The integer parameter gives the Hebrew
1489         /// year of the first date.
1490         /// </param>
1491         /// <param name="dayB">The integer parameter gives the day of month
1492         /// of the second date.
1493         /// </param>
1494         /// <param name="monthB">The integer parameter gives the Hebrew
1495         /// month of the second date.
1496         /// </param>
1497         /// <param name="yearB">The integer parameter gives the Hebrew
1498         /// year of the second date.
1499         /// </param>
1500         /// <returns>An integer giving the difference of days from the first
1501         /// the second date.
1502         /// </returns>
1503         public static int date_difference(int dayA, int monthA, int yearA,
1504                 int dayB, int monthB, int yearB)
1505         {
1506                 return  fixed_from_dmy(dayB, monthB, yearB) -
1507                         fixed_from_dmy(dayA, monthA, yearA);
1508         }
1509
1510         /// <summary>
1511         /// The method computes the number of the day in the year from
1512         /// a Hebrew date.
1513         /// </summary>
1514         /// <param name="day">An integer representing the day of the month,
1515         /// counting from 1.
1516         /// </param>
1517         /// <param name="month">An integer representing the month in the
1518         /// Hebrew year.
1519         /// </param>
1520         /// <param name="year">An integer representing the Hebrew year.
1521         /// </param>
1522         /// <returns>An integer value giving the number of the day in the
1523         /// Hebrew year, counting from 1.
1524         /// </returns>
1525         public static int day_number(int day, int month, int year) {
1526                 return date_difference(1, 7, year,
1527                         day, month, year) + 1;
1528         }
1529
1530         /// <summary>
1531         /// The method computes the days remaining in the given Hebrew
1532         /// year from a Hebrew date.
1533         /// </summary>
1534         /// <param name="day">An integer representing the day of the month,
1535         /// counting from 1.
1536         /// </param>
1537         /// <param name="month">An integer representing the month in the
1538         /// Hebrew year.
1539         /// </param>
1540         /// <param name="year">An integer representing the Hebrew year.
1541         /// </param>
1542         /// <returns>An integer value giving the number of days remaining in
1543         /// the Hebrew year.
1544         /// </returns>
1545         public static int days_remaining(int day, int month, int year) {
1546                 return date_difference(day, month, year,
1547                         1, 7, year+1)-1;
1548         }
1549 } // class HebrewCalendar
1550
1551
1552 /// <summary>
1553 /// A class encapsulating the functions of the Islamic calendar as static
1554 /// methods.
1555 /// </summary>
1556 /// <remarks>
1557 /// <para>There is no difference here in using Hijri or Islamic calendar.
1558 /// </para>
1559 /// <para>The epoch of the Islamic calendar isn't fixed, because we cannot
1560 /// surely say today, when the crescent of the new moon has been observed 
1561 /// around the July 16, 622 C.E. Julian. Even today the start and end of 
1562 /// the month Ramadan is defined by religous authorities. So the calendar
1563 /// can be offset by two days.
1564 /// </para> 
1565 /// <para>
1566 /// We don't support the offset here, however we changed the epoch from
1567 /// "Calendrical Calculations" to value, that .Net seems to be using.
1568 /// </para>
1569 /// <para>
1570 /// This class is not compatible to
1571 /// <see cref="T:System.Globalization.HijriCalendar"/>.
1572 /// </para>
1573 /// <seealso cref="T:CCFixed"/>
1574 /// </remarks>
1575 internal class CCHijriCalendar {
1576         /// <summary>An integer defining the epoch of the Gregorian calendar
1577         /// as fixed day number.</summary>
1578         /// <remarks>
1579         /// <para>
1580         /// The epoch is given as 16 July 622 C.E. Julian (R.D. 227015)
1581         /// in Calendrical Calculations, the approximate date of
1582         /// the emigration of
1583         /// Muhammed to Medina. However there is no way to determine today
1584         /// the observation of the crescent of the new moon in July 622 C.E.
1585         /// (Julian). So there is some variability in the epoch.
1586         /// Religous authorities determine the epoch by observing the
1587         /// crescent of the new moon for the month Ramadan, so there might
1588         /// be an offsets by two days of the epoch.
1589         /// </para>
1590         /// <para>Windows
1591         /// supports an AddHijriDate parameter in the registry to adapt
1592         /// for it. It seems that the .NET implementation of
1593         /// HijriCalendar uses an epoch of 227014, so we use it here. The
1594         /// ArgumentOutOfRangeException gives July, 18 622 as epoch,
1595         /// which is 227014 supporting our theory.
1596         /// </para>
1597         /// </remarks>
1598         const int epoch = 227014;
1599
1600         /// <summary>The enumeration defines the months of the Islamic
1601         /// calendar.
1602         /// </summary>
1603         public enum Month {
1604                 /// <summary>
1605                 /// Muharram.
1606                 /// </summary>
1607                 muharram = 1,
1608                 /// <summary>
1609                 /// Safar.
1610                 /// </summary>
1611                 safar,
1612                 /// <summary>
1613                 /// Rabi I.
1614                 /// </summary>
1615                 rabi_I,
1616                 /// <summary>
1617                 /// Rabi II.
1618                 /// </summary>
1619                 rabi_II,
1620                 /// <summary>
1621                 /// Jumada I.
1622                 /// </summary>
1623                 jumada_I,
1624                 /// <summary>
1625                 /// Jumada II.
1626                 /// </summary>
1627                 jumada_II,
1628                 /// <summary>
1629                 /// Rajab.
1630                 /// </summary>
1631                 rajab,
1632                 /// <summary>
1633                 /// Shaban.
1634                 /// </summary>
1635                 shaban,
1636                 /// <summary>
1637                 /// Ramadan.
1638                 /// </summary>
1639                 ramadan,
1640                 /// <summary>
1641                 /// Shawwal.
1642                 /// </summary>
1643                 shawwal,
1644                 /// <summary>
1645                 /// Dhu Al-Quada.
1646                 /// </summary>
1647                 dhu_al_quada,
1648                 /// <summary>
1649                 /// Dhu Al-Hijja.
1650                 /// </summary>
1651                 dhu_al_hijja,
1652         };
1653
1654         /// <summary>
1655         /// The method tells whether the year is a leap year.
1656         /// </summary>
1657         /// <param name="year">An integer representing the Islamic year.
1658         /// </param>
1659         /// <returns>A boolean which is true if <paramref name="year"/> is
1660         /// a leap year.
1661         /// </returns>
1662         public static bool is_leap_year(int year) {
1663                 return CCMath.mod(14+11*year, 30) < 11;
1664         }
1665
1666         /// <summary>
1667         /// The method returns the fixed day number of the given Islamic
1668         /// date.
1669         /// </summary>
1670         /// <param name="day">An integer representing the day of the month,
1671         /// counting from 1.
1672         /// </param>
1673         /// <param name="month">An integer representing the month in the
1674         /// Islamic year.
1675         /// </param>
1676         /// <param name="year">An integer representing the Islamic year.
1677         /// Non-positive values are allowed also.
1678         /// </param>
1679         /// <returns>An integer value representing the fixed day number.
1680         /// </returns>
1681         public static int fixed_from_dmy(int day, int month, int year) {
1682                 int k = epoch - 1;
1683                 k += 354 * (year-1);
1684                 k += CCMath.div(3+11*year, 30);
1685                 k += (int)System.Math.Ceiling(29.5 * (double)(month-1));
1686                 k += day;
1687
1688                 return k;
1689         }
1690
1691         /// <summary>
1692         /// The method computes the Islamic year from a fixed day number.
1693         /// </summary>
1694         /// <param name="date">The fixed day number.
1695         /// </param>
1696         /// <returns>An integer value giving the Islamic year of the date.
1697         /// </returns>
1698         public static int year_from_fixed(int date) {
1699                 return CCMath.div(30*(date-epoch)+10646, 10631);
1700         }
1701
1702         /// <summary>
1703         /// The method computes the Islamic year and month from a fixed day
1704         /// number.
1705         /// </summary>
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 my_from_fixed(out int month, out int year, int date)
1713         {
1714                 year = year_from_fixed(date);
1715
1716                 int m = 1+(int)System.Math.Ceiling(
1717                         ((double)(date-29-fixed_from_dmy(1,1,year)))/29.5);
1718
1719                 month = m < 12 ? m : 12;
1720         }
1721         
1722         /// <summary>
1723         /// The method computes the Islamic year, month, and day from a
1724         /// fixed day number.
1725         /// </summary>
1726         /// <param name="day">The output value returning the day of the
1727         /// month.
1728         /// </param>
1729         /// <param name="month">The output value giving the Islamic month.
1730         /// </param>
1731         /// <param name="year">The output value giving the Islamic year.
1732         /// </param>
1733         /// <param name="date">An integer value specifying the fixed day
1734         /// number.</param>
1735         public static void dmy_from_fixed(out int day, out int month,
1736                 out int year, int date)
1737         {
1738                 my_from_fixed(out month, out year, date);
1739                 day = date - fixed_from_dmy(1, month, year) + 1;
1740         }
1741
1742         /// <summary>A method computing the Islamic month from a fixed
1743         /// day number.
1744         /// </summary>
1745         /// <param name="date">An integer specifying the fixed day number.
1746         /// </param>
1747         /// <returns>An integer value representing the Islamic month.
1748         /// </returns>
1749         public static int month_from_fixed(int date) {
1750                 int month, year;
1751
1752                 my_from_fixed(out month, out year, date);
1753                 return month;
1754         }
1755
1756         /// <summary>
1757         /// A method computing the day of the month from a fixed day number.
1758         /// </summary>
1759         /// <param name="date">An integer specifying the fixed day number.
1760         /// </param>
1761         /// <returns>An integer value representing the day of the month.
1762         /// </returns>
1763         public static int day_from_fixed(int date) {
1764                 int day;
1765                 int month;
1766                 int year;
1767
1768                 dmy_from_fixed(out day, out month, out year, date);
1769                 return day;
1770         }
1771
1772         /// <summary>
1773         /// The method computes the difference between two Islamic dates.
1774         /// </summary>
1775         /// <param name="dayA">The integer parameter gives the day of month
1776         /// of the first date.
1777         /// </param>
1778         /// <param name="monthA">The integer parameter gives the Islamic
1779         /// month of the first date.
1780         /// </param>
1781         /// <param name="yearA">The integer parameter gives the Islamic
1782         /// year of the first date.
1783         /// </param>
1784         /// <param name="dayB">The integer parameter gives the day of month
1785         /// of the second date.
1786         /// </param>
1787         /// <param name="monthB">The integer parameter gives the Islamic
1788         /// month of the second date.
1789         /// </param>
1790         /// <param name="yearB">The integer parameter gives the Islamic
1791         /// year of the second date.
1792         /// </param>
1793         /// <returns>An integer giving the difference of days from the first
1794         /// the second date.
1795         /// </returns>
1796         public static int date_difference(int dayA, int monthA, int yearA,
1797                 int dayB, int monthB, int yearB)
1798         {
1799                 return  fixed_from_dmy(dayB, monthB, yearB) -
1800                         fixed_from_dmy(dayA, monthA, yearA);
1801         }
1802
1803         /// <summary>
1804         /// The method computes the number of the day in the year from
1805         /// a Islamic date.
1806         /// </summary>
1807         /// <param name="day">An integer representing the day of the month,
1808         /// counting from 1.
1809         /// </param>
1810         /// <param name="month">An integer representing the month in the
1811         /// Islamic year.
1812         /// </param>
1813         /// <param name="year">An integer representing the Islamic year.
1814         /// </param>
1815         /// <returns>An integer value giving the number of the day in the
1816         /// Islamic year, counting from 1.
1817         /// </returns>
1818         public static int day_number(int day, int month, int year) {
1819                 return date_difference(31, 12, year-1, day, month, year);
1820         }
1821
1822         /// <summary>
1823         /// The method computes the days remaining in the given Islamic
1824         /// year from a Islamic date.
1825         /// </summary>
1826         /// <param name="day">An integer representing the day of the month,
1827         /// counting from 1.
1828         /// </param>
1829         /// <param name="month">An integer representing the month in the
1830         /// Islamic year.
1831         /// </param>
1832         /// <param name="year">An integer representing the Islamic year.
1833         /// Non-positive values are allowed also.
1834         /// </param>
1835         /// <returns>An integer value giving the number of days remaining in
1836         /// the Islamic year.
1837         /// </returns>
1838         public static int days_remaining(int day, int month, int year) {
1839                 return date_difference(day, month, year,31, 12, year);
1840         }
1841 } // class CCHijriCalendar
1842
1843 /// <summary>
1844 /// A class that supports the Gregorian based calendars with other eras
1845 /// (e.g. <see cref="T:System.Gloablization.JapaneseCalendar"/>).
1846 /// </summary>
1847 [System.Serializable]
1848 internal class CCGregorianEraHandler {
1849         /// <summary>
1850         /// A struct that represents a single era.
1851         /// </summary>
1852         [System.Serializable]
1853         struct Era {
1854                 /// <summary>
1855                 /// The integer number identifying the era.
1856                 /// </summary>
1857                 private int _nr;
1858
1859                 /// <value>
1860                 /// A get-only property that gives the era integer number.
1861                 /// </value>
1862                 public int Nr { get { return _nr; } }
1863
1864                 /// <summary>This integer gives the first day of the era as
1865                 /// fixed day number.
1866                 /// </summary>
1867                 private int _start; // inclusive
1868                 /// <summary>
1869                 /// This integer gives the gregorian year of the
1870                 /// <see cref="M:_start"/> value.
1871                 /// </summary>
1872                 private int _gregorianYearStart;
1873                 /// <summary>
1874                 /// This integer gives the last day of the era as fixed day
1875                 /// number.
1876                 /// </summary>
1877                 private int _end;   // inclusive        
1878                 /// <summary>
1879                 /// This integer gives the largest year number of this era.
1880                 /// </summary>
1881                 private int _maxYear;
1882
1883                 /// <summary>
1884                 /// This constructor creates the era structure.
1885                 /// </summary>
1886                 /// <param name="nr">The integer number of the era.
1887                 /// </param>
1888                 /// <param name="start">The fixed day number defining the
1889                 /// first day of the era.
1890                 /// </param>
1891                 /// <param name="end">The fixed day number that defines the
1892                 /// last day of the era.
1893                 /// </param>
1894                 public Era(int nr, int start, int end) {
1895                         if (nr == 0)
1896                                 throw new System.ArgumentException(
1897                                         "Era number shouldn't be zero.");
1898                         _nr = nr;
1899                         if (start > end) {
1900                                 throw new System.ArgumentException(
1901                                         "Era should start before end.");
1902                         }
1903                         _start = start;
1904                         _end = end;
1905
1906                         _gregorianYearStart =
1907                                 CCGregorianCalendar.year_from_fixed(_start);
1908                         int gregorianYearEnd =
1909                                 CCGregorianCalendar.year_from_fixed(_end);
1910                         _maxYear = gregorianYearEnd - _gregorianYearStart + 1;
1911                 }
1912
1913                 /// <summary>
1914                 /// This method computes the Gregorian year from the year
1915                 /// of this era.
1916                 /// </summary>
1917                 /// <param name="year">An integer giving the year in the
1918                 /// era.
1919                 /// </param>
1920                 /// <returns>
1921                 /// The Gregorian year as integer.
1922                 /// </returns>
1923                 /// <exception cref="T:System.ArgumentOutOfRangeException">
1924                 /// The exception is thrown if the year isn't valid in this
1925                 /// era.
1926                 /// </exception>
1927                 public int GregorianYear(int year) {
1928                         if (year < 1 || year > _maxYear) {
1929                                 System.IO.StringWriter sw = 
1930                                         new System.IO.StringWriter();
1931                                 sw.Write(
1932                                         "Valid Values are between " +
1933                                         "{0} and {1}, inclusive.",
1934                                         1, _maxYear);
1935                                 throw new System.ArgumentOutOfRangeException(
1936                                         "year", sw.ToString());
1937                         }
1938                         return year + _gregorianYearStart - 1;
1939                 }
1940
1941                 /// <summary>
1942                 /// This function checks wether the given fixed day number is
1943                 /// ion the time span of the era.
1944                 /// </summary>
1945                 /// <param name="date">An integer giving the fixed day
1946                 /// number.
1947                 /// </param>
1948                 /// <returns>A boolean: true if the argument is in the time
1949                 /// span of the era.
1950                 /// </returns>
1951                 public bool Covers(int date) {
1952                         return _start <= date && date <= _end;
1953                 }
1954
1955                 /// <summary>
1956                 /// This function returns the year of the era and sets
1957                 /// the era in an output parameter.
1958                 /// </summary>
1959                 /// <param name="era">An output parameter returning the
1960                 /// era number.
1961                 /// </param>
1962                 /// <param name="date">An integer giving the fixed day
1963                 /// number.
1964                 /// </param>
1965                 /// <returns>An integer giving the year of the era.
1966                 /// </returns>
1967                 /// <exception cref="T:System.ArgumentOutOfRangeException">
1968                 /// The exception is thrown if date is outside of the time
1969                 /// span of the era.
1970                 /// </exception>
1971                 public int EraYear(out int era, int date) {
1972                         if (!Covers(date))
1973                                 throw new System.ArgumentOutOfRangeException(
1974                                         "date", 
1975                                         "Time was out of Era range.");
1976                         int gregorianYear =
1977                                 CCGregorianCalendar.year_from_fixed(date);
1978                         era = _nr;
1979                         return gregorianYear - _gregorianYearStart + 1;
1980                 }
1981         } // struct Era
1982
1983         /// <summary>
1984         /// A private member storing the eras in a
1985         /// <see cref="T:System.Collections.SortedList"/>.
1986         /// </summary>
1987         private SortedList _Eras;
1988
1989         /// <value>
1990         /// The property returns the era numbers as an array of integers.
1991         /// </value>
1992         public int[] Eras {
1993                 get {
1994                         int[] a = new int[_Eras.Count];
1995
1996                         for (int i = 0; i < _Eras.Count; i++) {
1997                                 Era e = (Era)_Eras.GetByIndex(i);
1998                                 a[i] = e.Nr;
1999                         }
2000
2001                         return a;
2002                 }
2003         }
2004
2005         /// <summary>
2006         /// Constructor.
2007         /// </summary>
2008         public CCGregorianEraHandler() {
2009                 _Eras = new SortedList();
2010         }
2011
2012         /// <summary>
2013         /// Method adds an era to the GregorianEraHandler instance.
2014         /// </summary>
2015         /// <param name="nr">The integer number of the era.
2016         /// </param>
2017         /// <param name="rd_start">The fixed day number defining the
2018         /// first day of the era.
2019         /// </param>
2020         /// <param name="rd_end">The fixed day number that defines the
2021         /// last day of the era.
2022         /// </param>
2023         public void appendEra(int nr, int rd_start, int rd_end) {
2024                 Era era = new Era(nr, rd_start, rd_end);
2025                 _Eras[(System.Object)nr] = era;
2026         }
2027         /// <summary>
2028         /// Method adds a yet not-ended era to the GregorianEraHandler
2029         /// instance.
2030         /// </summary>
2031         /// <param name="nr">The integer number of the era.
2032         /// </param>
2033         /// <param name="rd_start">The fixed day number defining the
2034         /// first day of the era.
2035         /// </param>
2036         public void appendEra(int nr, int rd_start) {
2037                 appendEra(nr, rd_start,
2038                         CCFixed.FromDateTime(DateTime.MaxValue));
2039         }
2040
2041         /// <summary>
2042         /// This method computes the Gregorian year from the year
2043         /// of the given era.
2044         /// </summary>
2045         /// <param name="year">An integer giving the year in the
2046         /// era.
2047         /// </param>
2048         /// <param name="era">An integer giving the era number.
2049         /// </param>
2050         /// <returns>
2051         /// The Gregorian year as integer.
2052         /// </returns>
2053         /// <exception cref="T:System.ArgumentOutOfRangeException">
2054         /// The exception is thrown if the year isn't valid in this
2055         /// era.
2056         /// </exception>
2057         public int GregorianYear(int year, int era) {
2058                 Era e = (Era)_Eras[(System.Object)era];
2059                 return e.GregorianYear(year);
2060         }
2061
2062         /// <summary>
2063         /// This function returns the year of the era and sets
2064         /// the era in an output parameter.
2065         /// </summary>
2066         /// <param name="era">An output parameter returning the
2067         /// era number.
2068         /// </param>
2069         /// <param name="date">An integer giving the fixed day
2070         /// number.
2071         /// </param>
2072         /// <returns>An integer giving the year of the era.
2073         /// </returns>
2074         /// <exception cref="T:System.ArgumentOutOfRangeException">
2075         /// The exception is thrown if the fixed day number is outside of the
2076         /// time spans of all eras.
2077         /// </exception>
2078         public int EraYear(out int era, int date)
2079         {
2080                 IList list = _Eras.GetValueList();
2081
2082                 foreach (Era e in list) {
2083                         if (e.Covers(date))
2084                                 return e.EraYear(out era, date);
2085                 }
2086
2087                 throw new System.ArgumentOutOfRangeException("date",
2088                         "Time value was out of era range.");
2089         }
2090
2091         /// <summary>
2092         /// The method checks whether a given
2093         /// <see cref="T:System.DateTime"/> is covered by any era.
2094         /// </summary>
2095         /// <param name="time">A 
2096         /// <see cref="T:System.DateTime"/> giving the date and time.
2097         /// </param>
2098         /// <exception cref="T:System.ArgumentOutOfRangeException">
2099         /// The exception is thrown if the argument isn't inside the time
2100         /// span of any era.
2101         /// </exception>
2102         public void CheckDateTime(System.DateTime time) {
2103                 int date = CCFixed.FromDateTime(time);
2104
2105                 if (!ValidDate(date))
2106                         throw new System.ArgumentOutOfRangeException("time",
2107                                 "Time value was out of era range.");
2108         }
2109                 
2110         /// <summary>
2111         /// The method tests whether a given
2112         /// fixed day number is covered by any era.
2113         /// </summary>
2114         /// <param name="date">An integer representing the fixed day number.
2115         /// </param>
2116         /// <returns> A boolean is returned: true if the argument is inside
2117         /// the time span of one era; false otherwise.
2118         /// </returns>
2119         public bool ValidDate(int date) {
2120                 IList list = _Eras.GetValueList();
2121
2122                 foreach (Era e in list) {
2123                         if (e.Covers(date))
2124                                 return true;
2125                 }
2126
2127                 return false;
2128         }
2129
2130         /// <summary>
2131         /// The method tests, whether the era number does exist.
2132         /// </summary>
2133         /// <param name="era">An integer giving the era number.
2134         /// </param>
2135         /// <returns>A boole value: True if the era number does exist;
2136         /// false otherwise.
2137         /// </returns>
2138         public bool ValidEra(int era) {
2139                 return _Eras.Contains((System.Object)era);
2140         }
2141 } // class CCGregorianEraHandler
2142
2143 } // namespace System.Globalization