1 // System.Globalization.HebrewCalendar.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
{
33 using System
.Runtime
.InteropServices
;
36 /// This is the Hebrew calendar.
39 /// <para>The Hebrew calendar supports only years between 5343 A.M. and
40 /// 6000 A.M. This has been done to be compatible with .NET.
42 /// <para>The implementation uses the
43 /// <see cref="N:CalendricalCalculations"/> namespace.
47 [MonoLimitation ("Serialization format not compatible with.NET")]
48 public class HebrewCalendar
: Calendar
{
52 public HebrewCalendar() {
53 M_AbbrEraNames
= new string[] {"A.M."}
;
54 M_EraNames
= new string[] {"Anno Mundi"}
;
55 if (twoDigitYearMax
== 99)
56 twoDigitYearMax
= 5790;
60 /// The era number for the Anno Mundi (A.M.) era, called
63 public static readonly int HebrewEra
= 1;
67 /// <see cref="T:System.DateTime"/> ticks for first day of year
70 internal const long M_MinTicks
= 499147488000000000L;
73 /// <see cref="T:System.DateTime"/> ticks for the last day of year
76 internal const long M_MaxTicks
= 706783967999999999L;
78 /// The minimum year in the A.M. era supported.
80 internal const int M_MinYear
= 5343;
82 /// The maximum year supported in the A.M. era.
84 internal override int M_MaxYear
{
88 /// <value>Overridden. Gives the eras supported by the Gregorian
89 /// calendar as an array of integers.
91 public override int[] Eras
{
93 return new int[] { HebrewEra }
;
97 public override int TwoDigitYearMax
100 return twoDigitYearMax
;
104 M_ArgumentInRange ("value", value, M_MinYear
, M_MaxYear
);
106 twoDigitYearMax
= value;
111 /// A protected member checking a
112 /// <see cref="T:System.DateTime"/> value.
114 /// <param name="time">The
115 /// <see cref="T:System.DateTime"/>
118 /// <exception cref="T:System.ArgumentOutOfRangeException">
119 /// The exception is thrown if the
120 /// <see cref="T:System.DateTime"/> parameter is not in the years
121 /// between 5343 A.M. and 6000 A.M., inclusive.
123 internal void M_CheckDateTime(DateTime time
) {
124 if (time
.Ticks
< M_MinTicks
|| time
.Ticks
> M_MaxTicks
)
125 throw new ArgumentOutOfRangeException(
127 "Only hebrew years between 5343 and 6000," +
128 " inclusive, are supported.");
132 /// A protected method checking the era number.
134 /// <param name="era">The era number.</param>
135 /// <exception name="T:System.ArgumentException">
136 /// The exception is thrown if the era is not equal
137 /// <see cref="F:HebrewEra"/>.
139 internal void M_CheckEra(ref int era
) {
140 if (era
== CurrentEra
)
142 if (era
!= HebrewEra
)
143 throw new ArgumentException("Era value was not valid.");
147 /// A protected method checking calendar year and the era number.
149 /// <param name="year">An integer representing the calendar year.
151 /// <param name="era">The era number.</param>
152 /// <exception cref="T:System.ArgumentException">
153 /// The exception is thrown if the era is not equal
154 /// <see cref="F:HebrewEra"/>.
156 /// <exception cref="T:System.ArgumentOutOfRangeException">
157 /// The exception is thrown if the calendar year is outside of
158 /// the allowed range.
160 internal override void M_CheckYE(int year
, ref int era
) {
162 if (year
< M_MinYear
|| year
> M_MaxYear
)
163 throw new ArgumentOutOfRangeException(
165 "Only hebrew years between 5343 and 6000," +
166 " inclusive, are supported.");
170 /// A protected method checking the calendar year, month, and
173 /// <param name="year">An integer representing the calendar year.
175 /// <param name="month">An integer giving the calendar month.
177 /// <param name="era">The era number.</param>
178 /// <exception cref="T:System.ArgumentException">
179 /// The exception is thrown if the era is not equal
180 /// <see cref="F:HebrewEra"/>.
182 /// <exception cref="T:System.ArgumentOutOfRangeException">
183 /// The exception is thrown if the calendar year or month is
184 /// outside of the allowed range.
186 internal void M_CheckYME(int year
, int month
, ref int era
) {
187 M_CheckYE(year
, ref era
);
188 int l
= CCHebrewCalendar
.last_month_of_year(year
);
189 if (month
< 1 || month
> l
) {
190 StringWriter sw
= new StringWriter();
191 sw
.Write("Month must be between 1 and {0}.", l
);
192 throw new ArgumentOutOfRangeException("month",
198 /// A protected method checking the calendar day, month, and year
199 /// and the era number.
201 /// <param name="year">An integer representing the calendar year.
203 /// <param name="month">An integer giving the calendar month.
205 /// <param name="day">An integer giving the calendar day.
207 /// <param name="era">The era number.</param>
208 /// <exception cref="T:System.ArgumentException">
209 /// The exception is thrown if the era is not equal
210 /// <see cref="F:HebrewEra"/>.
212 /// <exception cref="T:System.ArgumentOutOfRangeException">
213 /// The exception is thrown if the calendar year, month, or day is
214 /// outside of the allowed range.
216 internal void M_CheckYMDE(int year
, int month
, int day
,
219 M_CheckYME(year
, month
, ref era
);
220 M_ArgumentInRange("day", day
, 1, GetDaysInMonth(year
, month
,
226 /// Overrideden. Adds months to a given date.
228 /// <param name="time">The
229 /// <see cref="T:System.DateTime"/> to which to add
232 /// <param name="months">The number of months to add.</param>
233 /// <returns>A new <see cref="T:System.DateTime"/> value, that
234 /// results from adding <paramref name="months"/> to the specified
235 /// DateTime.</returns>
236 /// <exception cref="T:System.ArgumentOutOfRangeException">
237 /// The exception is thrown if the
238 /// <see cref="T:System.DateTime"/> return value is not in the years
239 /// between 5343 A.M. and 6000 A.M., inclusive.
241 public override DateTime
AddMonths(DateTime time
, int months
) {
248 int rd
= CCFixed
.FromDateTime(time
);
249 CCHebrewCalendar
.dmy_from_fixed(
250 out d
, out m
, out y
, rd
);
260 m
= GetMonthsInYear(y
);
266 int my
= GetMonthsInYear(y
);
267 if (m
+months
<= my
) {
277 t
= ToDateTime(y
, m
, d
, 0, 0, 0, 0);
278 t
= t
.Add(time
.TimeOfDay
);
285 /// Overridden. Adds years to a given date.
287 /// <param name="time">The
288 /// <see cref="T:System.DateTime"/> to which to add
291 /// <param name="years">The number of years to add.</param>
292 /// <returns>A new <see cref="T:System.DateTime"/> value, that
293 /// results from adding <paramref name="years"/> to the specified
294 /// DateTime.</returns>
295 /// <exception cref="T:System.ArgumentOutOfRangeException">
296 /// The exception is thrown if the
297 /// <see cref="T:System.DateTime"/> return value is not in the years
298 /// between 5343 A.M. and 6000 A.M., inclusive.
300 public override DateTime
AddYears(DateTime time
, int years
) {
301 int rd
= CCFixed
.FromDateTime(time
);
302 int day
, month
, year
;
303 CCHebrewCalendar
.dmy_from_fixed(
304 out day
, out month
, out year
, rd
);
306 rd
= CCHebrewCalendar
.fixed_from_dmy(day
, month
, year
);
307 DateTime t
= CCFixed
.ToDateTime(rd
);
308 t
= t
.Add(time
.TimeOfDay
);
314 /// Overriden. Gets the day of the month from
315 /// <paramref name="time"/>.
317 /// <param name="time">The
318 /// <see cref="T:System.DateTime"/> that specifies a
321 /// <returns>An integer giving the day of months, starting with 1.
323 /// <exception cref="T:System.ArgumentOutOfRangeException">
324 /// The exception is thrown if the
325 /// <see cref="T:System.DateTime"/> parameter is not in the years
326 /// between 5343 A.M. and 6000 A.M., inclusive.
328 public override int GetDayOfMonth(DateTime time
) {
329 M_CheckDateTime(time
);
330 int rd
= CCFixed
.FromDateTime(time
);
331 return CCHebrewCalendar
.day_from_fixed(rd
);
335 /// Overriden. Gets the day of the week from the specified date.
337 /// <param name="time">The
338 /// <see cref="T:System.DateTime"/> that specifies a
341 /// <returns>An integer giving the day of months, starting with 1.
343 /// <exception cref="T:System.ArgumentOutOfRangeException">
344 /// The exception is thrown if the
345 /// <see cref="T:System.DateTime"/> parameter is not in the years
346 /// between 5343 A.M. and 6000 A.M., inclusive.
348 public override DayOfWeek
GetDayOfWeek(DateTime time
) {
349 M_CheckDateTime(time
);
350 int rd
= CCFixed
.FromDateTime(time
);
351 return (DayOfWeek
)CCFixed
.day_of_week(rd
);
355 /// Overridden. Gives the number of the day in the year.
357 /// <param name="time">The
358 /// <see cref="T:System.DateTime"/> that specifies a
361 /// <returns>An integer representing the day of the year,
362 /// starting with 1.</returns>
363 /// <exception cref="T:System.ArgumentOutOfRangeException">
364 /// The exception is thrown if the
365 /// <see cref="T:System.DateTime"/> parameter is not in the years
366 /// between 5343 A.M. and 6000 A.M., inclusive.
368 public override int GetDayOfYear(DateTime time
) {
369 M_CheckDateTime(time
);
370 int rd
= CCFixed
.FromDateTime(time
);
371 int year
= CCHebrewCalendar
.year_from_fixed(rd
);
372 int rd1_7
= CCHebrewCalendar
.fixed_from_dmy(1, 7, year
);
373 return rd
- rd1_7
+ 1;
377 /// The method maps a .NET Hebrew month to a Calencdrical
378 /// Calculations Hebrew month.
380 /// <param name="month">An integer representing a month in .NET
381 /// counting (starting with Tishri).
383 /// <param name="year">An integer representing the Hebrew year.
385 /// <returns>The Hebrew month in Calendrical Calculations counting,
386 /// staring with the Hebrew month Nisan.
390 /// In .NET the month counting starts with the Hebrew month Tishri.
391 /// Calendrical Calculations starts with the month Nisan. So we must
395 internal int M_CCMonth(int month
, int year
) {
400 int l
= CCHebrewCalendar
.last_month_of_year(year
);
405 return month
<= 7 ? 6+month
: month
-7;
411 /// The method maps a Calendrical Calculations Hebrew month
412 /// to a .NET Hebrew month.
414 /// <param name="ccmonth">An integer representing a month in
415 /// Calendrical Calculations counting, starting with Nisan.
417 /// <param name="year">An integer representing the Hebrew year.
419 /// <returns>The Hebrew month in .NET counting,
420 /// staring with the Hebrew month Tishri.
424 /// In .NET the month counting starts with the Hebrew month Tishri.
425 /// Calendrical Calculations starts with the month Tisan. So we must
429 internal int M_Month(int ccmonth
, int year
) {
433 int l
= CCHebrewCalendar
.last_month_of_year(year
);
434 return ccmonth
+ (l
== 12 ? 6 : 7);
439 /// Overridden. Gives the number of days in the specified month
440 /// of the given year and era.
442 /// <param name="year">An integer that gives the year.
444 /// <param name="month">An integer that gives the month, starting
446 /// <param name="era">An integer that gives the era of the specified
448 /// <returns>An integer that gives the number of days of the
449 /// specified month.</returns>
450 /// <exception cref="T:System.ArgumentOutOfRangeException">
451 /// The exception is thrown, if <paramref name="month"/>,
452 /// <paramref name="year"/> ,or <paramref name="era"/> is outside
453 /// the allowed range.
455 public override int GetDaysInMonth(int year
, int month
, int era
) {
456 M_CheckYME(year
, month
, ref era
);
457 int ccmonth
= M_CCMonth(month
, year
);
458 return CCHebrewCalendar
.last_day_of_month(ccmonth
, year
);
462 /// Overridden. Gives the number of days of the specified
463 /// year of the given era.
465 /// <param name="year">An integer that specifies the year.
467 /// <param name="era">An ineger that specifies the era.
469 /// <returns>An integer that gives the number of days of the
470 /// specified year.</returns>
471 /// <exception cref="T:System.ArgumentOutOfRangeExceiption">
472 /// The exception is thrown, if
473 /// <paramref name="year"/> or <paramref name="era"/> are outside the
476 public override int GetDaysInYear(int year
, int era
) {
477 M_CheckYE(year
, ref era
);
478 int rd1
= CCHebrewCalendar
.fixed_from_dmy(1, 7, year
);
479 int rd2
= CCHebrewCalendar
.fixed_from_dmy(1, 7, year
+1);
485 /// Overridden. Gives the era of the specified date.
487 /// <param name="time">The
488 /// <see cref="T:System.DateTime"/> that specifies a
491 /// <returns>An integer representing the era of the calendar.
493 /// <exception cref="T:System.ArgumentOutOfRangeException">
494 /// The exception is thrown if the
495 /// <see cref="T:System.DateTime"/> parameter is not in the years
496 /// between 5343 A.M. and 6000 A.M., inclusive.
498 public override int GetEra(DateTime time
) {
499 M_CheckDateTime(time
);
503 public override int GetLeapMonth (int year
, int era
)
505 return IsLeapMonth (year
, 7, era
) ? 7 : 0;
509 /// Overridden. Gives the number of the month of the specified
512 /// <param name="time">The
513 /// <see cref="T:System.DateTime"/> that specifies a
516 /// <returns>An integer representing the month,
517 /// starting with 1.</returns>
518 /// <exception cref="T:System.ArgumentOutOfRangeException">
519 /// The exception is thrown if the
520 /// <see cref="T:System.DateTime"/> parameter is not in the years
521 /// between 5343 A.M. and 6000 A.M., inclusive.
523 public override int GetMonth(DateTime time
) {
524 M_CheckDateTime(time
);
525 int rd
= CCFixed
.FromDateTime(time
);
527 CCHebrewCalendar
.my_from_fixed(out ccmonth
, out year
, rd
);
528 return M_Month(ccmonth
, year
);
532 /// Overridden. Gives the number of months in the specified year
535 /// <param name="year">An integer that specifies the year.
537 /// <param name="era">An integer that specifies the era.
539 /// <returns>An integer that gives the number of the months in the
540 /// specified year.</returns>
541 /// <exception cref="T:System.ArgumentOutOfRangeException">
542 /// The exception is thrown, if the year or the era are not valid.
544 public override int GetMonthsInYear(int year
, int era
) {
545 M_CheckYE(year
, ref era
);
546 return CCHebrewCalendar
.last_month_of_year(year
);
550 /// Overridden. Gives the number of the year of the specified
553 /// <param name="time">The
554 /// <see cref="T:System.DateTime"/> that specifies a
557 /// <returns>An integer representing the year,
558 /// starting with 1.</returns>
559 /// <exception cref="T:System.ArgumentOutOfRangeException">
560 /// The exception is thrown if the
561 /// <see cref="T:System.DateTime"/> parameter is not in the years
562 /// between 5343 A.M. and 6000 A.M., inclusive.
564 public override int GetYear(DateTime time
) {
565 M_CheckDateTime(time
);
566 int rd
= CCFixed
.FromDateTime(time
);
567 return CCHebrewCalendar
.year_from_fixed(rd
);
571 /// Overridden. Tells whether the given day
574 /// <param name="year">An integer that specifies the year in the
577 /// <param name="month">An integer that specifies the month.
579 /// <param name="day">An integer that specifies the day.
581 /// <param name="era">An integer that specifies the era.
583 /// <returns>A boolean that tells whether the given day is a leap
586 /// <exception cref="T:System.ArgumentOutOfRangeException">
587 /// The exception is thrown, if the year, month, day, or era is not
590 /// <remarks>All days in Adar II are viewed as leap days and the
591 /// last day of Adar I.
593 public override bool IsLeapDay(int year
, int month
, int day
, int era
)
595 M_CheckYMDE(year
, month
, day
, ref era
);
596 return IsLeapYear(year
) &&
597 (month
== 7 || (month
== 6 && day
== 30));
601 /// Overridden. Tells whether the given month
604 /// <param name="year">An integer that specifies the year in the
607 /// <param name="month">An integer that specifies the month.
609 /// <param name="era">An integer that specifies the era.
611 /// <returns>A boolean that tells whether the given month is a leap
614 /// <exception cref="T:System.ArgumentOutOfRangeException">
615 /// The exception is thrown, if the year, month, or era is not
619 /// Adar II is viewed as leap month.
621 public override bool IsLeapMonth(int year
, int month
, int era
) {
622 M_CheckYME(year
, month
, ref era
);
623 return IsLeapYear(year
) && month
== 7;
627 /// Overridden. Tells whether the given year
630 /// <param name="year">An integer that specifies the year in the
633 /// <param name="era">An integer that specifies the era.
635 /// <returns>A boolean that tells whether the given year is a leap
638 /// <exception cref="T:System.ArgumentOutOfRangeException">
639 /// The exception is thrown, if the year or era is not
642 public override bool IsLeapYear(int year
, int era
) {
643 M_CheckYE(year
, ref era
);
644 return CCHebrewCalendar
.is_leap_year(year
);
648 /// Overridden. Creates the
649 /// <see cref="T:System.DateTime"/> from the parameters.
651 /// <param name="year">An integer that gives the year in the
652 /// <paramref name="era"/>.
654 /// <param name="month">An integer that specifies the month.
656 /// <param name="day">An integer that specifies the day.
658 /// <param name="hour">An integer that specifies the hour.
660 /// <param name="minute">An integer that specifies the minute.
662 /// <param name="second">An integer that gives the second.
664 /// <param name="milliseconds">An integer that gives the
667 /// <param name="era">An integer that specifies the era.
670 /// <see cref="T:system.DateTime"/> representig the date and time.
672 /// <exception cref="T:System.ArgumentOutOfRangeException">
673 /// The exception is thrown, if at least one of the parameters
676 public override DateTime
ToDateTime(int year
, int month
, int day
,
677 int hour
, int minute
, int second
, int millisecond
,
680 M_CheckYMDE(year
, month
, day
, ref era
);
681 M_CheckHMSM(hour
, minute
, second
, millisecond
);
682 int ccm
= M_CCMonth(month
, year
);
683 int rd
= CCHebrewCalendar
.fixed_from_dmy(day
, ccm
, year
);
684 return CCFixed
.ToDateTime(rd
,
685 hour
, minute
, second
, millisecond
);
688 public override int ToFourDigitYear (int year
)
690 M_ArgumentInRange ("year", year
, 0, M_MaxYear
- 1);
692 int baseExtra
= this.twoDigitYearMax
% 100;
693 int baseCentury
= this.twoDigitYearMax
- baseExtra
;
697 if (year
<= baseExtra
)
698 return baseCentury
+ year
;
700 return baseCentury
+ year
- 100;
703 public override CalendarAlgorithmType AlgorithmType
{
705 return CalendarAlgorithmType
.LunisolarCalendar
;
710 static DateTime Min
= new DateTime (1583, 1, 1, 0, 0, 0);
711 static DateTime Max
= new DateTime (2239, 9, 29, 11, 59, 59);
713 public override DateTime MinSupportedDateTime
{
719 public override DateTime MaxSupportedDateTime
{
724 } // class HebrewCalendar
726 } // namespace System.Globalization