1 // CalendricalCalculations.cs
3 // (C) Ulrich Kunitz 2002
7 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
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:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
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.
29 namespace System.Globalization {
31 using System.Collections;
33 /// <summary>A class that provides mathematical functions.</summary>
36 /// We are breaking the .Net
37 /// naming conventions to be compatible to the "Calendrical Calculations"
43 /// A static method which rounds a double value.
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);
52 /// A static method that computes the remainder of the division
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);
63 /// The static method divides two integers.
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).
70 /// Please notify that the function is not compatible to the standard
71 /// integer divide operation /.
73 public static int div(int x, int y) {
74 return (int)System.Math.Floor((double)x/(double)y);
78 /// The static method computes the remainder of two integers.
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>
84 /// Please notify that the method is not compatible to the C#
85 /// remainder operation %.
87 public static int mod(int x, int y) {
88 return x - y * div(x, y);
92 /// A static method that combines integer division and remainder
95 /// <param name="remainder">Remainder integer output value.
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) {
104 remainder = x - y * d;
109 /// A static method returning the sign of the argument.
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.
115 public static int signum(double x) {
124 /// A static method returning the sign of the integer
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.
131 public static int signum(int x) {
140 /// An adjusted remainder function as defined in "Calendrical
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.
148 public static double amod(double x, double y) {
149 double d = mod(x, y);
150 return (d == 0.0) ? y : d;
154 /// The adjusted remainder functions for integers as defined in
155 /// "Calendrical Calculations".
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.
162 public static int amod(int x, int y) {
164 return (i == 0) ? y : i;
168 /// <summary>The class implements methods to handle the fixed date value from
169 /// the "Calendrical Calculations" books.
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.
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.
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>
201 static class CCFixed {
202 /// <summary>The method computes the
203 /// <see cref="T:System.DateTime"/>
204 /// from a fixed day number.
206 /// <param name="date">A integer representing the fixed day number.
208 /// <returns>The <see cref="T:System.DateTime"/> representing
211 public static System.DateTime ToDateTime(int date) {
212 long ticks = (date - 1) * System.TimeSpan.TicksPerDay;
213 return new System.DateTime(ticks);
216 /// <summary>The method computes the
217 /// <see cref="T:System.DateTime"/>
218 /// from a fixed day number and time arguments.
220 /// <param name="date">An integer representing the fixed day number.
222 /// <param name="hour">An integer argument specifying the hour.
224 /// <param name="minute">An integer argument specifying the minute.
226 /// <param name="second">An integer argument giving the second.
228 /// <param name="milliseconds">An double argument specifying
229 /// the milliseconds. Notice that
230 /// <see cref="T:System.DateTime"/> has 100 nanosecond resolution.
232 /// <returns>The <see cref="T:System.DateTime"/> representing
235 public static System.DateTime ToDateTime(int date,
236 int hour, int minute, int second, double milliseconds)
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);
246 /// A static method computing the fixed day number from a
247 /// <see cref="T:System.DateTime"/> value.
249 /// <param name="time">A
250 /// <see cref="T:System.DateTime"/> value representing the date.
252 /// <returns>The fixed day number as integer representing the date.
254 public static int FromDateTime(System.DateTime time) {
255 return 1 + (int)(time.Ticks / System.TimeSpan.TicksPerDay);
259 /// The static method computes the <see cref="T:DayOfWeek"/>.
261 /// <param name="date">An integer representing the fixed day number.
263 /// <returns>The day of week.</returns>
264 public static DayOfWeek day_of_week(int date) {
265 return (DayOfWeek)CCMath.mod(date, 7);
269 /// The static method computes the date of a day of week on or before
270 /// a particular date.
272 /// <param name="date">An integer representing the date as
273 /// fixed day number.
275 /// <param name="k">An integer representing the day of the week,
276 /// starting with 0 for sunday.
278 /// <returns>The fixed day number of the day of week specified by k
279 /// on or before the given date.
281 public static int kday_on_or_before(int date, int k) {
282 return date - (int)day_of_week(date-k);
286 /// The static method computes the date of a day of week on or after
287 /// a particular date.
289 /// <param name="date">An integer representing the date as
290 /// fixed day number.
292 /// <param name="k">An integer representing the day of the week,
293 /// starting with 0 for sunday.
295 /// <returns>The fixed day number of the day of week specified by k
296 /// on or after the given date.
298 public static int kday_on_or_after(int date, int k) {
299 return kday_on_or_before(date+6, k);
303 /// The static method computes the date of a day of week that is
304 /// nearest to a particular date.
306 /// <param name="date">An integer representing the date as
307 /// fixed day number.
309 /// <param name="k">An integer representing the day of the week,
310 /// starting with 0 for sunday.
312 /// <returns>The fixed day number of the day of week neares to the
315 public static int kd_nearest(int date, int k) {
316 return kday_on_or_before(date+3, k);
320 /// The static method computes the date of a day of week after
321 /// a particular date.
323 /// <param name="date">An integer representing the date as
324 /// fixed day number.
326 /// <param name="k">An integer representing the day of the week,
327 /// starting with 0 for sunday.
329 /// <returns>The fixed day number of the day of week specified by k
330 /// after the given date.
332 public static int kday_after(int date, int k) {
333 return kday_on_or_before(date+7, k);
337 /// The static method computes the date of a day of week before
338 /// a particular date.
340 /// <param name="date">An integer representing the date as
341 /// fixed day number.
343 /// <param name="k">An integer representing the day of the week,
344 /// starting with 0 for sunday.
346 /// <returns>The fixed day number of the day of week specified by k
347 /// before the given date.
349 public static int kday_before(int date, int k) {
350 return kday_on_or_before(date-1, k);
355 /// A class encapsulating the functions of the Gregorian calendar as static
360 /// This class is not compatible to
361 /// <see cref="T:System.Globalization.GregorianCalendar"/>.
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.
368 /// <seealso cref="T:CCFixed"/>
370 static class CCGregorianCalendar {
371 /// <summary>An integer defining the epoch of the Gregorian calendar
372 /// as fixed day number.</summary>
373 /// <remarks>The epoch is January 3, 1 C.E. (Julian).</remarks>
376 /// <summary>The enumeration defines the months of the Gregorian
432 /// The method tells whether the year is a leap year.
434 /// <param name="year">An integer representing the Gregorian year.
436 /// <returns>A boolean which is true if <paramref name="year"/> is
439 public static bool is_leap_year(int year) {
440 if (CCMath.mod(year, 4) != 0)
442 switch (CCMath.mod(year, 400)) {
454 /// The method returns the fixed day number of the given Gregorian
457 /// <param name="day">An integer representing the day of the month,
460 /// <param name="month">An integer representing the month in the
463 /// <param name="year">An integer representing the Gregorian year.
464 /// Non-positive values are allowed also.
466 /// <returns>An integer value representing the fixed day number.
468 public static int fixed_from_dmy(int day, int month, int year) {
470 year += CCMath.div_mod (out month, month - 1, 12);
476 k += CCMath.div(year-1, 4);
477 k -= CCMath.div(year-1, 100);
478 k += CCMath.div(year-1, 400);
479 k += CCMath.div(367*month-362, 12);
481 k += is_leap_year(year) ? -1 : -2;
490 /// The method computes the Gregorian year from a fixed day number.
492 /// <param name="date">The fixed day number.
494 /// <returns>An integer value giving the Gregorian year of the date.
496 public static int year_from_fixed(int date) {
497 int d = date - epoch;
498 int n_400 = CCMath.div_mod(out d, d, 146097);
499 int n_100 = CCMath.div_mod(out d, d, 36524);
500 int n_4 = CCMath.div_mod(out d, d, 1461);
501 int n_1 = CCMath.div(d, 365);
503 int year = 400*n_400 + 100*n_100 + 4*n_4 + n_1;
504 return (n_100 == 4 || n_1 == 4) ? year : year + 1;
508 /// The method computes the Gregorian year and month from a fixed day
511 /// <param name="month">The output value giving the Gregorian month.
513 /// <param name="year">The output value giving the Gregorian year.
515 /// <param name="date">An integer value specifying the fixed day
517 public static void my_from_fixed(out int month, out int year,
520 year = year_from_fixed(date);
522 int prior_days = date - fixed_from_dmy(1, (int)Month.january,
526 if (date < fixed_from_dmy(1, (int)Month.march, year)) {
528 } else if (is_leap_year(year)) {
534 month = CCMath.div(12 * (prior_days + correction) + 373, 367);
539 /// The method computes the Gregorian year, month, and day from a
540 /// fixed day number.
542 /// <param name="day">The output value returning the day of the
545 /// <param name="month">The output value giving the Gregorian month.
547 /// <param name="year">The output value giving the Gregorian year.
549 /// <param name="date">An integer value specifying the fixed day
551 public static void dmy_from_fixed(out int day, out int month,
555 my_from_fixed(out month, out year, date);
556 day = date - fixed_from_dmy(1, month, year) + 1;
559 /// <summary>A method computing the Gregorian month from a fixed
562 /// <param name="date">An integer specifying the fixed day number.
564 /// <returns>An integer value representing the Gregorian month.
566 public static int month_from_fixed(int date) {
569 my_from_fixed(out month, out year, date);
574 /// A method computing the day of the month from a fixed day number.
576 /// <param name="date">An integer specifying the fixed day number.
578 /// <returns>An integer value representing the day of the month.
580 public static int day_from_fixed(int date) {
581 int day, month, year;
583 dmy_from_fixed(out day, out month, out year, date);
588 /// The method computes the difference between two Gregorian dates.
590 /// <param name="dayA">The integer parameter gives the day of month
591 /// of the first date.
593 /// <param name="monthA">The integer parameter gives the Gregorian
594 /// month of the first date.
596 /// <param name="yearA">The integer parameter gives the Gregorian
597 /// year of the first date.
599 /// <param name="dayB">The integer parameter gives the day of month
600 /// of the second date.
602 /// <param name="monthB">The integer parameter gives the Gregorian
603 /// month of the second date.
605 /// <param name="yearB">The integer parameter gives the Gregorian
606 /// year of the second date.
608 /// <returns>An integer giving the difference of days from the first
611 public static int date_difference(int dayA, int monthA, int yearA,
612 int dayB, int monthB, int yearB)
614 return fixed_from_dmy(dayB, monthB, yearB) -
615 fixed_from_dmy(dayA, monthA, yearA);
619 /// The method computes the number of the day in the year from
620 /// a Gregorian date.
622 /// <param name="day">An integer representing the day of the month,
625 /// <param name="month">An integer representing the month in the
628 /// <param name="year">An integer representing the Gregorian year.
629 /// Non-positive values are allowed also.
631 /// <returns>An integer value giving the number of the day in the
632 /// Gregorian year, counting from 1.
634 public static int day_number(int day, int month, int year) {
635 return date_difference(31, (int)Month.december, year-1,
640 /// The method computes the days remaining in the given Gregorian
641 /// year from a Gregorian date.
643 /// <param name="day">An integer representing the day of the month,
646 /// <param name="month">An integer representing the month in the
649 /// <param name="year">An integer representing the Gregorian year.
650 /// Non-positive values are allowed also.
652 /// <returns>An integer value giving the number of days remaining in
653 /// the Gregorian year.
655 public static int days_remaining(int day, int month, int year) {
656 return date_difference(day, month, year,
657 31, (int)Month.december, year);
660 // Helper functions for the Gregorian calendars.
663 /// Adds months to the given date.
665 /// <param name="time">The
666 /// <see cref="T:System.DateTime"/> to which to add
669 /// <param name="months">The number of months to add.</param>
670 /// <returns>A new <see cref="T:System.DateTime"/> value, that
671 /// results from adding <paramref name="months"/> to the specified
672 /// DateTime.</returns>
673 public static System.DateTime AddMonths(System.DateTime time,
676 int rd = CCFixed.FromDateTime(time);
677 int day, month, year;
678 dmy_from_fixed(out day, out month, out year, rd);
680 year += CCMath.div_mod(out month, month, 12);
681 int maxday = GetDaysInMonth (year, month);
684 rd = fixed_from_dmy(day, month, year);
685 System.DateTime t = CCFixed.ToDateTime(rd);
686 return t.Add(time.TimeOfDay);
690 /// Adds years to the given date.
692 /// <param name="time">The
693 /// <see cref="T:System.DateTime"/> to which to add
696 /// <param name="years">The number of years to add.</param>
697 /// <returns>A new <see cref="T:System.DateTime"/> value, that
698 /// results from adding <paramref name="years"/> to the specified
699 /// DateTime.</returns>
700 public static System.DateTime AddYears(System.DateTime time,
703 int rd = CCFixed.FromDateTime(time);
704 int day, month, year;
705 dmy_from_fixed(out day, out month, out year, rd);
707 int maxday = GetDaysInMonth (year, month);
710 rd = fixed_from_dmy(day, month, year);
711 System.DateTime t = CCFixed.ToDateTime(rd);
712 return t.Add(time.TimeOfDay);
716 /// Gets the of the month from <paramref name="time"/>.
718 /// <param name="time">The
719 /// <see cref="T:System.DateTime"/> that specifies a
722 /// <returns>An integer giving the day of months, starting with 1.
724 public static int GetDayOfMonth(System.DateTime time) {
725 return day_from_fixed(CCFixed.FromDateTime(time));
729 /// The method gives the number of the day in the year.
731 /// <param name="time">The
732 /// <see cref="T:System.DateTime"/> that specifies a
735 /// <returns>An integer representing the day of the year,
736 /// starting with 1.</returns>
737 public static int GetDayOfYear(System.DateTime time) {
738 int rd = CCFixed.FromDateTime(time);
739 int year = year_from_fixed(rd);
740 int rd1_1 = fixed_from_dmy(1, 1, year);
741 return rd - rd1_1 + 1;
745 /// A method that gives the number of days of the specified
746 /// month of the <paramref name="year"/>.
748 /// <param name="year">An integer that gives the year in the current
750 /// <param name="month">An integer that gives the month, starting
752 /// <returns>An integer that gives the number of days of the
753 /// specified month.</returns>
754 public static int GetDaysInMonth(int year, int month) {
755 int rd1 = fixed_from_dmy(1, month, year);
756 int rd2 = fixed_from_dmy(1, month+1, year);
761 /// The method gives the number of days in the specified year.
763 /// <param name="year">An integer that gives the year.
765 /// <returns>An integer that gives the number of days of the
766 /// specified year.</returns>
767 public static int GetDaysInYear(int year) {
768 int rd1 = fixed_from_dmy(1, 1, year);
769 int rd2 = fixed_from_dmy(1, 1, year+1);
774 /// The method gives the number of the month of the specified
777 /// <param name="time">The
778 /// <see cref="T:System.DateTime"/> that specifies a
781 /// <returns>An integer representing the month,
782 /// starting with 1.</returns>
783 public static int GetMonth(System.DateTime time) {
784 return month_from_fixed(CCFixed.FromDateTime(time));
788 /// The method gives the number of the year of the specified
791 /// <param name="time">The
792 /// <see cref="T:System.DateTime"/> that specifies a
795 /// <returns>An integer representing the year.
797 public static int GetYear(System.DateTime time) {
798 return year_from_fixed(CCFixed.FromDateTime(time));
802 /// A virtual method that tells whether the given day
805 /// <param name="year">An integer that specifies the year.
807 /// <param name="month">An integer that specifies the month.
809 /// <param name="day">An integer that specifies the day.
811 /// <returns>A boolean that tells whether the given day is a leap
814 public static bool IsLeapDay(int year, int month, int day) {
815 return is_leap_year(year) && month == 2 && day == 29;
819 /// A method that creates the
820 /// <see cref="T:System.DateTime"/> from the parameters.
822 /// <param name="year">An integer that gives the year
824 /// <param name="month">An integer that specifies the month.
826 /// <param name="day">An integer that specifies the day.
828 /// <param name="hour">An integer that specifies the hour.
830 /// <param name="minute">An integer that specifies the minute.
832 /// <param name="second">An integer that gives the second.
834 /// <param name="milliseconds">An integer that gives the
838 /// <see cref="T:system.DateTime"/> representig the date and time.
840 public static System.DateTime ToDateTime(int year, int month, int day,
841 int hour, int minute, int second, int milliseconds)
843 return CCFixed.ToDateTime(fixed_from_dmy(day, month, year),
844 hour, minute, second, milliseconds);
846 } // class CCGregorianCalendar
849 /// A class encapsulating the functions of the Julian calendar as static
853 /// <para>The algorithms don't support a year 0. Years before Common Era
854 /// (B.C.E. or B.C.) are negative and years of Common Era (C.E. or A.D.)
858 /// This class is not compatible to
859 /// <see cref="T:System.Globalization.JulianCalendar"/>.
861 /// <seealso cref="T:CCFixed"/>
863 static class CCJulianCalendar {
864 /// <summary>An integer defining the epoch of the Julian calendar
865 /// as fixed day number.</summary>
866 /// <remarks>The epoch is December 30, 0 (Gregorian).</remarks>
867 const int epoch = -1; // 30. 12. 0 Gregorian
869 /// <summary>The enumeration defines the months of the Julian
924 /// The method tells whether the year is a leap year.
926 /// <param name="year">An integer representing the Julian year.
928 /// <returns>A boolean which is true if <paramref name="year"/> is
931 public static bool is_leap_year(int year) {
932 return CCMath.mod(year, 4) == (year > 0 ? 0 : 3);
936 /// The method returns the fixed day number of the given Julian
939 /// <param name="day">An integer representing the day of the month,
942 /// <param name="month">An integer representing the month in the
945 /// <param name="year">An integer representing the Julian year.
946 /// Positive and Negative values are allowed.
948 /// <returns>An integer value representing the fixed day number.
950 public static int fixed_from_dmy(int day, int month, int year) {
951 int y = year < 0 ? year+1 : year;
954 y += CCMath.div_mod (out month, month - 1, 12);
960 k += CCMath.div(y-1, 4);
961 k += CCMath.div(367*month-362, 12);
963 k += is_leap_year(year) ? -1 : -2;
971 /// The method computes the Julian year from a fixed day number.
973 /// <param name="date">The fixed day number.
975 /// <returns>An integer value giving the Julian year of the date.
977 public static int year_from_fixed(int date) {
978 int approx = CCMath.div(4*(date-epoch)+1464, 1461);
979 return approx <= 0 ? approx - 1 : approx;
983 /// The method computes the Julian year and month from a fixed day
986 /// <param name="month">The output value giving the Julian month.
988 /// <param name="year">The output value giving the Julian year.
990 /// <param name="date">An integer value specifying the fixed day
992 public static void my_from_fixed(out int month, out int year, int date)
994 year = year_from_fixed(date);
996 int prior_days = date - fixed_from_dmy(1, (int)Month.january,
1000 if (date < fixed_from_dmy(1, (int)Month.march, year)) {
1002 } else if (is_leap_year(year)) {
1008 month = CCMath.div(12 * (prior_days + correction) + 373, 367);
1013 /// The method computes the Julian year, month, and day from a
1014 /// fixed day number.
1016 /// <param name="day">The output value returning the day of the
1019 /// <param name="month">The output value giving the Julian month.
1021 /// <param name="year">The output value giving the Julian year.
1023 /// <param name="date">An integer value specifying the fixed day
1025 public static void dmy_from_fixed(out int day, out int month,
1026 out int year, int date)
1028 my_from_fixed(out month, out year, date);
1029 day = date - fixed_from_dmy(1, month, year) + 1;
1032 /// <summary>A method computing the Julian month from a fixed
1035 /// <param name="date">An integer specifying the fixed day number.
1037 /// <returns>An integer value representing the Julian month.
1039 public static int month_from_fixed(int date) {
1042 my_from_fixed(out month, out year, date);
1047 /// A method computing the day of the month from a fixed day number.
1049 /// <param name="date">An integer specifying the fixed day number.
1051 /// <returns>An integer value representing the day of the month.
1053 public static int day_from_fixed(int date) {
1058 dmy_from_fixed(out day, out month, out year, date);
1063 /// The method computes the difference between two Julian dates.
1065 /// <param name="dayA">The integer parameter gives the day of month
1066 /// of the first date.
1068 /// <param name="monthA">The integer parameter gives the Julian
1069 /// month of the first date.
1071 /// <param name="yearA">The integer parameter gives the Julian
1072 /// year of the first date.
1074 /// <param name="dayB">The integer parameter gives the day of month
1075 /// of the second date.
1077 /// <param name="monthB">The integer parameter gives the Julian
1078 /// month of the second date.
1080 /// <param name="yearB">The integer parameter gives the Julian
1081 /// year of the second date.
1083 /// <returns>An integer giving the difference of days from the first
1084 /// the second date.
1086 public static int date_difference(int dayA, int monthA, int yearA,
1087 int dayB, int monthB, int yearB)
1089 return fixed_from_dmy(dayB, monthB, yearB) -
1090 fixed_from_dmy(dayA, monthA, yearA);
1094 /// The method computes the number of the day in the year from
1097 /// <param name="day">An integer representing the day of the month,
1098 /// counting from 1.
1100 /// <param name="month">An integer representing the month in the
1103 /// <param name="year">An integer representing the Julian year.
1104 /// Negative values are allowed also.
1106 /// <returns>An integer value giving the number of the day in the
1107 /// Julian year, counting from 1.
1109 public static int day_number(int day, int month, int year) {
1110 return date_difference(31, (int)Month.december, year-1,
1115 /// The method computes the days remaining in the given Julian
1116 /// year from a Julian date.
1118 /// <param name="day">An integer representing the day of the month,
1119 /// counting from 1.
1121 /// <param name="month">An integer representing the month in the
1124 /// <param name="year">An integer representing the Julian year.
1125 /// Negative values are allowed also.
1127 /// <returns>An integer value giving the number of days remaining in
1128 /// the Julian year.
1130 public static int days_remaining(int day, int month, int year) {
1131 return date_difference(day, month, year,
1132 31, (int)Month.december, year);
1134 } // class CCJulianCalendar
1137 /// A class encapsulating the functions of the Hebrew calendar as static
1142 /// This class is not compatible to
1143 /// <see cref="T:System.Globalization.HebrewCalendar"/>.
1145 /// <seealso cref="T:CCFixed"/>
1147 static class CCHebrewCalendar {
1148 /// <summary>An integer defining the epoch of the Hebrew calendar
1149 /// as fixed day number.</summary>
1150 /// <remarks>The epoch is October 10, 3761 B.C.E. (Julian).</remarks>
1151 const int epoch = -1373427;
1153 /// <summary>The enumeration defines the months of the Gregorian
1157 /// The enumaration differs from .NET which defines Tishri as month 1.
1209 /// Adar I. Only in years with Adar II.
1213 /// Adar II. Only in years wirh Adar I.
1219 /// The method tells whether the year is a leap year.
1221 /// <param name="year">An integer representing the Hebrew year.
1223 /// <returns>A boolean which is true if <paramref name="year"/> is
1226 public static bool is_leap_year(int year) {
1227 return CCMath.mod(7*year+1, 19) < 7;
1231 /// The Method gives the number of the last month in a year, which
1232 /// is equal with the number of month in a Hebrew year.
1234 /// <param name="year">An integer representing the Hebrew year.
1236 /// <returns>An integer giving the number of the last month of the
1237 /// Hebrew year, which is the same as the numbers of month in the
1240 public static int last_month_of_year(int year) {
1241 return is_leap_year(year) ? 13 : 12;
1245 /// <summary>The method is a helper function.</summary>
1246 /// <param name="year">An integer specifying the Hebrew year.
1248 /// <returns>An integer representing the number of elapsed days
1249 /// until the Hebrew year.</returns>
1250 public static int elapsed_days(int year) {
1251 int months_elapsed = CCMath.div(235*year-234, 19);
1253 int d = CCMath.div_mod(out r, months_elapsed, 1080);
1254 int parts_elapsed = 204 + 793 * r;
1255 int hours_elapsed = 11 + 12 * months_elapsed +
1256 793 * d + CCMath.div(parts_elapsed, 1080);
1258 int day = 29*months_elapsed + CCMath.div(hours_elapsed, 24);
1260 if (CCMath.mod(3*(day+1), 7) < 3) {
1267 /// <summary>A method computing the delay of new year for the given
1270 /// <param name="year">An integer that gives the Hebrew year.
1272 /// <returns>The new year delay in days of the given Hebrew year.
1274 public static int new_year_delay(int year) {
1275 int ny1 = elapsed_days(year);
1276 int ny2 = elapsed_days(year+1);
1278 if (ny2 - ny1 == 356) {
1281 int ny0 = elapsed_days(year-1);
1282 if (ny1 - ny0 == 382) {
1289 /// The method computes the last day of month (nummer of days in a
1290 /// month) of the given Hebrew year.
1292 /// <param name="month">The Hebrew month, allowed value between
1293 /// One and Thirteen.
1295 /// <param name="year">An integer that gives the Hebrew year.
1297 /// <returns>The number of the last day of the month of the given
1298 /// Hebrew year, which gives automatically the number of days in the
1301 /// <exception cref="T:System.ArgumentOutOfRange.Exception">
1302 /// The exception is thrown if month not between One and Thirteen.
1304 public static int last_day_of_month(int month, int year) {
1305 if (month < 1 || month > 13)
1306 throw new System.ArgumentOutOfRangeException("month",
1307 "Month should be between One and Thirteen.");
1313 if (!long_heshvan(year))
1317 if (short_kislev(year))
1322 if (!is_leap_year(year))
1331 /// The functions checks whether the month Heshvan is a long one
1332 /// in the given Hebrew year.
1334 /// <param name="year">An integer that gives the Hebrew year.
1336 /// <returns>A boolean value: true if there is a long Heshvan
1337 /// in the given Hebrew year; false otherwise.
1339 public static bool long_heshvan(int year) {
1340 return CCMath.mod(days_in_year(year), 10) == 5;
1344 /// The functions checks whether the month Kislev is a short one
1345 /// in the given Hebrew year.
1347 /// <param name="year">An integer that gives the Hebrew year.
1349 /// <returns>A boolean value: true if there is a short Kislev
1350 /// in the given Hebrew year; false otherwise.
1352 public static bool short_kislev(int year) {
1353 return CCMath.mod(days_in_year(year), 10) == 3;
1357 /// The functions gives the number of days in the specified Hebrew
1360 /// <param name="year">An integer that gives the Hebrew year.
1362 /// <returns>The days of the Hebrew year as integer.
1364 public static int days_in_year(int year) {
1365 return fixed_from_dmy(1, 7, year+1) -
1366 fixed_from_dmy(1, 7, year);
1370 /// The method returns the fixed day number of the given Hebrew
1373 /// <param name="day">An integer representing the day of the month,
1374 /// counting from 1.
1376 /// <param name="month">An integer representing the month in the
1379 /// <param name="year">An integer representing the Hebrew year.
1380 /// Non-positive values are allowed also.
1382 /// <returns>An integer value representing the fixed day number.
1384 public static int fixed_from_dmy(int day, int month, int year) {
1385 var lastMonth = last_month_of_year (year);
1386 while (month > lastMonth) {
1389 lastMonth = last_month_of_year (year);
1394 k += elapsed_days(year);
1395 k += new_year_delay(year);
1398 int l = last_month_of_year(year);
1399 for (m = 7; m <= l; m++) {
1400 k += last_day_of_month(m, year);
1402 for (m = 1; m < month; m++) {
1403 k += last_day_of_month(m, year);
1407 for (m = 7; m < month; m++) {
1408 k += last_day_of_month(m, year);
1418 /// The method computes the Hebrew year from a fixed day number.
1420 /// <param name="date">The fixed day number.
1422 /// <returns>An integer value giving the Hebrew year of the date.
1424 public static int year_from_fixed(int date) {
1425 int approx = (int)System.Math.Floor(
1426 ((double)(date - epoch))/(35975351.0/98496.0));
1428 for (y = approx; date >= fixed_from_dmy(1, 7, y); y++) {}
1433 /// The method computes the Hebrew year and month from a fixed day
1436 /// <param name="month">The output value giving the Hebrew month.
1438 /// <param name="year">The output value giving the Hebrew year.
1440 /// <param name="date">An integer value specifying the fixed day
1442 public static void my_from_fixed(out int month, out int year,
1445 year = year_from_fixed(date);
1447 int start = date < fixed_from_dmy(1, 1, year) ? 7 : 1;
1450 date > fixed_from_dmy(last_day_of_month(month, year),
1457 /// The method computes the Hebrew year, month, and day from a
1458 /// fixed day number.
1460 /// <param name="day">The output value returning the day of the
1463 /// <param name="month">The output value giving the Hebrew month.
1465 /// <param name="year">The output value giving the Hebrew year.
1467 /// <param name="date">An integer value specifying the fixed day
1469 public static void dmy_from_fixed(out int day, out int month,
1470 out int year, int date)
1472 my_from_fixed(out month, out year, date);
1473 day = date - fixed_from_dmy(1, month, year) + 1;
1476 /// <summary>A method computing the Hebrew month from a fixed
1479 /// <param name="date">An integer specifying the fixed day number.
1481 /// <returns>An integer value representing the Hebrew month.
1483 public static int month_from_fixed(int date) {
1486 my_from_fixed(out month, out year, date);
1491 /// A method computing the day of the month from a fixed day number.
1493 /// <param name="date">An integer specifying the fixed day number.
1495 /// <returns>An integer value representing the day of the month.
1497 public static int day_from_fixed(int date) {
1498 int day, month, year;
1500 dmy_from_fixed(out day, out month, out year, date);
1505 /// The method computes the difference between two Hebrew dates.
1507 /// <param name="dayA">The integer parameter gives the day of month
1508 /// of the first date.
1510 /// <param name="monthA">The integer parameter gives the Hebrew
1511 /// month of the first date.
1513 /// <param name="yearA">The integer parameter gives the Hebrew
1514 /// year of the first date.
1516 /// <param name="dayB">The integer parameter gives the day of month
1517 /// of the second date.
1519 /// <param name="monthB">The integer parameter gives the Hebrew
1520 /// month of the second date.
1522 /// <param name="yearB">The integer parameter gives the Hebrew
1523 /// year of the second date.
1525 /// <returns>An integer giving the difference of days from the first
1526 /// the second date.
1528 public static int date_difference(int dayA, int monthA, int yearA,
1529 int dayB, int monthB, int yearB)
1531 return fixed_from_dmy(dayB, monthB, yearB) -
1532 fixed_from_dmy(dayA, monthA, yearA);
1536 /// The method computes the number of the day in the year from
1539 /// <param name="day">An integer representing the day of the month,
1540 /// counting from 1.
1542 /// <param name="month">An integer representing the month in the
1545 /// <param name="year">An integer representing the Hebrew year.
1547 /// <returns>An integer value giving the number of the day in the
1548 /// Hebrew year, counting from 1.
1550 public static int day_number(int day, int month, int year) {
1551 return date_difference(1, 7, year,
1552 day, month, year) + 1;
1556 /// The method computes the days remaining in the given Hebrew
1557 /// year from a Hebrew date.
1559 /// <param name="day">An integer representing the day of the month,
1560 /// counting from 1.
1562 /// <param name="month">An integer representing the month in the
1565 /// <param name="year">An integer representing the Hebrew year.
1567 /// <returns>An integer value giving the number of days remaining in
1568 /// the Hebrew year.
1570 public static int days_remaining(int day, int month, int year) {
1571 return date_difference(day, month, year,
1574 } // class HebrewCalendar
1578 /// A class encapsulating the functions of the Islamic calendar as static
1582 /// <para>There is no difference here in using Hijri or Islamic calendar.
1584 /// <para>The epoch of the Islamic calendar isn't fixed, because we cannot
1585 /// surely say today, when the crescent of the new moon has been observed
1586 /// around the July 16, 622 C.E. Julian. Even today the start and end of
1587 /// the month Ramadan is defined by religous authorities. So the calendar
1588 /// can be offset by two days.
1591 /// We don't support the offset here, however we changed the epoch from
1592 /// "Calendrical Calculations" to value, that .Net seems to be using.
1595 /// This class is not compatible to
1596 /// <see cref="T:System.Globalization.HijriCalendar"/>.
1598 /// <seealso cref="T:CCFixed"/>
1600 static class CCHijriCalendar {
1601 /// <summary>An integer defining the epoch of the Gregorian calendar
1602 /// as fixed day number.</summary>
1605 /// The epoch is given as 16 July 622 C.E. Julian (R.D. 227015)
1606 /// in Calendrical Calculations, the approximate date of
1607 /// the emigration of
1608 /// Muhammed to Medina. However there is no way to determine today
1609 /// the observation of the crescent of the new moon in July 622 C.E.
1610 /// (Julian). So there is some variability in the epoch.
1611 /// Religous authorities determine the epoch by observing the
1612 /// crescent of the new moon for the month Ramadan, so there might
1613 /// be an offsets by two days of the epoch.
1616 /// supports an AddHijriDate parameter in the registry to adapt
1617 /// for it. It seems that the .NET implementation of
1618 /// HijriCalendar uses an epoch of 227014, so we use it here. The
1619 /// ArgumentOutOfRangeException gives July, 18 622 as epoch,
1620 /// which is 227014 supporting our theory.
1623 const int epoch = 227014;
1625 /// <summary>The enumeration defines the months of the Islamic
1680 /// The method tells whether the year is a leap year.
1682 /// <param name="year">An integer representing the Islamic year.
1684 /// <returns>A boolean which is true if <paramref name="year"/> is
1687 public static bool is_leap_year(int year) {
1688 return CCMath.mod(14+11*year, 30) < 11;
1692 /// The method returns the fixed day number of the given Islamic
1695 /// <param name="day">An integer representing the day of the month,
1696 /// counting from 1.
1698 /// <param name="month">An integer representing the month in the
1701 /// <param name="year">An integer representing the Islamic year.
1702 /// Non-positive values are allowed also.
1704 /// <returns>An integer value representing the fixed day number.
1706 public static int fixed_from_dmy(int day, int month, int year) {
1708 year += CCMath.div_mod (out month, month - 1, 12);
1713 k += 354 * (year-1);
1714 k += CCMath.div(3+11*year, 30);
1715 k += (int)System.Math.Ceiling(29.5 * (double)(month-1));
1722 /// The method computes the Islamic year from a fixed day number.
1724 /// <param name="date">The fixed day number.
1726 /// <returns>An integer value giving the Islamic year of the date.
1728 public static int year_from_fixed(int date) {
1729 return CCMath.div(30*(date-epoch)+10646, 10631);
1733 /// The method computes the Islamic year and month from a fixed day
1736 /// <param name="month">The output value giving the Islamic month.
1738 /// <param name="year">The output value giving the Islamic year.
1740 /// <param name="date">An integer value specifying the fixed day
1742 public static void my_from_fixed(out int month, out int year, int date)
1744 year = year_from_fixed(date);
1746 int m = 1+(int)System.Math.Ceiling(
1747 ((double)(date-29-fixed_from_dmy(1,1,year)))/29.5);
1749 month = m < 12 ? m : 12;
1753 /// The method computes the Islamic year, month, and day from a
1754 /// fixed day number.
1756 /// <param name="day">The output value returning the day of the
1759 /// <param name="month">The output value giving the Islamic month.
1761 /// <param name="year">The output value giving the Islamic year.
1763 /// <param name="date">An integer value specifying the fixed day
1765 public static void dmy_from_fixed(out int day, out int month,
1766 out int year, int date)
1768 my_from_fixed(out month, out year, date);
1769 day = date - fixed_from_dmy(1, month, year) + 1;
1772 /// <summary>A method computing the Islamic month from a fixed
1775 /// <param name="date">An integer specifying the fixed day number.
1777 /// <returns>An integer value representing the Islamic month.
1779 public static int month_from_fixed(int date) {
1782 my_from_fixed(out month, out year, date);
1787 /// A method computing the day of the month from a fixed day number.
1789 /// <param name="date">An integer specifying the fixed day number.
1791 /// <returns>An integer value representing the day of the month.
1793 public static int day_from_fixed(int date) {
1798 dmy_from_fixed(out day, out month, out year, date);
1803 /// The method computes the difference between two Islamic dates.
1805 /// <param name="dayA">The integer parameter gives the day of month
1806 /// of the first date.
1808 /// <param name="monthA">The integer parameter gives the Islamic
1809 /// month of the first date.
1811 /// <param name="yearA">The integer parameter gives the Islamic
1812 /// year of the first date.
1814 /// <param name="dayB">The integer parameter gives the day of month
1815 /// of the second date.
1817 /// <param name="monthB">The integer parameter gives the Islamic
1818 /// month of the second date.
1820 /// <param name="yearB">The integer parameter gives the Islamic
1821 /// year of the second date.
1823 /// <returns>An integer giving the difference of days from the first
1824 /// the second date.
1826 public static int date_difference(int dayA, int monthA, int yearA,
1827 int dayB, int monthB, int yearB)
1829 return fixed_from_dmy(dayB, monthB, yearB) -
1830 fixed_from_dmy(dayA, monthA, yearA);
1834 /// The method computes the number of the day in the year from
1837 /// <param name="day">An integer representing the day of the month,
1838 /// counting from 1.
1840 /// <param name="month">An integer representing the month in the
1843 /// <param name="year">An integer representing the Islamic year.
1845 /// <returns>An integer value giving the number of the day in the
1846 /// Islamic year, counting from 1.
1848 public static int day_number(int day, int month, int year) {
1849 return date_difference(31, 12, year-1, day, month, year);
1853 /// The method computes the days remaining in the given Islamic
1854 /// year from a Islamic date.
1856 /// <param name="day">An integer representing the day of the month,
1857 /// counting from 1.
1859 /// <param name="month">An integer representing the month in the
1862 /// <param name="year">An integer representing the Islamic year.
1863 /// Non-positive values are allowed also.
1865 /// <returns>An integer value giving the number of days remaining in
1866 /// the Islamic year.
1868 public static int days_remaining(int day, int month, int year) {
1869 return date_difference(day, month, year,31, 12, year);
1871 } // class CCHijriCalendar
1873 internal class CCEastAsianLunisolarCalendar
1875 public static int fixed_from_dmy (int day, int month, int year)
1879 k += 354 * (year - 1);
1880 k += CCMath.div (3+11*year, 30);
1881 k += (int) Math.Ceiling(29.53 * (double)(month-1));
1886 throw new Exception ("fixed_from_dmy");
1889 public static int year_from_fixed (int date)
1891 throw new Exception ("year_from_fixed");
1894 public static void my_from_fixed(out int month, out int year, int date)
1897 year = year_from_fixed (date);
1899 int m = 1+(int)System.Math.Ceiling(
1900 ((double)(date-29-fixed_from_dmy(1,1,year)))/29.5);
1902 month = m < 12 ? m : 12;
1904 throw new Exception ("my_from_fixed");
1907 public static void dmy_from_fixed(out int day, out int month,
1908 out int year, int date)
1911 my_from_fixed (out month, out year, date);
1912 day = date - fixed_from_dmy (1, month, year) + 1;
1914 throw new Exception ("dmy_from_fixed");
1917 public static DateTime AddMonths (DateTime date, int months)
1920 throw new Exception ("AddMonths");
1923 public static DateTime AddYears (DateTime date, int years)
1925 throw new Exception ("AddYears");
1928 public static int GetDayOfMonth (DateTime date)
1930 throw new Exception ("GetDayOfMonth");
1933 public static int GetDayOfYear (DateTime date)
1935 throw new Exception ("GetDayOfYear");
1938 public static int GetDaysInMonth (int gyear, int month)
1940 throw new Exception ("GetDaysInMonth");
1943 public static int GetDaysInYear (int year)
1945 throw new Exception ("GetDaysInYear");
1948 public static int GetMonth (DateTime date)
1950 throw new Exception ("GetMonth");
1953 public static bool IsLeapMonth (int gyear, int month)
1955 int goldenNumber = gyear % 19;
1960 for (int y = 0; y < goldenNumber; y++) {
1961 for (int l = 0, m = 1; m <= month; m++) {
1965 if (y == goldenNumber && m == month)
1979 public static bool IsLeapYear (int gyear)
1982 // FIXME: it is still wrong.
1985 case 0: case 3: case 6: case 9: case 11: case 14: case 17:
1991 int goldenNumber = (gyear - 1900) % 19;
1994 while (goldenNumber-- >= 0) {
2004 public static DateTime ToDateTime (int year, int month, int day, int hour, int minute, int second, int millisecond)
2006 throw new Exception ("ToDateTime");
2011 /// A class that supports the Gregorian based calendars with other eras
2012 /// (e.g. <see cref="T:System.Gloablization.JapaneseCalendar"/>).
2014 [System.Serializable]
2015 internal class CCGregorianEraHandler {
2017 /// A struct that represents a single era.
2019 [System.Serializable]
2022 /// The integer number identifying the era.
2027 /// A get-only property that gives the era integer number.
2029 public int Nr { get { return _nr; } }
2031 /// <summary>This integer gives the first day of the era as
2032 /// fixed day number.
2034 private int _start; // inclusive
2036 /// This integer gives the gregorian year of the
2037 /// <see cref="M:_start"/> value.
2039 private int _gregorianYearStart;
2041 /// This integer gives the last day of the era as fixed day
2044 private int _end; // inclusive
2046 /// This integer gives the largest year number of this era.
2048 private int _maxYear;
2051 /// This constructor creates the era structure.
2053 /// <param name="nr">The integer number of the era.
2055 /// <param name="start">The fixed day number defining the
2056 /// first day of the era.
2058 /// <param name="end">The fixed day number that defines the
2059 /// last day of the era.
2061 public Era(int nr, int start, int end) {
2063 throw new System.ArgumentException(
2064 "Era number shouldn't be zero.");
2067 throw new System.ArgumentException(
2068 "Era should start before end.");
2073 _gregorianYearStart =
2074 CCGregorianCalendar.year_from_fixed(_start);
2075 int gregorianYearEnd =
2076 CCGregorianCalendar.year_from_fixed(_end);
2077 _maxYear = gregorianYearEnd - _gregorianYearStart + 1;
2081 /// This method computes the Gregorian year from the year
2084 /// <param name="year">An integer giving the year in the
2088 /// The Gregorian year as integer.
2090 /// <exception cref="T:System.ArgumentOutOfRangeException">
2091 /// The exception is thrown if the year isn't valid in this
2094 public int GregorianYear(int year) {
2095 if (year < 1 || year > _maxYear) {
2096 System.IO.StringWriter sw =
2097 new System.IO.StringWriter();
2099 "Valid Values are between " +
2100 "{0} and {1}, inclusive.",
2102 throw new System.ArgumentOutOfRangeException(
2103 "year", sw.ToString());
2105 return year + _gregorianYearStart - 1;
2109 /// This function checks wether the given fixed day number is
2110 /// ion the time span of the era.
2112 /// <param name="date">An integer giving the fixed day
2115 /// <returns>A boolean: true if the argument is in the time
2116 /// span of the era.
2118 public bool Covers(int date) {
2119 return _start <= date && date <= _end;
2123 /// This function returns the year of the era and sets
2124 /// the era in an output parameter.
2126 /// <param name="era">An output parameter returning the
2129 /// <param name="date">An integer giving the fixed day
2132 /// <returns>An integer giving the year of the era.
2134 /// <exception cref="T:System.ArgumentOutOfRangeException">
2135 /// The exception is thrown if date is outside of the time
2136 /// span of the era.
2138 public int EraYear(out int era, int date) {
2140 throw new System.ArgumentOutOfRangeException(
2142 "Time was out of Era range.");
2144 CCGregorianCalendar.year_from_fixed(date);
2146 return gregorianYear - _gregorianYearStart + 1;
2151 /// A private member storing the eras in a
2152 /// <see cref="T:System.Collections.SortedList"/>.
2154 private SortedList _Eras;
2157 /// The property returns the era numbers as an array of integers.
2161 int[] a = new int[_Eras.Count];
2163 for (int i = 0; i < _Eras.Count; i++) {
2164 Era e = (Era)_Eras.GetByIndex(i);
2175 public CCGregorianEraHandler() {
2176 _Eras = new SortedList();
2180 /// Method adds an era to the GregorianEraHandler instance.
2182 /// <param name="nr">The integer number of the era.
2184 /// <param name="rd_start">The fixed day number defining the
2185 /// first day of the era.
2187 /// <param name="rd_end">The fixed day number that defines the
2188 /// last day of the era.
2190 public void appendEra(int nr, int rd_start, int rd_end) {
2191 Era era = new Era(nr, rd_start, rd_end);
2192 _Eras[(System.Object)nr] = era;
2195 /// Method adds a yet not-ended era to the GregorianEraHandler
2198 /// <param name="nr">The integer number of the era.
2200 /// <param name="rd_start">The fixed day number defining the
2201 /// first day of the era.
2203 public void appendEra(int nr, int rd_start) {
2204 appendEra(nr, rd_start,
2205 CCFixed.FromDateTime(DateTime.MaxValue));
2209 /// This method computes the Gregorian year from the year
2210 /// of the given era.
2212 /// <param name="year">An integer giving the year in the
2215 /// <param name="era">An integer giving the era number.
2218 /// The Gregorian year as integer.
2220 /// <exception cref="T:System.ArgumentOutOfRangeException">
2221 /// The exception is thrown if the year isn't valid in this
2224 public int GregorianYear(int year, int era) {
2225 Era e = (Era)_Eras[(System.Object)era];
2226 return e.GregorianYear(year);
2230 /// This function returns the year of the era and sets
2231 /// the era in an output parameter.
2233 /// <param name="era">An output parameter returning the
2236 /// <param name="date">An integer giving the fixed day
2239 /// <returns>An integer giving the year of the era.
2241 /// <exception cref="T:System.ArgumentOutOfRangeException">
2242 /// The exception is thrown if the fixed day number is outside of the
2243 /// time spans of all eras.
2245 public int EraYear(out int era, int date)
2247 IList list = _Eras.GetValueList();
2249 foreach (Era e in list) {
2251 return e.EraYear(out era, date);
2254 throw new System.ArgumentOutOfRangeException("date",
2255 "Time value was out of era range.");
2259 /// The method checks whether a given
2260 /// <see cref="T:System.DateTime"/> is covered by any era.
2262 /// <param name="time">A
2263 /// <see cref="T:System.DateTime"/> giving the date and time.
2265 /// <exception cref="T:System.ArgumentOutOfRangeException">
2266 /// The exception is thrown if the argument isn't inside the time
2267 /// span of any era.
2269 public void CheckDateTime(System.DateTime time) {
2270 int date = CCFixed.FromDateTime(time);
2272 if (!ValidDate(date))
2273 throw new System.ArgumentOutOfRangeException("time",
2274 "Time value was out of era range.");
2278 /// The method tests whether a given
2279 /// fixed day number is covered by any era.
2281 /// <param name="date">An integer representing the fixed day number.
2283 /// <returns> A boolean is returned: true if the argument is inside
2284 /// the time span of one era; false otherwise.
2286 public bool ValidDate(int date) {
2287 IList list = _Eras.GetValueList();
2289 foreach (Era e in list) {
2298 /// The method tests, whether the era number does exist.
2300 /// <param name="era">An integer giving the era number.
2302 /// <returns>A boole value: True if the era number does exist;
2303 /// false otherwise.
2305 public bool ValidEra(int era) {
2306 return _Eras.Contains((System.Object)era);
2308 } // class CCGregorianEraHandler
2311 // FIXME: remove this class. It should be identical to CCGregorianEraHandler
2312 [System.Serializable]
2313 internal class CCEastAsianLunisolarEraHandler
2318 private int _nr; // era index
2324 private int _start; // inclusive
2325 private int _gregorianYearStart;
2326 private int _end; // inclusive
2327 private int _maxYear;
2329 public Era (int nr, int start, int end)
2332 throw new ArgumentException ("Era number shouldn't be zero.");
2335 throw new ArgumentException ("Era should start before end.");
2339 _gregorianYearStart = CCGregorianCalendar.year_from_fixed (_start);
2340 int gregorianYearEnd = CCGregorianCalendar.year_from_fixed (_end);
2341 _maxYear = gregorianYearEnd - _gregorianYearStart + 1;
2344 public int GregorianYear (int year)
2346 if (year < 1 || year > _maxYear)
2347 throw new ArgumentOutOfRangeException ("year", String.Format ("Valid Values are between {0} and {1}, inclusive.", 1, _maxYear));
2348 return year + _gregorianYearStart - 1;
2351 public bool Covers (int date) {
2352 return _start <= date && date <= _end;
2355 public int EraYear (out int era, int date) {
2357 throw new ArgumentOutOfRangeException ("date", "Time was out of Era range.");
2358 int gregorianYear = CCGregorianCalendar.year_from_fixed (date);
2360 return gregorianYear - _gregorianYearStart + 1;
2364 private SortedList _Eras;
2369 int[] a = new int [_Eras.Count];
2370 for (int i = 0; i < _Eras.Count; i++) {
2371 Era e = (Era) _Eras.GetByIndex (i);
2378 public CCEastAsianLunisolarEraHandler ()
2380 _Eras = new SortedList ();
2383 public void appendEra (int nr, int rd_start, int rd_end)
2385 Era era = new Era (nr, rd_start, rd_end);
2389 public void appendEra (int nr, int rd_start)
2391 appendEra (nr, rd_start, CCFixed.FromDateTime (DateTime.MaxValue));
2394 public int GregorianYear (int year, int era)
2396 Era e = (Era) _Eras [era];
2397 return e.GregorianYear (year);
2400 public int EraYear (out int era, int date)
2402 foreach (Era e in _Eras.Values)
2403 if (e.Covers (date))
2404 return e.EraYear (out era, date);
2406 throw new ArgumentOutOfRangeException ("date", "Time value was out of era range.");
2409 public void CheckDateTime (DateTime time)
2411 int date = CCFixed.FromDateTime (time);
2413 if (!ValidDate (date))
2414 throw new ArgumentOutOfRangeException ("time", "Time value was out of era range.");
2417 public bool ValidDate (int date)
2419 foreach (Era e in _Eras.Values) {
2420 if (e.Covers (date))
2426 public bool ValidEra (int era)
2428 return _Eras.Contains (era);
2432 } // namespace System.Globalization