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"
41 internal class CCMath
{
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 internal 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 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>
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
) {
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);
476 k
+= is_leap_year(year
) ? -1 : -2;
485 /// The method computes the Gregorian year from a fixed day number.
487 /// <param name="date">The fixed day number.
489 /// <returns>An integer value giving the Gregorian year of the date.
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);
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;
503 /// The method computes the Gregorian year and month from a fixed day
506 /// <param name="month">The output value giving the Gregorian month.
508 /// <param name="year">The output value giving the Gregorian year.
510 /// <param name="date">An integer value specifying the fixed day
512 public static void my_from_fixed(out int month
, out int year
,
515 year
= year_from_fixed(date
);
517 int prior_days
= date
- fixed_from_dmy(1, (int)Month
.january
,
521 if (date
< fixed_from_dmy(1, (int)Month
.march
, year
)) {
523 } else if (is_leap_year(year
)) {
529 month
= CCMath
.div(12 * (prior_days
+ correction
) + 373, 367);
534 /// The method computes the Gregorian year, month, and day from a
535 /// fixed day number.
537 /// <param name="day">The output value returning the day of the
540 /// <param name="month">The output value giving the Gregorian month.
542 /// <param name="year">The output value giving the Gregorian year.
544 /// <param name="date">An integer value specifying the fixed day
546 public static void dmy_from_fixed(out int day
, out int month
,
550 my_from_fixed(out month
, out year
, date
);
551 day
= date
- fixed_from_dmy(1, month
, year
) + 1;
554 /// <summary>A method computing the Gregorian month from a fixed
557 /// <param name="date">An integer specifying the fixed day number.
559 /// <returns>An integer value representing the Gregorian month.
561 public static int month_from_fixed(int date
) {
564 my_from_fixed(out month
, out year
, date
);
569 /// A method computing the day of the month from a fixed day number.
571 /// <param name="date">An integer specifying the fixed day number.
573 /// <returns>An integer value representing the day of the month.
575 public static int day_from_fixed(int date
) {
576 int day
, month
, year
;
578 dmy_from_fixed(out day
, out month
, out year
, date
);
583 /// The method computes the difference between two Gregorian dates.
585 /// <param name="dayA">The integer parameter gives the day of month
586 /// of the first date.
588 /// <param name="monthA">The integer parameter gives the Gregorian
589 /// month of the first date.
591 /// <param name="yearA">The integer parameter gives the Gregorian
592 /// year of the first date.
594 /// <param name="dayB">The integer parameter gives the day of month
595 /// of the second date.
597 /// <param name="monthB">The integer parameter gives the Gregorian
598 /// month of the second date.
600 /// <param name="yearB">The integer parameter gives the Gregorian
601 /// year of the second date.
603 /// <returns>An integer giving the difference of days from the first
606 public static int date_difference(int dayA
, int monthA
, int yearA
,
607 int dayB
, int monthB
, int yearB
)
609 return fixed_from_dmy(dayB
, monthB
, yearB
) -
610 fixed_from_dmy(dayA
, monthA
, yearA
);
614 /// The method computes the number of the day in the year from
615 /// a Gregorian date.
617 /// <param name="day">An integer representing the day of the month,
620 /// <param name="month">An integer representing the month in the
623 /// <param name="year">An integer representing the Gregorian year.
624 /// Non-positive values are allowed also.
626 /// <returns>An integer value giving the number of the day in the
627 /// Gregorian year, counting from 1.
629 public static int day_number(int day
, int month
, int year
) {
630 return date_difference(31, (int)Month
.december
, year
-1,
635 /// The method computes the days remaining in the given Gregorian
636 /// year from a Gregorian date.
638 /// <param name="day">An integer representing the day of the month,
641 /// <param name="month">An integer representing the month in the
644 /// <param name="year">An integer representing the Gregorian year.
645 /// Non-positive values are allowed also.
647 /// <returns>An integer value giving the number of days remaining in
648 /// the Gregorian year.
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
);
655 // Helper functions for the Gregorian calendars.
658 /// Adds months to the given date.
660 /// <param name="time">The
661 /// <see cref="T:System.DateTime"/> to which to add
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
,
671 int rd
= CCFixed
.FromDateTime(time
);
672 int day
, month
, year
;
673 dmy_from_fixed(out day
, out month
, out year
, rd
);
675 year
+= CCMath
.div_mod(out month
, month
, 12);
676 int maxday
= GetDaysInMonth (year
, month
);
679 rd
= fixed_from_dmy(day
, month
, year
);
680 System
.DateTime t
= CCFixed
.ToDateTime(rd
);
681 return t
.Add(time
.TimeOfDay
);
685 /// Adds years to the given date.
687 /// <param name="time">The
688 /// <see cref="T:System.DateTime"/> to which to add
691 /// <param name="years">The number of years to add.</param>
692 /// <returns>A new <see cref="T:System.DateTime"/> value, that
693 /// results from adding <paramref name="years"/> to the specified
694 /// DateTime.</returns>
695 public static System
.DateTime
AddYears(System
.DateTime time
,
698 int rd
= CCFixed
.FromDateTime(time
);
699 int day
, month
, year
;
700 dmy_from_fixed(out day
, out month
, out year
, rd
);
702 int maxday
= GetDaysInMonth (year
, month
);
705 rd
= fixed_from_dmy(day
, month
, year
);
706 System
.DateTime t
= CCFixed
.ToDateTime(rd
);
707 return t
.Add(time
.TimeOfDay
);
711 /// Gets the of the month from <paramref name="time"/>.
713 /// <param name="time">The
714 /// <see cref="T:System.DateTime"/> that specifies a
717 /// <returns>An integer giving the day of months, starting with 1.
719 public static int GetDayOfMonth(System
.DateTime time
) {
720 return day_from_fixed(CCFixed
.FromDateTime(time
));
724 /// The method gives the number of the day in the year.
726 /// <param name="time">The
727 /// <see cref="T:System.DateTime"/> that specifies a
730 /// <returns>An integer representing the day of the year,
731 /// starting with 1.</returns>
732 public static int GetDayOfYear(System
.DateTime time
) {
733 int rd
= CCFixed
.FromDateTime(time
);
734 int year
= year_from_fixed(rd
);
735 int rd1_1
= fixed_from_dmy(1, 1, year
);
736 return rd
- rd1_1
+ 1;
740 /// A method that gives the number of days of the specified
741 /// month of the <paramref name="year"/>.
743 /// <param name="year">An integer that gives the year in the current
745 /// <param name="month">An integer that gives the month, starting
747 /// <returns>An integer that gives the number of days of the
748 /// specified month.</returns>
749 public static int GetDaysInMonth(int year
, int month
) {
750 int rd1
= fixed_from_dmy(1, month
, year
);
751 int rd2
= fixed_from_dmy(1, month
+1, year
);
756 /// The method gives the number of days in the specified year.
758 /// <param name="year">An integer that gives the year.
760 /// <returns>An integer that gives the number of days of the
761 /// specified year.</returns>
762 public static int GetDaysInYear(int year
) {
763 int rd1
= fixed_from_dmy(1, 1, year
);
764 int rd2
= fixed_from_dmy(1, 1, year
+1);
769 /// The method gives the number of the month of the specified
772 /// <param name="time">The
773 /// <see cref="T:System.DateTime"/> that specifies a
776 /// <returns>An integer representing the month,
777 /// starting with 1.</returns>
778 public static int GetMonth(System
.DateTime time
) {
779 return month_from_fixed(CCFixed
.FromDateTime(time
));
783 /// The method gives the number of the year of the specified
786 /// <param name="time">The
787 /// <see cref="T:System.DateTime"/> that specifies a
790 /// <returns>An integer representing the year.
792 public static int GetYear(System
.DateTime time
) {
793 return year_from_fixed(CCFixed
.FromDateTime(time
));
797 /// A virtual method that tells whether the given day
800 /// <param name="year">An integer that specifies the year.
802 /// <param name="month">An integer that specifies the month.
804 /// <param name="day">An integer that specifies the day.
806 /// <returns>A boolean that tells whether the given day is a leap
809 public static bool IsLeapDay(int year
, int month
, int day
) {
810 return is_leap_year(year
) && month
== 2 && day
== 29;
814 /// A method that creates the
815 /// <see cref="T:System.DateTime"/> from the parameters.
817 /// <param name="year">An integer that gives the year
819 /// <param name="month">An integer that specifies the month.
821 /// <param name="day">An integer that specifies the day.
823 /// <param name="hour">An integer that specifies the hour.
825 /// <param name="minute">An integer that specifies the minute.
827 /// <param name="second">An integer that gives the second.
829 /// <param name="milliseconds">An integer that gives the
833 /// <see cref="T:system.DateTime"/> representig the date and time.
835 public static System
.DateTime
ToDateTime(int year
, int month
, int day
,
836 int hour
, int minute
, int second
, int milliseconds
)
838 return CCFixed
.ToDateTime(fixed_from_dmy(day
, month
, year
),
839 hour
, minute
, second
, milliseconds
);
841 } // class CCGregorianCalendar
844 /// A class encapsulating the functions of the Julian calendar as static
848 /// <para>The algorithms don't support a year 0. Years before Common Era
849 /// (B.C.E. or B.C.) are negative and years of Common Era (C.E. or A.D.)
853 /// This class is not compatible to
854 /// <see cref="T:System.Globalization.JulianCalendar"/>.
856 /// <seealso cref="T:CCFixed"/>
858 internal class CCJulianCalendar
{
859 /// <summary>An integer defining the epoch of the Julian calendar
860 /// as fixed day number.</summary>
861 /// <remarks>The epoch is December 30, 0 (Gregorian).</remarks>
862 const int epoch
= -1; // 30. 12. 0 Gregorian
864 /// <summary>The enumeration defines the months of the Julian
919 /// The method tells whether the year is a leap year.
921 /// <param name="year">An integer representing the Julian year.
923 /// <returns>A boolean which is true if <paramref name="year"/> is
926 public static bool is_leap_year(int year
) {
927 return CCMath
.mod(year
, 4) == (year
> 0 ? 0 : 3);
931 /// The method returns the fixed day number of the given Julian
934 /// <param name="day">An integer representing the day of the month,
937 /// <param name="month">An integer representing the month in the
940 /// <param name="year">An integer representing the Julian year.
941 /// Positive and Negative values are allowed.
943 /// <returns>An integer value representing the fixed day number.
945 public static int fixed_from_dmy(int day
, int month
, int year
) {
946 int y
= year
< 0 ? year
+1 : year
;
949 k
+= CCMath
.div(y
-1, 4);
950 k
+= CCMath
.div(367*month
-362, 12);
952 k
+= is_leap_year(year
) ? -1 : -2;
960 /// The method computes the Julian year from a fixed day number.
962 /// <param name="date">The fixed day number.
964 /// <returns>An integer value giving the Julian year of the date.
966 public static int year_from_fixed(int date
) {
967 int approx
= CCMath
.div(4*(date
-epoch
)+1464, 1461);
968 return approx
<= 0 ? approx
- 1 : approx
;
972 /// The method computes the Julian year and month from a fixed day
975 /// <param name="month">The output value giving the Julian month.
977 /// <param name="year">The output value giving the Julian year.
979 /// <param name="date">An integer value specifying the fixed day
981 public static void my_from_fixed(out int month
, out int year
, int date
)
983 year
= year_from_fixed(date
);
985 int prior_days
= date
- fixed_from_dmy(1, (int)Month
.january
,
989 if (date
< fixed_from_dmy(1, (int)Month
.march
, year
)) {
991 } else if (is_leap_year(year
)) {
997 month
= CCMath
.div(12 * (prior_days
+ correction
) + 373, 367);
1002 /// The method computes the Julian year, month, and day from a
1003 /// fixed day number.
1005 /// <param name="day">The output value returning the day of the
1008 /// <param name="month">The output value giving the Julian month.
1010 /// <param name="year">The output value giving the Julian year.
1012 /// <param name="date">An integer value specifying the fixed day
1014 public static void dmy_from_fixed(out int day
, out int month
,
1015 out int year
, int date
)
1017 my_from_fixed(out month
, out year
, date
);
1018 day
= date
- fixed_from_dmy(1, month
, year
) + 1;
1021 /// <summary>A method computing the Julian month from a fixed
1024 /// <param name="date">An integer specifying the fixed day number.
1026 /// <returns>An integer value representing the Julian month.
1028 public static int month_from_fixed(int date
) {
1031 my_from_fixed(out month
, out year
, date
);
1036 /// A method computing the day of the month from a fixed day number.
1038 /// <param name="date">An integer specifying the fixed day number.
1040 /// <returns>An integer value representing the day of the month.
1042 public static int day_from_fixed(int date
) {
1047 dmy_from_fixed(out day
, out month
, out year
, date
);
1052 /// The method computes the difference between two Julian dates.
1054 /// <param name="dayA">The integer parameter gives the day of month
1055 /// of the first date.
1057 /// <param name="monthA">The integer parameter gives the Julian
1058 /// month of the first date.
1060 /// <param name="yearA">The integer parameter gives the Julian
1061 /// year of the first date.
1063 /// <param name="dayB">The integer parameter gives the day of month
1064 /// of the second date.
1066 /// <param name="monthB">The integer parameter gives the Julian
1067 /// month of the second date.
1069 /// <param name="yearB">The integer parameter gives the Julian
1070 /// year of the second date.
1072 /// <returns>An integer giving the difference of days from the first
1073 /// the second date.
1075 public static int date_difference(int dayA
, int monthA
, int yearA
,
1076 int dayB
, int monthB
, int yearB
)
1078 return fixed_from_dmy(dayB
, monthB
, yearB
) -
1079 fixed_from_dmy(dayA
, monthA
, yearA
);
1083 /// The method computes the number of the day in the year from
1086 /// <param name="day">An integer representing the day of the month,
1087 /// counting from 1.
1089 /// <param name="month">An integer representing the month in the
1092 /// <param name="year">An integer representing the Julian year.
1093 /// Negative values are allowed also.
1095 /// <returns>An integer value giving the number of the day in the
1096 /// Julian year, counting from 1.
1098 public static int day_number(int day
, int month
, int year
) {
1099 return date_difference(31, (int)Month
.december
, year
-1,
1104 /// The method computes the days remaining in the given Julian
1105 /// year from a Julian date.
1107 /// <param name="day">An integer representing the day of the month,
1108 /// counting from 1.
1110 /// <param name="month">An integer representing the month in the
1113 /// <param name="year">An integer representing the Julian year.
1114 /// Negative values are allowed also.
1116 /// <returns>An integer value giving the number of days remaining in
1117 /// the Julian year.
1119 public static int days_remaining(int day
, int month
, int year
) {
1120 return date_difference(day
, month
, year
,
1121 31, (int)Month
.december
, year
);
1123 } // class CCJulianCalendar
1126 /// A class encapsulating the functions of the Hebrew calendar as static
1131 /// This class is not compatible to
1132 /// <see cref="T:System.Globalization.HebrewCalendar"/>.
1134 /// <seealso cref="T:CCFixed"/>
1136 internal class CCHebrewCalendar
{
1137 /// <summary>An integer defining the epoch of the Hebrew calendar
1138 /// as fixed day number.</summary>
1139 /// <remarks>The epoch is October 10, 3761 B.C.E. (Julian).</remarks>
1140 const int epoch
= -1373427;
1142 /// <summary>The enumeration defines the months of the Gregorian
1146 /// The enumaration differs from .NET which defines Tishri as month 1.
1198 /// Adar I. Only in years with Adar II.
1202 /// Adar II. Only in years wirh Adar I.
1208 /// The method tells whether the year is a leap year.
1210 /// <param name="year">An integer representing the Hebrew year.
1212 /// <returns>A boolean which is true if <paramref name="year"/> is
1215 public static bool is_leap_year(int year
) {
1216 return CCMath
.mod(7*year
+1, 19) < 7;
1220 /// The Method gives the number of the last month in a year, which
1221 /// is equal with the number of month in a Hebrew year.
1223 /// <param name="year">An integer representing the Hebrew year.
1225 /// <returns>An integer giving the number of the last month of the
1226 /// Hebrew year, which is the same as the numbers of month in the
1229 public static int last_month_of_year(int year
) {
1230 return is_leap_year(year
) ? 13 : 12;
1234 /// <summary>The method is a helper function.</summary>
1235 /// <param name="year">An integer specifying the Hebrew year.
1237 /// <returns>An integer representing the number of elapsed days
1238 /// until the Hebrew year.</returns>
1239 public static int elapsed_days(int year
) {
1240 int months_elapsed
= CCMath
.div(235*year
-234, 19);
1242 int d
= CCMath
.div_mod(out r
, months_elapsed
, 1080);
1243 int parts_elapsed
= 204 + 793 * r
;
1244 int hours_elapsed
= 11 + 12 * months_elapsed
+
1245 793 * d
+ CCMath
.div(parts_elapsed
, 1080);
1247 int day
= 29*months_elapsed
+ CCMath
.div(hours_elapsed
, 24);
1249 if (CCMath
.mod(3*(day
+1), 7) < 3) {
1256 /// <summary>A method computing the delay of new year for the given
1259 /// <param name="year">An integer that gives the Hebrew year.
1261 /// <returns>The new year delay in days of the given Hebrew year.
1263 public static int new_year_delay(int year
) {
1264 int ny1
= elapsed_days(year
);
1265 int ny2
= elapsed_days(year
+1);
1267 if (ny2
- ny1
== 356) {
1270 int ny0
= elapsed_days(year
-1);
1271 if (ny1
- ny0
== 382) {
1278 /// The method computes the last day of month (nummer of days in a
1279 /// month) of the given Hebrew year.
1281 /// <param name="month">The Hebrew month, allowed value between
1282 /// One and Thirteen.
1284 /// <param name="year">An integer that gives the Hebrew year.
1286 /// <returns>The number of the last day of the month of the given
1287 /// Hebrew year, which gives automatically the number of days in the
1290 /// <exception cref="T:System.ArgumentOutOfRange.Exception">
1291 /// The exception is thrown if month not between One and Thirteen.
1293 public static int last_day_of_month(int month
, int year
) {
1294 if (month
< 1 || month
> 13)
1295 throw new System
.ArgumentOutOfRangeException("month",
1296 "Month should be between One and Thirteen.");
1302 if (!long_heshvan(year
))
1306 if (short_kislev(year
))
1311 if (!is_leap_year(year
))
1320 /// The functions checks whether the month Heshvan is a long one
1321 /// in the given Hebrew year.
1323 /// <param name="year">An integer that gives the Hebrew year.
1325 /// <returns>A boolean value: true if there is a long Heshvan
1326 /// in the given Hebrew year; false otherwise.
1328 public static bool long_heshvan(int year
) {
1329 return CCMath
.mod(days_in_year(year
), 10) == 5;
1333 /// The functions checks whether the month Kislev is a short one
1334 /// in the given Hebrew year.
1336 /// <param name="year">An integer that gives the Hebrew year.
1338 /// <returns>A boolean value: true if there is a short Kislev
1339 /// in the given Hebrew year; false otherwise.
1341 public static bool short_kislev(int year
) {
1342 return CCMath
.mod(days_in_year(year
), 10) == 3;
1346 /// The functions gives the number of days in the specified Hebrew
1349 /// <param name="year">An integer that gives the Hebrew year.
1351 /// <returns>The days of the Hebrew year as integer.
1353 public static int days_in_year(int year
) {
1354 return fixed_from_dmy(1, 7, year
+1) -
1355 fixed_from_dmy(1, 7, year
);
1359 /// The method returns the fixed day number of the given Hebrew
1362 /// <param name="day">An integer representing the day of the month,
1363 /// counting from 1.
1365 /// <param name="month">An integer representing the month in the
1368 /// <param name="year">An integer representing the Hebrew year.
1369 /// Non-positive values are allowed also.
1371 /// <returns>An integer value representing the fixed day number.
1373 public static int fixed_from_dmy(int day
, int month
, int year
) {
1376 k
+= elapsed_days(year
);
1377 k
+= new_year_delay(year
);
1380 int l
= last_month_of_year(year
);
1381 for (m
= 7; m
<= l
; m
++) {
1382 k
+= last_day_of_month(m
, year
);
1384 for (m
= 1; m
< month
; m
++) {
1385 k
+= last_day_of_month(m
, year
);
1389 for (m
= 7; m
< month
; m
++) {
1390 k
+= last_day_of_month(m
, year
);
1400 /// The method computes the Hebrew year from a fixed day number.
1402 /// <param name="date">The fixed day number.
1404 /// <returns>An integer value giving the Hebrew year of the date.
1406 public static int year_from_fixed(int date
) {
1407 int approx
= (int)System
.Math
.Floor(
1408 ((double)(date
- epoch
))/(35975351.0/98496.0));
1410 for (y
= approx
; date
>= fixed_from_dmy(1, 7, y
); y
++) {}
1415 /// The method computes the Hebrew year and month from a fixed day
1418 /// <param name="month">The output value giving the Hebrew month.
1420 /// <param name="year">The output value giving the Hebrew year.
1422 /// <param name="date">An integer value specifying the fixed day
1424 public static void my_from_fixed(out int month
, out int year
,
1427 year
= year_from_fixed(date
);
1429 int start
= date
< fixed_from_dmy(1, 1, year
) ? 7 : 1;
1432 date
> fixed_from_dmy(last_day_of_month(month
, year
),
1439 /// The method computes the Hebrew year, month, and day from a
1440 /// fixed day number.
1442 /// <param name="day">The output value returning the day of the
1445 /// <param name="month">The output value giving the Hebrew month.
1447 /// <param name="year">The output value giving the Hebrew year.
1449 /// <param name="date">An integer value specifying the fixed day
1451 public static void dmy_from_fixed(out int day
, out int month
,
1452 out int year
, int date
)
1454 my_from_fixed(out month
, out year
, date
);
1455 day
= date
- fixed_from_dmy(1, month
, year
) + 1;
1458 /// <summary>A method computing the Hebrew month from a fixed
1461 /// <param name="date">An integer specifying the fixed day number.
1463 /// <returns>An integer value representing the Hebrew month.
1465 public static int month_from_fixed(int date
) {
1468 my_from_fixed(out month
, out year
, date
);
1473 /// A method computing the day of the month from a fixed day number.
1475 /// <param name="date">An integer specifying the fixed day number.
1477 /// <returns>An integer value representing the day of the month.
1479 public static int day_from_fixed(int date
) {
1480 int day
, month
, year
;
1482 dmy_from_fixed(out day
, out month
, out year
, date
);
1487 /// The method computes the difference between two Hebrew dates.
1489 /// <param name="dayA">The integer parameter gives the day of month
1490 /// of the first date.
1492 /// <param name="monthA">The integer parameter gives the Hebrew
1493 /// month of the first date.
1495 /// <param name="yearA">The integer parameter gives the Hebrew
1496 /// year of the first date.
1498 /// <param name="dayB">The integer parameter gives the day of month
1499 /// of the second date.
1501 /// <param name="monthB">The integer parameter gives the Hebrew
1502 /// month of the second date.
1504 /// <param name="yearB">The integer parameter gives the Hebrew
1505 /// year of the second date.
1507 /// <returns>An integer giving the difference of days from the first
1508 /// the second date.
1510 public static int date_difference(int dayA
, int monthA
, int yearA
,
1511 int dayB
, int monthB
, int yearB
)
1513 return fixed_from_dmy(dayB
, monthB
, yearB
) -
1514 fixed_from_dmy(dayA
, monthA
, yearA
);
1518 /// The method computes the number of the day in the year from
1521 /// <param name="day">An integer representing the day of the month,
1522 /// counting from 1.
1524 /// <param name="month">An integer representing the month in the
1527 /// <param name="year">An integer representing the Hebrew year.
1529 /// <returns>An integer value giving the number of the day in the
1530 /// Hebrew year, counting from 1.
1532 public static int day_number(int day
, int month
, int year
) {
1533 return date_difference(1, 7, year
,
1534 day
, month
, year
) + 1;
1538 /// The method computes the days remaining in the given Hebrew
1539 /// year from a Hebrew date.
1541 /// <param name="day">An integer representing the day of the month,
1542 /// counting from 1.
1544 /// <param name="month">An integer representing the month in the
1547 /// <param name="year">An integer representing the Hebrew year.
1549 /// <returns>An integer value giving the number of days remaining in
1550 /// the Hebrew year.
1552 public static int days_remaining(int day
, int month
, int year
) {
1553 return date_difference(day
, month
, year
,
1556 } // class HebrewCalendar
1560 /// A class encapsulating the functions of the Islamic calendar as static
1564 /// <para>There is no difference here in using Hijri or Islamic calendar.
1566 /// <para>The epoch of the Islamic calendar isn't fixed, because we cannot
1567 /// surely say today, when the crescent of the new moon has been observed
1568 /// around the July 16, 622 C.E. Julian. Even today the start and end of
1569 /// the month Ramadan is defined by religous authorities. So the calendar
1570 /// can be offset by two days.
1573 /// We don't support the offset here, however we changed the epoch from
1574 /// "Calendrical Calculations" to value, that .Net seems to be using.
1577 /// This class is not compatible to
1578 /// <see cref="T:System.Globalization.HijriCalendar"/>.
1580 /// <seealso cref="T:CCFixed"/>
1582 internal class CCHijriCalendar
{
1583 /// <summary>An integer defining the epoch of the Gregorian calendar
1584 /// as fixed day number.</summary>
1587 /// The epoch is given as 16 July 622 C.E. Julian (R.D. 227015)
1588 /// in Calendrical Calculations, the approximate date of
1589 /// the emigration of
1590 /// Muhammed to Medina. However there is no way to determine today
1591 /// the observation of the crescent of the new moon in July 622 C.E.
1592 /// (Julian). So there is some variability in the epoch.
1593 /// Religous authorities determine the epoch by observing the
1594 /// crescent of the new moon for the month Ramadan, so there might
1595 /// be an offsets by two days of the epoch.
1598 /// supports an AddHijriDate parameter in the registry to adapt
1599 /// for it. It seems that the .NET implementation of
1600 /// HijriCalendar uses an epoch of 227014, so we use it here. The
1601 /// ArgumentOutOfRangeException gives July, 18 622 as epoch,
1602 /// which is 227014 supporting our theory.
1605 const int epoch
= 227014;
1607 /// <summary>The enumeration defines the months of the Islamic
1662 /// The method tells whether the year is a leap year.
1664 /// <param name="year">An integer representing the Islamic year.
1666 /// <returns>A boolean which is true if <paramref name="year"/> is
1669 public static bool is_leap_year(int year
) {
1670 return CCMath
.mod(14+11*year
, 30) < 11;
1674 /// The method returns the fixed day number of the given Islamic
1677 /// <param name="day">An integer representing the day of the month,
1678 /// counting from 1.
1680 /// <param name="month">An integer representing the month in the
1683 /// <param name="year">An integer representing the Islamic year.
1684 /// Non-positive values are allowed also.
1686 /// <returns>An integer value representing the fixed day number.
1688 public static int fixed_from_dmy(int day
, int month
, int year
) {
1690 k
+= 354 * (year
-1);
1691 k
+= CCMath
.div(3+11*year
, 30);
1692 k
+= (int)System
.Math
.Ceiling(29.5 * (double)(month
-1));
1699 /// The method computes the Islamic year from a fixed day number.
1701 /// <param name="date">The fixed day number.
1703 /// <returns>An integer value giving the Islamic year of the date.
1705 public static int year_from_fixed(int date
) {
1706 return CCMath
.div(30*(date
-epoch
)+10646, 10631);
1710 /// The method computes the Islamic year and month from a fixed day
1713 /// <param name="month">The output value giving the Islamic month.
1715 /// <param name="year">The output value giving the Islamic year.
1717 /// <param name="date">An integer value specifying the fixed day
1719 public static void my_from_fixed(out int month
, out int year
, int date
)
1721 year
= year_from_fixed(date
);
1723 int m
= 1+(int)System
.Math
.Ceiling(
1724 ((double)(date
-29-fixed_from_dmy(1,1,year
)))/29.5);
1726 month
= m
< 12 ? m
: 12;
1730 /// The method computes the Islamic year, month, and day from a
1731 /// fixed day number.
1733 /// <param name="day">The output value returning the day of the
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 dmy_from_fixed(out int day
, out int month
,
1743 out int year
, int date
)
1745 my_from_fixed(out month
, out year
, date
);
1746 day
= date
- fixed_from_dmy(1, month
, year
) + 1;
1749 /// <summary>A method computing the Islamic month from a fixed
1752 /// <param name="date">An integer specifying the fixed day number.
1754 /// <returns>An integer value representing the Islamic month.
1756 public static int month_from_fixed(int date
) {
1759 my_from_fixed(out month
, out year
, date
);
1764 /// A method computing the day of the month from a fixed day number.
1766 /// <param name="date">An integer specifying the fixed day number.
1768 /// <returns>An integer value representing the day of the month.
1770 public static int day_from_fixed(int date
) {
1775 dmy_from_fixed(out day
, out month
, out year
, date
);
1780 /// The method computes the difference between two Islamic dates.
1782 /// <param name="dayA">The integer parameter gives the day of month
1783 /// of the first date.
1785 /// <param name="monthA">The integer parameter gives the Islamic
1786 /// month of the first date.
1788 /// <param name="yearA">The integer parameter gives the Islamic
1789 /// year of the first date.
1791 /// <param name="dayB">The integer parameter gives the day of month
1792 /// of the second date.
1794 /// <param name="monthB">The integer parameter gives the Islamic
1795 /// month of the second date.
1797 /// <param name="yearB">The integer parameter gives the Islamic
1798 /// year of the second date.
1800 /// <returns>An integer giving the difference of days from the first
1801 /// the second date.
1803 public static int date_difference(int dayA
, int monthA
, int yearA
,
1804 int dayB
, int monthB
, int yearB
)
1806 return fixed_from_dmy(dayB
, monthB
, yearB
) -
1807 fixed_from_dmy(dayA
, monthA
, yearA
);
1811 /// The method computes the number of the day in the year from
1814 /// <param name="day">An integer representing the day of the month,
1815 /// counting from 1.
1817 /// <param name="month">An integer representing the month in the
1820 /// <param name="year">An integer representing the Islamic year.
1822 /// <returns>An integer value giving the number of the day in the
1823 /// Islamic year, counting from 1.
1825 public static int day_number(int day
, int month
, int year
) {
1826 return date_difference(31, 12, year
-1, day
, month
, year
);
1830 /// The method computes the days remaining in the given Islamic
1831 /// year from a Islamic date.
1833 /// <param name="day">An integer representing the day of the month,
1834 /// counting from 1.
1836 /// <param name="month">An integer representing the month in the
1839 /// <param name="year">An integer representing the Islamic year.
1840 /// Non-positive values are allowed also.
1842 /// <returns>An integer value giving the number of days remaining in
1843 /// the Islamic year.
1845 public static int days_remaining(int day
, int month
, int year
) {
1846 return date_difference(day
, month
, year
,31, 12, year
);
1848 } // class CCHijriCalendar
1850 internal class CCEastAsianLunisolarCalendar
1852 public static int fixed_from_dmy (int day
, int month
, int year
)
1856 k += 354 * (year - 1);
1857 k += CCMath.div (3+11*year, 30);
1858 k += (int) Math.Ceiling(29.53 * (double)(month-1));
1863 throw new Exception ("fixed_from_dmy");
1866 public static int year_from_fixed (int date
)
1868 throw new Exception ("year_from_fixed");
1871 public static void my_from_fixed(out int month
, out int year
, int date
)
1874 year = year_from_fixed (date);
1876 int m = 1+(int)System.Math.Ceiling(
1877 ((double)(date-29-fixed_from_dmy(1,1,year)))/29.5);
1879 month = m < 12 ? m : 12;
1881 throw new Exception ("my_from_fixed");
1884 public static void dmy_from_fixed(out int day
, out int month
,
1885 out int year
, int date
)
1888 my_from_fixed (out month, out year, date);
1889 day = date - fixed_from_dmy (1, month, year) + 1;
1891 throw new Exception ("dmy_from_fixed");
1894 public static DateTime
AddMonths (DateTime date
, int months
)
1897 throw new Exception ("AddMonths");
1900 public static DateTime
AddYears (DateTime date
, int years
)
1902 throw new Exception ("AddYears");
1905 public static int GetDayOfMonth (DateTime date
)
1907 throw new Exception ("GetDayOfMonth");
1910 public static int GetDayOfYear (DateTime date
)
1912 throw new Exception ("GetDayOfYear");
1915 public static int GetDaysInMonth (int gyear
, int month
)
1917 throw new Exception ("GetDaysInMonth");
1920 public static int GetDaysInYear (int year
)
1922 throw new Exception ("GetDaysInYear");
1925 public static int GetMonth (DateTime date
)
1927 throw new Exception ("GetMonth");
1930 public static bool IsLeapMonth (int gyear
, int month
)
1932 int goldenNumber
= gyear
% 19;
1937 for (int y
= 0; y
< goldenNumber
; y
++) {
1938 for (int l
= 0, m
= 1; m
<= month
; m
++) {
1942 if (y
== goldenNumber
&& m
== month
)
1956 public static bool IsLeapYear (int gyear
)
1959 // FIXME: it is still wrong.
1962 case 0: case 3: case 6: case 9: case 11: case 14: case 17:
1968 int goldenNumber = (gyear - 1900) % 19;
1971 while (goldenNumber-- >= 0) {
1981 public static DateTime
ToDateTime (int year
, int month
, int day
, int hour
, int minute
, int second
, int millisecond
)
1983 throw new Exception ("ToDateTime");
1988 /// A class that supports the Gregorian based calendars with other eras
1989 /// (e.g. <see cref="T:System.Gloablization.JapaneseCalendar"/>).
1991 [System
.Serializable
]
1992 internal class CCGregorianEraHandler
{
1994 /// A struct that represents a single era.
1996 [System
.Serializable
]
1999 /// The integer number identifying the era.
2004 /// A get-only property that gives the era integer number.
2006 public int Nr { get { return _nr; }
}
2008 /// <summary>This integer gives the first day of the era as
2009 /// fixed day number.
2011 private int _start
; // inclusive
2013 /// This integer gives the gregorian year of the
2014 /// <see cref="M:_start"/> value.
2016 private int _gregorianYearStart
;
2018 /// This integer gives the last day of the era as fixed day
2021 private int _end
; // inclusive
2023 /// This integer gives the largest year number of this era.
2025 private int _maxYear
;
2028 /// This constructor creates the era structure.
2030 /// <param name="nr">The integer number of the era.
2032 /// <param name="start">The fixed day number defining the
2033 /// first day of the era.
2035 /// <param name="end">The fixed day number that defines the
2036 /// last day of the era.
2038 public Era(int nr
, int start
, int end
) {
2040 throw new System
.ArgumentException(
2041 "Era number shouldn't be zero.");
2044 throw new System
.ArgumentException(
2045 "Era should start before end.");
2050 _gregorianYearStart
=
2051 CCGregorianCalendar
.year_from_fixed(_start
);
2052 int gregorianYearEnd
=
2053 CCGregorianCalendar
.year_from_fixed(_end
);
2054 _maxYear
= gregorianYearEnd
- _gregorianYearStart
+ 1;
2058 /// This method computes the Gregorian year from the year
2061 /// <param name="year">An integer giving the year in the
2065 /// The Gregorian year as integer.
2067 /// <exception cref="T:System.ArgumentOutOfRangeException">
2068 /// The exception is thrown if the year isn't valid in this
2071 public int GregorianYear(int year
) {
2072 if (year
< 1 || year
> _maxYear
) {
2073 System
.IO
.StringWriter sw
=
2074 new System
.IO
.StringWriter();
2076 "Valid Values are between " +
2077 "{0} and {1}, inclusive.",
2079 throw new System
.ArgumentOutOfRangeException(
2080 "year", sw
.ToString());
2082 return year
+ _gregorianYearStart
- 1;
2086 /// This function checks wether the given fixed day number is
2087 /// ion the time span of the era.
2089 /// <param name="date">An integer giving the fixed day
2092 /// <returns>A boolean: true if the argument is in the time
2093 /// span of the era.
2095 public bool Covers(int date
) {
2096 return _start
<= date
&& date
<= _end
;
2100 /// This function returns the year of the era and sets
2101 /// the era in an output parameter.
2103 /// <param name="era">An output parameter returning the
2106 /// <param name="date">An integer giving the fixed day
2109 /// <returns>An integer giving the year of the era.
2111 /// <exception cref="T:System.ArgumentOutOfRangeException">
2112 /// The exception is thrown if date is outside of the time
2113 /// span of the era.
2115 public int EraYear(out int era
, int date
) {
2117 throw new System
.ArgumentOutOfRangeException(
2119 "Time was out of Era range.");
2121 CCGregorianCalendar
.year_from_fixed(date
);
2123 return gregorianYear
- _gregorianYearStart
+ 1;
2128 /// A private member storing the eras in a
2129 /// <see cref="T:System.Collections.SortedList"/>.
2131 private SortedList _Eras
;
2134 /// The property returns the era numbers as an array of integers.
2138 int[] a
= new int[_Eras
.Count
];
2140 for (int i
= 0; i
< _Eras
.Count
; i
++) {
2141 Era e
= (Era
)_Eras
.GetByIndex(i
);
2152 public CCGregorianEraHandler() {
2153 _Eras
= new SortedList();
2157 /// Method adds an era to the GregorianEraHandler instance.
2159 /// <param name="nr">The integer number of the era.
2161 /// <param name="rd_start">The fixed day number defining the
2162 /// first day of the era.
2164 /// <param name="rd_end">The fixed day number that defines the
2165 /// last day of the era.
2167 public void appendEra(int nr
, int rd_start
, int rd_end
) {
2168 Era era
= new Era(nr
, rd_start
, rd_end
);
2169 _Eras
[(System
.Object
)nr
] = era
;
2172 /// Method adds a yet not-ended era to the GregorianEraHandler
2175 /// <param name="nr">The integer number of the era.
2177 /// <param name="rd_start">The fixed day number defining the
2178 /// first day of the era.
2180 public void appendEra(int nr
, int rd_start
) {
2181 appendEra(nr
, rd_start
,
2182 CCFixed
.FromDateTime(DateTime
.MaxValue
));
2186 /// This method computes the Gregorian year from the year
2187 /// of the given era.
2189 /// <param name="year">An integer giving the year in the
2192 /// <param name="era">An integer giving the era number.
2195 /// The Gregorian year as integer.
2197 /// <exception cref="T:System.ArgumentOutOfRangeException">
2198 /// The exception is thrown if the year isn't valid in this
2201 public int GregorianYear(int year
, int era
) {
2202 Era e
= (Era
)_Eras
[(System
.Object
)era
];
2203 return e
.GregorianYear(year
);
2207 /// This function returns the year of the era and sets
2208 /// the era in an output parameter.
2210 /// <param name="era">An output parameter returning the
2213 /// <param name="date">An integer giving the fixed day
2216 /// <returns>An integer giving the year of the era.
2218 /// <exception cref="T:System.ArgumentOutOfRangeException">
2219 /// The exception is thrown if the fixed day number is outside of the
2220 /// time spans of all eras.
2222 public int EraYear(out int era
, int date
)
2224 IList list
= _Eras
.GetValueList();
2226 foreach (Era e
in list
) {
2228 return e
.EraYear(out era
, date
);
2231 throw new System
.ArgumentOutOfRangeException("date",
2232 "Time value was out of era range.");
2236 /// The method checks whether a given
2237 /// <see cref="T:System.DateTime"/> is covered by any era.
2239 /// <param name="time">A
2240 /// <see cref="T:System.DateTime"/> giving the date and time.
2242 /// <exception cref="T:System.ArgumentOutOfRangeException">
2243 /// The exception is thrown if the argument isn't inside the time
2244 /// span of any era.
2246 public void CheckDateTime(System
.DateTime time
) {
2247 int date
= CCFixed
.FromDateTime(time
);
2249 if (!ValidDate(date
))
2250 throw new System
.ArgumentOutOfRangeException("time",
2251 "Time value was out of era range.");
2255 /// The method tests whether a given
2256 /// fixed day number is covered by any era.
2258 /// <param name="date">An integer representing the fixed day number.
2260 /// <returns> A boolean is returned: true if the argument is inside
2261 /// the time span of one era; false otherwise.
2263 public bool ValidDate(int date
) {
2264 IList list
= _Eras
.GetValueList();
2266 foreach (Era e
in list
) {
2275 /// The method tests, whether the era number does exist.
2277 /// <param name="era">An integer giving the era number.
2279 /// <returns>A boole value: True if the era number does exist;
2280 /// false otherwise.
2282 public bool ValidEra(int era
) {
2283 return _Eras
.Contains((System
.Object
)era
);
2285 } // class CCGregorianEraHandler
2288 // FIXME: remove this class. It should be identical to CCGregorianEraHandler
2289 [System
.Serializable
]
2290 internal class CCEastAsianLunisolarEraHandler
2295 private int _nr
; // era index
2301 private int _start
; // inclusive
2302 private int _gregorianYearStart
;
2303 private int _end
; // inclusive
2304 private int _maxYear
;
2306 public Era (int nr
, int start
, int end
)
2309 throw new ArgumentException ("Era number shouldn't be zero.");
2312 throw new ArgumentException ("Era should start before end.");
2316 _gregorianYearStart
= CCGregorianCalendar
.year_from_fixed (_start
);
2317 int gregorianYearEnd
= CCGregorianCalendar
.year_from_fixed (_end
);
2318 _maxYear
= gregorianYearEnd
- _gregorianYearStart
+ 1;
2321 public int GregorianYear (int year
)
2323 if (year
< 1 || year
> _maxYear
)
2324 throw new ArgumentOutOfRangeException ("year", String
.Format ("Valid Values are between {0} and {1}, inclusive.", 1, _maxYear
));
2325 return year
+ _gregorianYearStart
- 1;
2328 public bool Covers (int date
) {
2329 return _start
<= date
&& date
<= _end
;
2332 public int EraYear (out int era
, int date
) {
2334 throw new ArgumentOutOfRangeException ("date", "Time was out of Era range.");
2335 int gregorianYear
= CCGregorianCalendar
.year_from_fixed (date
);
2337 return gregorianYear
- _gregorianYearStart
+ 1;
2341 private SortedList _Eras
;
2346 int[] a
= new int [_Eras
.Count
];
2347 for (int i
= 0; i
< _Eras
.Count
; i
++) {
2348 Era e
= (Era
) _Eras
.GetByIndex (i
);
2355 public CCEastAsianLunisolarEraHandler ()
2357 _Eras
= new SortedList ();
2360 public void appendEra (int nr
, int rd_start
, int rd_end
)
2362 Era era
= new Era (nr
, rd_start
, rd_end
);
2366 public void appendEra (int nr
, int rd_start
)
2368 appendEra (nr
, rd_start
, CCFixed
.FromDateTime (DateTime
.MaxValue
));
2371 public int GregorianYear (int year
, int era
)
2373 Era e
= (Era
) _Eras
[era
];
2374 return e
.GregorianYear (year
);
2377 public int EraYear (out int era
, int date
)
2379 foreach (Era e
in _Eras
.Values
)
2380 if (e
.Covers (date
))
2381 return e
.EraYear (out era
, date
);
2383 throw new ArgumentOutOfRangeException ("date", "Time value was out of era range.");
2386 public void CheckDateTime (DateTime time
)
2388 int date
= CCFixed
.FromDateTime (time
);
2390 if (!ValidDate (date
))
2391 throw new ArgumentOutOfRangeException ("time", "Time value was out of era range.");
2394 public bool ValidDate (int date
)
2396 foreach (Era e
in _Eras
.Values
) {
2397 if (e
.Covers (date
))
2403 public bool ValidEra (int era
)
2405 return _Eras
.Contains (era
);
2409 } // namespace System.Globalization