GenericParameter.cs: override Module properly
[mcs.git] / class / corlib / System.Globalization / Calendar.cs
blobd4d8bb64f11d7873f3cb50ea6b090b48f507bdec
1 // System.Globalization.Calendar.cs
2 //
3 // (C) Ulrich Kunitz 2002
4 //
6 //
7 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 namespace System.Globalization {
31 using System;
32 using System.IO;
33 using System.Runtime.InteropServices;
35 /// <remarks>
36 /// The class serves as a base class for calendar classes.
37 /// </remarks>
38 [Serializable]
39 [ComVisible (true)]
40 public abstract class Calendar : ICloneable
42 /// <value>An protected integer property that gives the number of
43 /// days in a week. It might be overridden.</value>
44 internal virtual int M_DaysInWeek
46 get { return 7; }
49 /// <summary>
50 /// The protected method creates the string used in the
51 /// <see cref="T:System.ArgumentOutOfRangeException"/>
52 /// </summary>
53 /// <param name="a">An object that represents the smallest
54 /// allowable value.</param>
55 /// <param name="b">An object that represents the greatest allowable
56 /// value.</param>
57 /// <returns>The string used in the
58 /// <see cref="T:System.ArgumentOutOfRangeException"/>
59 /// </returns>
60 internal string M_ValidValues(object a, object b)
62 StringWriter sw = new StringWriter();
63 sw.Write("Valid values are between {0} and {1}, inclusive.",
64 a, b);
65 return sw.ToString();
68 /// <summary>
69 /// The protected method checks wether the parameter
70 /// <paramref name="arg"/> is in the allowed range.
71 /// </summary>
72 /// <param name="param">A string that gives the name of the
73 /// parameter to check.</param>
74 /// <param name="arg">An integer that gives the value to check.
75 /// </param>
76 /// <param name="a">An integer that represents the smallest allowed
77 /// value.</param>
78 /// <param name="b">An integer that represents the greatest allowed
79 /// value.</param>
80 /// <exception cref="T:System.ArgumentOutOfRangeException">
81 /// The exception is thrown, if the <paramref name="arg"/> is outside
82 /// the allowed range.
83 /// </exception>
84 internal void M_ArgumentInRange(string param, int arg, int a, int b)
86 if (a <= arg && arg <= b)
87 return;
88 throw new ArgumentOutOfRangeException(param, M_ValidValues(a, b));
91 /// <summary>
92 /// The protected method, that checks whether
93 /// <paramref name="hour"/>, <paramref name="minute"/>,
94 /// <paramref name="second"/>, and <parameref name="millisecond"/>
95 /// are in their valid ranges
96 /// </summary>
97 /// <param name="hour">An integer that represents a hour,
98 /// should be between 0 and 23.</param>
99 /// <param name="minute">An integer that represents a minute,
100 /// should be between 0 and 59.</param>
101 /// <param name="second">An integer that represents a second,
102 /// should be between 0 and 59.</param>
103 /// <param name="milliseconds">An integer that represents a number
104 /// of milliseconds, should be between 0 and 999999.</param>
105 /// <exception cref="T:System.ArgumentOutOfRangeException">
106 /// The Exception is thrown, if one of the parameter is outside the
107 /// allowed the range.
108 /// </exception>
109 internal void M_CheckHMSM(int hour, int minute, int second,
110 int milliseconds)
112 M_ArgumentInRange("hour", hour, 0, 23);
113 M_ArgumentInRange("minute", minute, 0, 59);
114 M_ArgumentInRange("second", second, 0, 59);
115 M_ArgumentInRange("milliseconds", milliseconds, 0, 999999);
118 /// <value>
119 /// A represantation of the CurrentEra.
120 /// </value>
121 public const int CurrentEra = 0;
123 /// <value>When overridden gives the eras supported by the
124 /// calendar as an array of integers.
125 /// </value>
126 public abstract int[] Eras { get; }
128 [NonSerialized]
129 bool m_isReadOnly;
131 #if !MOONLIGHT
132 [System.Runtime.InteropServices.ComVisible(false)]
133 public virtual CalendarAlgorithmType AlgorithmType {
134 get {
135 return CalendarAlgorithmType.Unknown;
138 #endif
140 [System.Runtime.InteropServices.ComVisible(false)]
141 public virtual DateTime MaxSupportedDateTime {
142 get {
143 return DateTime.MaxValue;
147 [System.Runtime.InteropServices.ComVisible(false)]
148 public virtual DateTime MinSupportedDateTime {
149 get {
150 return DateTime.MinValue;
154 // LAMESPEC: huh, why not Calendar but Object?
155 [ComVisible (false)]
156 public virtual object Clone ()
158 Calendar c = (Calendar) MemberwiseClone ();
159 c.m_isReadOnly = false;
160 return c;
163 [ComVisible (false)]
164 public virtual int GetLeapMonth (int year)
166 return GetLeapMonth (year, GetEra (ToDateTime (year, 1, 1, 0, 0, 0, 0)));
169 [ComVisible (false)]
170 public virtual int GetLeapMonth (int year, int era)
172 int max = GetMonthsInYear (year, era);
173 for (int i = 1; i <= max; i++)
174 if (IsLeapMonth (year, i, era))
175 return i;
176 return 0;
179 [ComVisible (false)]
180 public bool IsReadOnly {
181 get { return m_isReadOnly; }
184 [ComVisible (false)]
185 public static Calendar ReadOnly (Calendar calendar)
187 if (calendar.m_isReadOnly)
188 return calendar;
189 Calendar c = (Calendar) calendar.Clone ();
190 c.m_isReadOnly = true;
191 return c;
194 internal void CheckReadOnly ()
196 if (m_isReadOnly)
197 throw new InvalidOperationException ("This Calendar is read-only.");
200 /// <summary>
201 /// The protected member stores the value for the
202 /// <see cref="P:TwoDigitYearMax"/>
203 /// property.
204 /// </summary>
205 [NonSerialized]
206 internal int twoDigitYearMax;
209 /// <summary>
210 /// Private field containing the maximum year for the calendar.
211 /// </summary>
212 [NonSerialized]
213 private int M_MaxYearValue = 0;
215 /// <value>
216 /// Get-only property returing the maximum allowed year for this
217 /// class.
218 /// </value>
219 internal virtual int M_MaxYear {
220 get {
221 if (M_MaxYearValue == 0) {
222 M_MaxYearValue = GetYear(DateTime.MaxValue);
224 return M_MaxYearValue;
228 /// <summary>
229 /// Checks whether the year is the era is valid, if era = CurrentEra
230 /// the right value is set.
231 /// </summary>
232 /// <param name="year">The year to check.</param>
233 /// <param name="era">The era to check.</Param>
234 /// <exception cref="T:ArgumentOutOfRangeException">
235 /// The exception will be thrown, if the year is not valid.
236 /// </exception>
237 internal virtual void M_CheckYE(int year, ref int era)
240 // By default, we do nothing.
242 // This used to be an abstract method in Mono's implementation,
243 // but that means that end-user code could not create their
244 // own calendars.
246 // Binaries would also crash in this condition.
249 /// <value>
250 /// <para>The property gives the maximum value for years with two
251 /// digits. If the property has the value 2029, than the two-digit
252 /// integer 29 results in the year 2029 and 30 in the
253 /// year 1930.</para>
254 /// <para>It might be overridden.</para>
255 /// </value>
256 public virtual int TwoDigitYearMax {
257 get { return twoDigitYearMax; }
258 set {
259 CheckReadOnly ();
260 M_ArgumentInRange("year", value, 100, M_MaxYear);
261 int era = CurrentEra;
262 M_CheckYE(value, ref era);
263 twoDigitYearMax = value;
267 /// <summary>
268 /// The virtual method adds days to a given date.
269 /// </summary>
270 /// <param name="time">The
271 /// <see cref="T:System.DateTime"/> to which to add
272 /// days.
273 /// </param>
274 /// <param name="days">The number of days to add.</param>
275 /// <returns>A new <see cref="T:System.DateTime"/> value, that
276 /// results from adding <paramref name="days"/> to the specified
277 /// DateTime.</returns>
278 public virtual DateTime AddDays(DateTime time, int days) {
279 return time.Add(TimeSpan.FromDays(days));
282 /// <summary>
283 /// The virtual method adds hours to a given date.
284 /// </summary>
285 /// <param name="time">The
286 /// <see cref="T:System.DateTime"/> to which to add
287 /// hours.
288 /// </param>
289 /// <param name="hours">The number of hours to add.</param>
290 /// <returns>A new <see cref="T:System.DateTime"/> value, that
291 /// results from adding <paramref name="hours"/> to the specified
292 /// DateTime.</returns>
293 public virtual DateTime AddHours(DateTime time, int hours) {
294 return time.Add(TimeSpan.FromHours(hours));
297 /// <summary>
298 /// The virtual method adds milliseconds to a given date.
299 /// </summary>
300 /// <param name="time">The
301 /// <see cref="T:System.DateTime"/> to which to add
302 /// milliseconds.
303 /// </param>
304 /// <param name="milliseconds">The number of milliseconds given as
305 /// double to add. Keep in mind the 100 nanosecond resolution of
306 /// <see cref="T:System.DateTime"/>.
307 /// </param>
308 /// <returns>A new <see cref="T:System.DateTime"/> value, that
309 /// results from adding <paramref name="milliseconds"/> to the specified
310 /// DateTime.</returns>
311 public virtual DateTime AddMilliseconds(DateTime time,
312 double milliseconds)
314 return time.Add(TimeSpan.FromMilliseconds(milliseconds));
317 /// <summary>
318 /// The virtual method adds minutes to a given date.
319 /// </summary>
320 /// <param name="time">The
321 /// <see cref="T:System.DateTime"/> to which to add
322 /// minutes.
323 /// </param>
324 /// <param name="minutes">The number of minutes to add.</param>
325 /// <returns>A new <see cref="T:System.DateTime"/> value, that
326 /// results from adding <paramref name="minutes"/> to the specified
327 /// DateTime.</returns>
328 public virtual DateTime AddMinutes(DateTime time, int minutes) {
329 return time.Add(TimeSpan.FromMinutes(minutes));
332 /// <summary>
333 /// When overrideden adds months to a given date.
334 /// </summary>
335 /// <param name="time">The
336 /// <see cref="T:System.DateTime"/> to which to add
337 /// months.
338 /// </param>
339 /// <param name="months">The number of months to add.</param>
340 /// <returns>A new <see cref="T:System.DateTime"/> value, that
341 /// results from adding <paramref name="months"/> to the specified
342 /// DateTime.</returns>
343 public abstract DateTime AddMonths(DateTime time, int months);
345 /// <summary>
346 /// The virtual method adds seconds to a given date.
347 /// </summary>
348 /// <param name="time">The
349 /// <see cref="T:System.DateTime"/> to which to add
350 /// seconds.
351 /// </param>
352 /// <param name="seconds">The number of seconds to add.</param>
353 /// <returns>A new <see cref="T:System.DateTime"/> value, that
354 /// results from adding <paramref name="seconds"/> to the specified
355 /// DateTime.</returns>
356 public virtual DateTime AddSeconds(DateTime time, int seconds) {
357 return time.Add(TimeSpan.FromSeconds(seconds));
360 /// <summary>
361 /// A wirtual method that adds weeks to a given date.
362 /// </summary>
363 /// <param name="time">The
364 /// <see cref="T:System.DateTime"/> to which to add
365 /// weeks.
366 /// </param>
367 /// <param name="weeks">The number of weeks to add.</param>
368 /// <returns>A new <see cref="T:System.DateTime"/> value, that
369 /// results from adding <paramref name="weeks"/> to the specified
370 /// DateTime.</returns>
371 public virtual DateTime AddWeeks(DateTime time, int weeks) {
372 return time.AddDays(weeks * M_DaysInWeek);
375 /// <summary>
376 /// When overrideden adds years to a given date.
377 /// </summary>
378 /// <param name="time">The
379 /// <see cref="T:System.DateTime"/> to which to add
380 /// years.
381 /// </param>
382 /// <param name="years">The number of years to add.</param>
383 /// <returns>A new <see cref="T:System.DateTime"/> value, that
384 /// results from adding <paramref name="years"/> to the specified
385 /// DateTime.</returns>
386 public abstract DateTime AddYears(DateTime time, int years);
388 /// <summary>
389 /// When overriden gets the day of the month from
390 /// <paramref name="time"/>.
391 /// </summary>
392 /// <param name="time">The
393 /// <see cref="T:System.DateTime"/> that specifies a
394 /// date.
395 /// </param>
396 /// <returns>An integer giving the day of months, starting with 1.
397 /// </returns>
398 public abstract int GetDayOfMonth(DateTime time);
400 /// <summary>
401 /// When overriden gets the day of the week from the specified date.
402 /// </summary>
403 /// <param name="time">The
404 /// <see cref="T:System.DateTime"/> that specifies a
405 /// date.
406 /// </param>
407 /// <returns>An integer giving the day of months, starting with 1.
408 /// </returns>
409 public abstract DayOfWeek GetDayOfWeek(DateTime time);
411 /// <summary>
412 /// When overridden gives the number of the day in the year.
413 /// </summary>
414 /// <param name="time">The
415 /// <see cref="T:System.DateTime"/> that specifies a
416 /// date.
417 /// </param>
418 /// <returns>An integer representing the day of the year,
419 /// starting with 1.</returns>
420 public abstract int GetDayOfYear(DateTime time);
422 /// <summary>
423 /// A virtual method that gives the number of days of the specified
424 /// month of the <paramref name="year"/> and the
425 /// <see cref="P:CurrentEra"/>.
426 /// </summary>
427 /// <param name="year">An integer that gives the year in the current
428 /// era.</param>
429 /// <param name="month">An integer that gives the month, starting
430 /// with 1.</param>
431 /// <returns>An integer that gives the number of days of the
432 /// specified month.</returns>
433 /// <exception cref="T:System.ArgumentOutOfRangeException">
434 /// The exception is thrown, if <paramref name="month"/> or
435 /// <paramref name="year"/> is outside the allowed range.
436 /// </exception>
437 public virtual int GetDaysInMonth(int year, int month) {
438 return GetDaysInMonth(year, month, CurrentEra);
441 /// <summary>
442 /// When overridden gives the number of days in the specified month
443 /// of the given year and era.
444 /// </summary>
445 /// <param name="year">An integer that gives the year.
446 /// </param>
447 /// <param name="month">An integer that gives the month, starting
448 /// with 1.</param>
449 /// <param name="era">An intger that gives the era of the specified
450 /// year.</param>
451 /// <returns>An integer that gives the number of days of the
452 /// specified month.</returns>
453 /// <exception cref="T:System.ArgumentOutOfRangeException">
454 /// The exception is thrown, if <paramref name="month"/>,
455 /// <paramref name="year"/> ,or <paramref name="era"/> is outside
456 /// the allowed range.
457 /// </exception>
458 public abstract int GetDaysInMonth(int year, int month, int era);
460 /// <summary>
461 /// A virtual method that gives the number of days of the specified
462 /// year of the <see cref="P:CurrentEra"/>.
463 /// </summary>
464 /// <param name="year">An integer that gives the year in the current
465 /// era.</param>
466 /// <returns>An integer that gives the number of days of the
467 /// specified year.</returns>
468 /// <exception cref="T:System.ArgumentOutOfRangeException">
469 /// The exception is thrown, if
470 /// <paramref name="year"/> is outside the allowed range.
471 /// </exception>
472 public virtual int GetDaysInYear(int year) {
473 return GetDaysInYear(year, CurrentEra);
476 /// <summary>
477 /// When overridden gives the number of days of the specified
478 /// year of the given era..
479 /// </summary>
480 /// <param name="year">An integer that specifies the year.
481 /// </param>
482 /// <param name="era">An ineger that specifies the era.
483 /// </param>
484 /// <returns>An integer that gives the number of days of the
485 /// specified year.</returns>
486 /// <exception cref="T:System.ArgumentOutOfRangeExceiption">
487 /// The exception is thrown, if
488 /// <paramref name="year"/> is outside the allowed range.
489 /// </exception>
490 public abstract int GetDaysInYear(int year, int era);
492 /// <summary>
493 /// When overridden gives the era of the specified date.
494 /// </summary>
495 /// <param name="time">The
496 /// <see cref="T:System.DateTime"/> that specifies a
497 /// date.
498 /// </param>
499 /// <returns>An integer representing the era of the calendar.
500 /// </returns>
501 public abstract int GetEra(DateTime time);
503 /// <summary>
504 /// Virtual method that gives the hour of the specified time.
505 /// </summary>
506 /// <param name="time">The
507 /// <see cref="T:System.DateTime"/> that specifies the
508 /// time.
509 /// </param>
510 /// <returns>An integer that gives the hour of the specified time,
511 /// starting with 0.</returns>
512 public virtual int GetHour(DateTime time) {
513 return time.TimeOfDay.Hours;
516 /// <summary>
517 /// Virtual method that gives the milliseconds in the current second
518 /// of the specified time.
519 /// </summary>
520 /// <param name="time">The
521 /// <see cref="T:System.DateTime"/> that specifies the
522 /// time.
523 /// </param>
524 /// <returns>An integer that gives the milliseconds in the seconds
525 /// of the specified time, starting with 0.</returns>
526 public virtual double GetMilliseconds(DateTime time) {
527 return time.TimeOfDay.Milliseconds;
530 /// <summary>
531 /// Virtual method that gives the minute of the specified time.
532 /// </summary>
533 /// <param name="time">The
534 /// <see cref="T:System.DateTime"/> that specifies the
535 /// time.
536 /// </param>
537 /// <returns>An integer that gives the minute of the specified time,
538 /// starting with 0.</returns>
539 public virtual int GetMinute(DateTime time) {
540 return time.TimeOfDay.Minutes;
543 /// <summary>
544 /// When overridden gives the number of the month of the specified
545 /// date.
546 /// </summary>
547 /// <param name="time">The
548 /// <see cref="T:System.DateTime"/> that specifies a
549 /// date.
550 /// </param>
551 /// <returns>An integer representing the month,
552 /// starting with 1.</returns>
553 public abstract int GetMonth(DateTime time);
555 /// <summary>
556 /// Virtual method that gives the number of months of the specified
557 /// year of the <see cref="M:CurrentEra"/>.
558 /// </summary>
559 /// <param name="year">An integer that specifies the year in the
560 /// current era.
561 /// </param>
562 /// <returns>An integer that gives the number of the months in the
563 /// specified year.</returns>
564 /// <exception cref="T:System.ArgumentOutOfRangeException">
565 /// The exception is thrown, if the year is not allowed in the
566 /// current era.
567 /// </exception>
568 public virtual int GetMonthsInYear(int year) {
569 return GetMonthsInYear(year, CurrentEra);
572 /// <summary>
573 /// When overridden gives the number of months in the specified year
574 /// and era.
575 /// </summary>
576 /// <param name="year">An integer that specifies the year.
577 /// </param>
578 /// <param name="era">An integer that specifies the era.
579 /// </param>
580 /// <returns>An integer that gives the number of the months in the
581 /// specified year.</returns>
582 /// <exception cref="T:System.ArgumentOutOfRangeException">
583 /// The exception is thrown, if the year or the era are not valid.
584 /// </exception>
585 public abstract int GetMonthsInYear(int year, int era);
587 /// <summary>
588 /// Virtual method that gives the second of the specified time.
589 /// </summary>
590 /// <param name="time">The
591 /// <see cref="T:System.DateTime"/> that specifies the
592 /// time.
593 /// </param>
594 /// <returns>An integer that gives the second of the specified time,
595 /// starting with 0.</returns>
596 public virtual int GetSecond(DateTime time) {
597 return time.TimeOfDay.Seconds;
600 /// <summary>
601 /// A protected method to calculate the number of days between two
602 /// dates.
603 /// </summary>
604 /// <param name="timeA">A <see cref="T:System.DateTime"/>
605 /// representing the first date.
606 /// </param>
607 /// <param name="timeB">A <see cref="T:System.DateTime"/>
608 /// representing the second date.
609 /// </param>
610 /// <returns>An integer that represents the difference of days
611 /// between <paramref name="timeA"/> and <paramref name="timeB"/>.
612 /// </returns>
613 internal int M_DiffDays(DateTime timeA, DateTime timeB) {
614 long diff = timeA.Ticks - timeB.Ticks;
616 if (diff >= 0) {
617 return (int)(diff/TimeSpan.TicksPerDay);
620 diff += 1;
621 return -1 + (int)(diff/TimeSpan.TicksPerDay);
624 /// <summary>
625 /// A protected method that gives the first day of the second week of
626 /// the year.
627 /// </summary>
628 /// <param name="year">An integer that represents the year.</param>
629 /// <param name="rule">The
630 /// <see cref="T:System.Globalization.CalendarWeekRule"/>
631 /// to be used for the calculation.
632 /// </param>
633 /// <param name="firstDayOfWeek">
634 /// The <see cref="T:System.Globalization.DayOfWeek"/>
635 /// specifying the first day in a week.
636 /// </param>
637 /// <returns>The <see cref="T:System.DateTime"/> representing
638 /// the first day of the second week of the year.
639 /// </returns>
640 internal DateTime M_GetFirstDayOfSecondWeekOfYear(
641 int year, CalendarWeekRule rule, DayOfWeek firstDayOfWeek)
643 DateTime d1 = ToDateTime(year, 1, 1, 0, 0, 0, 0);
644 int dow1 = (int)GetDayOfWeek(d1);
645 int fdow = (int)firstDayOfWeek;
646 int d = 0;
648 switch (rule) {
649 case CalendarWeekRule.FirstDay:
650 if (fdow > dow1) {
651 d += fdow - dow1;
653 else {
654 d += fdow + M_DaysInWeek - dow1;
656 break;
657 case CalendarWeekRule.FirstFullWeek:
658 d = M_DaysInWeek;
659 if (fdow >= dow1) {
660 d += fdow - dow1;
662 else {
663 d += fdow + M_DaysInWeek - dow1;
665 break;
666 case CalendarWeekRule.FirstFourDayWeek:
667 int dow4 = (dow1 + 3)%M_DaysInWeek;
669 d = 3;
670 if (fdow > dow4) {
671 d += fdow - dow4;
673 else {
674 d += fdow + M_DaysInWeek - dow4;
676 break;
679 return AddDays(d1, d);
682 /// <summary>
683 /// A virtual method that gives the number of the week in the year.
684 /// </summary>
685 /// <param name="time">A
686 /// <see cref="T:System.DateTime"/> representing the date.
687 /// </param>
688 /// <param name="rule">The
689 /// <see cref="T:System.Globalization.CalendarWeekRule"/>
690 /// to be used for the calculation.
691 /// </param>
692 /// <param name="firstDayOfWeek">
693 /// The <see cref="T:System.Globalization.DayOfWeek"/>
694 /// specifying the first day in a week.
695 /// </param>
696 /// <returns>An integer representing the number of the week in the
697 /// year, starting with 1.
698 /// </returns>
699 public virtual int GetWeekOfYear(DateTime time,
700 CalendarWeekRule rule,
701 DayOfWeek firstDayOfWeek)
703 if (firstDayOfWeek < DayOfWeek.Sunday ||
704 DayOfWeek.Saturday < firstDayOfWeek)
706 throw new ArgumentOutOfRangeException("firstDayOfWeek",
707 "Value is not a valid day of week.");
709 int year = GetYear(time);
711 int days;
713 while (true) {
714 DateTime secondWeek = M_GetFirstDayOfSecondWeekOfYear(
715 year, rule, firstDayOfWeek);
716 days = M_DiffDays(time, secondWeek) + M_DaysInWeek;
717 if (days >= 0)
718 break;
719 year -= 1;
722 return 1 + days/M_DaysInWeek;
725 /// <summary>
726 /// When overridden gives the number of the year of the specified
727 /// date.
728 /// </summary>
729 /// <param name="time">The
730 /// <see cref="T:System.DateTime"/> that specifies a
731 /// date.
732 /// </param>
733 /// <returns>An integer representing the year,
734 /// starting with 1.</returns>
735 public abstract int GetYear(DateTime time);
737 /// <summary>
738 /// A virtual method that tells whether the given day in the
739 /// <see cref="M:CurrentEra"/> is a leap day.
740 /// </summary>
741 /// <param name="year">An integer that specifies the year in the
742 /// current era.
743 /// </param>
744 /// <param name="month">An integer that specifies the month.
745 /// </param>
746 /// <param name="day">An integer that specifies the day.
747 /// </param>
748 /// <returns>A boolean that tells whether the given day is a leap
749 /// day.
750 /// </returns>
751 /// <exception cref="T:System.ArgumentOutOfRangeException">
752 /// The exception is thrown, if the year, month or day is not valid
753 /// the current era.
754 /// </exception>
755 public virtual bool IsLeapDay(int year, int month, int day) {
756 return IsLeapDay(year, month, day, CurrentEra);
759 /// <summary>
760 /// Tells when overridden whether the given day
761 /// is a leap day.
762 /// </summary>
763 /// <param name="year">An integer that specifies the year in the
764 /// given era.
765 /// </param>
766 /// <param name="month">An integer that specifies the month.
767 /// </param>
768 /// <param name="day">An integer that specifies the day.
769 /// </param>
770 /// <param name="era">An integer that specifies the era.
771 /// </param>
772 /// <returns>A boolean that tells whether the given day is a leap
773 /// day.
774 /// </returns>
775 /// <exception cref="T:System.ArgumentOutOfRangeException">
776 /// The exception is thrown, if the year, month, day, or era is not
777 /// valid.
778 /// </exception>
779 public abstract bool IsLeapDay(int year, int month, int day, int era);
781 /// <summary>
782 /// A virtual method that tells whether the given month of the
783 /// specified year in the
784 /// <see cref="M:CurrentEra"/> is a leap month.
785 /// </summary>
786 /// <param name="year">An integer that specifies the year in the
787 /// current era.
788 /// </param>
789 /// <param name="month">An integer that specifies the month.
790 /// </param>
791 /// <returns>A boolean that tells whether the given month is a leap
792 /// month.
793 /// </returns>
794 /// <exception cref="T:System.ArgumentOutOfRangeException">
795 /// The exception is thrown, if the year or month is not valid
796 /// the current era.
797 /// </exception>
798 public virtual bool IsLeapMonth(int year, int month) {
799 return IsLeapMonth(year, month, CurrentEra);
802 /// <summary>
803 /// Tells when overridden whether the given month
804 /// is a leap month.
805 /// </summary>
806 /// <param name="year">An integer that specifies the year in the
807 /// given era.
808 /// </param>
809 /// <param name="month">An integer that specifies the month.
810 /// </param>
811 /// <param name="era">An integer that specifies the era.
812 /// </param>
813 /// <returns>A boolean that tells whether the given month is a leap
814 /// month.
815 /// </returns>
816 /// <exception cref="T:System.ArgumentOutOfRangeException">
817 /// The exception is thrown, if the year, month, or era is not
818 /// valid.
819 /// </exception>
820 public abstract bool IsLeapMonth(int year, int month, int era);
822 /// <summary>
823 /// A virtual method that tells whether the given year
824 /// in the
825 /// <see cref="M:CurrentEra"/> is a leap year.
826 /// </summary>
827 /// <param name="year">An integer that specifies the year in the
828 /// current era.
829 /// </param>
830 /// <returns>A boolean that tells whether the given year is a leap
831 /// year.
832 /// </returns>
833 /// <exception cref="T:System.ArgumentOutOfRangeException">
834 /// The exception is thrown, if the year is not valid
835 /// the current era.
836 /// </exception>
837 public virtual bool IsLeapYear(int year) {
838 return IsLeapYear(year, CurrentEra);
841 /// <summary>
842 /// Tells when overridden whether the given year
843 /// is a leap year.
844 /// </summary>
845 /// <param name="year">An integer that specifies the year in the
846 /// given era.
847 /// </param>
848 /// <param name="era">An integer that specifies the era.
849 /// </param>
850 /// <returns>A boolean that tells whether the given year is a leap
851 /// year.
852 /// </returns>
853 /// <exception cref="T:System.ArgumentOutOfRangeException">
854 /// The exception is thrown, if the year or era is not
855 /// valid.
856 /// </exception>
857 public abstract bool IsLeapYear(int year, int era);
859 /// <summary>
860 /// A virtual method that creates the
861 /// <see cref="T:System.DateTime"/> from the parameters.
862 /// </summary>
863 /// <param name="year">An integer that gives the year in the
864 /// <see cref="M:CurrentEra"/>.
865 /// </param>
866 /// <param name="month">An integer that specifies the month.
867 /// </param>
868 /// <param name="day">An integer that specifies the day.
869 /// </param>
870 /// <param name="hour">An integer that specifies the hour.
871 /// </param>
872 /// <param name="minute">An integer that specifies the minute.
873 /// </param>
874 /// <param name="second">An integer that gives the second.
875 /// </param>
876 /// <param name="milliseconds">An integer that gives the
877 /// milliseconds.
878 /// </param>
879 /// <returns>A
880 /// <see cref="T:system.DateTime"/> representig the date and time.
881 /// </returns>
882 /// <exception cref="T:System.ArgumentOutOfRangeException">
883 /// The exception is thrown, if at least one of the parameters
884 /// is out of range.
885 /// </exception>
886 public virtual DateTime ToDateTime(int year, int month, int day,
887 int hour, int minute, int second, int millisecond)
889 return ToDateTime (year, month, day, hour, minute, second,
890 millisecond, CurrentEra);
894 /// <summary>
895 /// When overridden creates the
896 /// <see cref="T:System.DateTime"/> from the parameters.
897 /// </summary>
898 /// <param name="year">An integer that gives the year in the
899 /// <paramref name="era"/>.
900 /// </param>
901 /// <param name="month">An integer that specifies the month.
902 /// </param>
903 /// <param name="day">An integer that specifies the day.
904 /// </param>
905 /// <param name="hour">An integer that specifies the hour.
906 /// </param>
907 /// <param name="minute">An integer that specifies the minute.
908 /// </param>
909 /// <param name="second">An integer that gives the second.
910 /// </param>
911 /// <param name="milliseconds">An integer that gives the
912 /// milliseconds.
913 /// </param>
914 /// <param name="era">An integer that specifies the era.
915 /// </param>
916 /// <returns>A
917 /// <see cref="T:system.DateTime"/> representig the date and time.
918 /// </returns>
919 /// <exception cref="T:System.ArgumentOutOfRangeException">
920 /// The exception is thrown, if at least one of the parameters
921 /// is out of range.
922 /// </exception>
923 public abstract DateTime ToDateTime(int year, int month, int day,
924 int hour, int minute, int second, int millisecond,
925 int era);
927 /// <summary>
928 /// A virtual method that converts a two-digit year to a four-digit
929 /// year. It uses the <see cref="M:TwoDigitYearMax"/> property.
930 /// </summary>
931 /// <param name="year">An integer that gives the two-digit year.
932 /// </param>
933 /// <returns>An integer giving the four digit year.
934 /// </returns>
935 /// <exception cref="T:System.ArgumentOutOfRangeException">
936 /// The exception is thrown if the year is negative or the resulting
937 /// year is invalid.
938 /// </exception>
939 public virtual int ToFourDigitYear(int year) {
940 if (year < 0)
941 throw new ArgumentOutOfRangeException(
942 "year", "Non-negative number required.");
943 /* seems not to be the right thing to do, but .NET is
944 * doing it this way.
946 if (year <= 99) {
947 int year2 = TwoDigitYearMax%100;
948 int d = year - year2;
949 year = TwoDigitYearMax + d + (d <= 0 ? 0 : -100);
951 int era = CurrentEra;
952 M_CheckYE(year, ref era);
953 return year;
956 // TwoDigitYearMax: Windows reads it from the Registry, we
957 // should have an XML file with the defaults
958 /// <summary>
959 /// The default constructor, is sets the TwoDigitYearMax to 2029.
960 /// </summary>
961 /// <remarks>
962 /// The .NET framework reads the value from the registry.
963 /// We should implement it here. Currently I set the default values
964 /// in the ctors of the derived classes, if it is 99.
965 /// </remarks>
966 protected Calendar() {
967 twoDigitYearMax = 99;
970 /// <summary>Protected field storing the abbreviated era names.
971 /// </summary>
972 [NonSerialized]
973 internal string[] M_AbbrEraNames;
974 /// <summary>Protected field storing the era names.
975 /// </summary>
976 [NonSerialized]
977 internal string[] M_EraNames;
979 /// <value>
980 /// The property stores the era names. It might be overwritten by
981 /// CultureInfo.
982 /// </value>
983 internal string[] AbbreviatedEraNames {
984 get {
985 if (M_AbbrEraNames == null ||
986 M_AbbrEraNames.Length != Eras.Length)
987 throw new Exception(
988 "Internal: M_AbbrEraNames " +
989 "wrong initialized!");
990 return (string[])M_AbbrEraNames.Clone();
992 set {
993 CheckReadOnly ();
994 if (value.Length != Eras.Length) {
995 StringWriter sw = new StringWriter();
996 sw.Write("Array length must be equal Eras " +
997 "length {0}.", Eras.Length);
998 throw new ArgumentException(
999 sw.ToString());
1001 M_AbbrEraNames = (string[])value.Clone();
1005 /// <value>
1006 /// The property stores the era names. It might be overwritten by
1007 /// CultureInfo.
1008 /// </value>
1009 internal string[] EraNames {
1010 get {
1011 if (M_EraNames == null ||
1012 M_EraNames.Length != Eras.Length)
1013 throw new Exception(
1014 "Internal: M_EraNames " +
1015 "not initialized!");
1016 return (string[])M_EraNames.Clone();
1018 set {
1019 CheckReadOnly ();
1020 if (value.Length != Eras.Length) {
1021 StringWriter sw = new StringWriter();
1022 sw.Write("Array length must be equal Eras " +
1023 "length {0}.", Eras.Length);
1024 throw new ArgumentException(
1025 sw.ToString());
1027 M_EraNames = (string[])value.Clone();
1031 internal int m_currentEraValue; // Unused, by MS serializes this
1033 } // class Calendar
1035 } // namespace System.Globalization