Merge pull request #839 from glinos/master
[mono.git] / mcs / class / corlib / System.Globalization / GregorianCalendar.cs
1 // System.Globalization.GregorianCalendar.cs
2 //
3 // (C) Ulrich Kunitz 2002
4 //
5
6 //
7 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 namespace System.Globalization {
30
31 using System;
32 using System.Runtime.InteropServices;
33
34 /// <summary>
35 /// This is the Gregorian calendar.
36 /// </summary>
37 /// <remarks>
38 /// <para>The Gregorian calendar supports only the Common Era from
39 /// the Gregorian year 1 to the Gregorian year 9999.
40 /// </para>
41 /// <para>The implementation uses the
42 /// <see cref="N:CalendricalCalculations"/> namespace.
43 /// </para>
44 /// </remarks>
45 [Serializable]
46 [ComVisible (true)]
47 [MonoLimitation ("Serialization format not compatible with .NET")]
48 public class GregorianCalendar : Calendar {
49
50         /// <summary>
51         /// The era number for the Common Era (C.E.) or Anno Domini (A.D.)
52         /// respective.
53         /// </summary>
54         public const int ADEra = 1;
55
56         /// <value>Overridden. Gives the eras supported by the Gregorian
57         /// calendar as an array of integers.
58         /// </value>
59         public override int[] Eras {
60                 get {
61                         return new int[] { ADEra }; 
62                 }
63         }
64
65         public override int TwoDigitYearMax 
66         {
67                 get {
68                         return twoDigitYearMax;
69                 }
70                 set {
71                         CheckReadOnly ();
72                         M_ArgumentInRange ("value", value, 100, M_MaxYear);
73
74                         twoDigitYearMax = value;
75                 }
76         }
77
78         /// <summary>
79         /// A protected member storing the
80         /// <see cref="T:System.Globalization.GregorianCalendarTypes"/>.
81         /// </summary>
82         [NonSerialized]
83         internal GregorianCalendarTypes m_type;
84
85         /// <value>
86         /// The property stores the 
87         /// <see cref="T:System.Globalization.GregorianCalendarTypes"/>.
88         /// </value>
89         public virtual GregorianCalendarTypes CalendarType {
90                 get { return m_type; }
91                 set { 
92                         CheckReadOnly ();
93                         // mscorlib 1:0:3300:0 doesn't check anything here
94                         m_type = value;
95                 }
96         }
97
98         /// <summary>
99         /// A protected method checking the era number.
100         /// </summary>
101         /// <param name="era">The era number.</param>
102         /// <exception name="T:System.ArgumentException">
103         /// The exception is thrown if the era is not equal
104         /// <see cref="M:ADEra"/>.
105         /// </exception>
106         internal void M_CheckEra(ref int era) {
107                 if (era == CurrentEra)
108                         era = ADEra;
109                 if (era != ADEra)
110                         throw new ArgumentException("Era value was not valid.");
111         }
112
113         /// <summary>
114         /// A protected method checking calendar year and the era number.
115         /// </summary>
116         /// <param name="year">An integer representing the calendar year.
117         /// </param>
118         /// <param name="era">The era number.</param>
119         /// <exception cref="T:System.ArgumentException">
120         /// The exception is thrown if the era is not equal
121         /// <see cref="M:ADEra"/>.
122         /// </exception>
123         /// <exception cref="T:System.ArgumentOutOfRangeException">
124         /// The exception is thrown if the calendar year is outside of
125         /// the allowed range.
126         /// </exception>
127         internal override void M_CheckYE(int year, ref int era) {
128                 M_CheckEra(ref era);
129                 M_ArgumentInRange("year", year, 1, 9999);
130         }
131
132         /// <summary>
133         /// A protected method checking the calendar year, month, and
134         /// era number.
135         /// </summary>
136         /// <param name="year">An integer representing the calendar year.
137         /// </param>
138         /// <param name="month">An integer giving the calendar month.
139         /// </param>
140         /// <param name="era">The era number.</param>
141         /// <exception cref="T:System.ArgumentException">
142         /// The exception is thrown if the era is not equal
143         /// <see cref="M:ADEra"/>.
144         /// </exception>
145         /// <exception cref="T:System.ArgumentOutOfRangeException">
146         /// The exception is thrown if the calendar year or month is
147         /// outside of the allowed range.
148         /// </exception>
149         internal void M_CheckYME(int year, int month, ref int era) {
150                 M_CheckYE(year, ref era);
151                 if (month < 1 || month > 12)
152                         throw new ArgumentOutOfRangeException("month",
153                                 "Month must be between one and twelve.");
154         }
155
156         /// <summary>
157         /// A protected method checking the calendar day, month, and year
158         /// and the era number.
159         /// </summary>
160         /// <param name="year">An integer representing the calendar year.
161         /// </param>
162         /// <param name="month">An integer giving the calendar month.
163         /// </param>
164         /// <param name="day">An integer giving the calendar day.
165         /// </param>
166         /// <param name="era">The era number.</param>
167         /// <exception cref="T:System.ArgumentException">
168         /// The exception is thrown if the era is not equal
169         /// <see cref="M:ADEra"/>.
170         /// </exception>
171         /// <exception cref="T:System.ArgumentOutOfRangeException">
172         /// The exception is thrown if the calendar year, month, or day is
173         /// outside of the allowed range.
174         /// </exception>
175         internal void M_CheckYMDE(int year, int month, int day, ref int era)
176         {
177                 M_CheckYME(year, month, ref era);
178                 M_ArgumentInRange("day", day, 1,
179                         GetDaysInMonth(year, month, era));
180         }
181
182         /// <summary>
183         /// Overridden. Adds months to a given date.
184         /// </summary>
185         /// <param name="time">The
186         /// <see cref="T:System.DateTime"/> to which to add
187         /// months.
188         /// </param>
189         /// <param name="months">The number of months to add.</param>
190         /// <returns>A new <see cref="T:System.DateTime"/> value, that
191         /// results from adding <paramref name="months"/> to the specified
192         /// DateTime.</returns>
193         public override DateTime AddMonths(DateTime time, int months) {
194                 return CCGregorianCalendar.AddMonths(time, months);
195         }
196
197         /// <summary>
198         /// Overridden. Adds years to a given date.
199         /// </summary>
200         /// <param name="time">The
201         /// <see cref="T:System.DateTime"/> to which to add
202         /// years.
203         /// </param>
204         /// <param name="years">The number of years to add.</param>
205         /// <returns>A new <see cref="T:System.DateTime"/> value, that
206         /// results from adding <paramref name="years"/> to the specified
207         /// DateTime.</returns>
208         public override DateTime AddYears(DateTime time, int years) {
209                 return CCGregorianCalendar.AddYears(time, years);
210         }
211                 
212         /// <summary>
213         /// Overridden. Gets the day of the month from
214         /// <paramref name="time"/>.
215         /// </summary>
216         /// <param name="time">The
217         /// <see cref="T:System.DateTime"/> that specifies a
218         /// date.
219         /// </param>
220         /// <returns>An integer giving the day of months, starting with 1.
221         /// </returns>
222         public override int GetDayOfMonth(DateTime time) {
223                 return CCGregorianCalendar.GetDayOfMonth(time);
224         }
225
226         /// <summary>
227         /// Overridden. Gets the day of the week from the specified date.
228         /// </summary>
229         /// <param name="time">The
230         /// <see cref="T:System.DateTime"/> that specifies a
231         /// date.
232         /// </param>
233         /// <returns>An integer giving the day of months, starting with 1.
234         /// </returns>
235         public override DayOfWeek GetDayOfWeek(DateTime time) {
236                 int rd = CCFixed.FromDateTime(time);
237                 return (DayOfWeek)CCFixed.day_of_week(rd);
238         }
239
240         /// <summary>
241         /// Overridden. Gives the number of the day in the year.
242         /// </summary>
243         /// <param name="time">The
244         /// <see cref="T:System.DateTime"/> that specifies a
245         /// date.
246         /// </param>
247         /// <returns>An integer representing the day of the year,
248         /// starting with 1.</returns>
249         public override int GetDayOfYear(DateTime time) {
250                 return CCGregorianCalendar.GetDayOfYear(time);
251         }
252
253         /// <summary>
254         /// Overridden. Gives the number of days in the specified month
255         /// of the given year and era.
256         /// </summary>
257         /// <param name="year">An integer that gives the year.
258         /// </param>
259         /// <param name="month">An integer that gives the month, starting
260         /// with 1.</param>
261         /// <param name="era">An intger that gives the era of the specified
262         /// year.</param>
263         /// <returns>An integer that gives the number of days of the
264         /// specified month.</returns>
265         /// <exception cref="T:System.ArgumentOutOfRangeException">
266         /// The exception is thrown, if <paramref name="month"/>,
267         /// <paramref name="year"/> ,or <paramref name="era"/> is outside
268         /// the allowed range.
269         /// </exception>
270         public override int GetDaysInMonth(int year, int month, int era) {
271                 // mscorlib doesn't check year, probably a bug; we do
272                 M_CheckYME(year, month, ref era);
273                 return CCGregorianCalendar.GetDaysInMonth(year, month);
274         }
275
276         /// <summary>
277         /// Overridden. Gives the number of days of the specified
278         /// year of the given era. 
279         /// </summary>
280         /// <param name="year">An integer that specifies the year. 
281         /// </param>
282         /// <param name="era">An ineger that specifies the era.
283         /// </param>
284         /// <returns>An integer that gives the number of days of the
285         /// specified year.</returns>
286         /// <exception cref="T:System.ArgumentOutOfRangeExceiption">
287         /// The exception is thrown, if
288         /// <paramref name="year"/> is outside the allowed range.
289         /// </exception>
290         public override int GetDaysInYear(int year, int era) {
291                 M_CheckYE(year, ref era);
292                 return CCGregorianCalendar.GetDaysInYear(year);
293         }
294                 
295
296         /// <summary>
297         /// Overridden. Gives the era of the specified date.
298         /// </summary>
299         /// <param name="time">The
300         /// <see cref="T:System.DateTime"/> that specifies a
301         /// date.
302         /// </param>
303         /// <returns>An integer representing the era of the calendar.
304         /// </returns>
305         public override int GetEra(DateTime time) {
306                 return ADEra;
307         }
308
309         [ComVisible (false)]
310         public override int GetLeapMonth (int year, int era)
311         {
312                 return 0;
313         }
314
315         /// <summary>
316         /// Overridden. Gives the number of the month of the specified
317         /// date.
318         /// </summary>
319         /// <param name="time">The
320         /// <see cref="T:System.DateTime"/> that specifies a
321         /// date.
322         /// </param>
323         /// <returns>An integer representing the month, 
324         /// starting with 1.</returns>
325         public override int GetMonth(DateTime time) {
326                 return CCGregorianCalendar.GetMonth(time);
327         }
328
329         /// <summary>
330         /// Overridden. Gives the number of months in the specified year 
331         /// and era.
332         /// </summary>
333         /// <param name="year">An integer that specifies the year.
334         /// </param>
335         /// <param name="era">An integer that specifies the era.
336         /// </param>
337         /// <returns>An integer that gives the number of the months in the
338         /// specified year.</returns>
339         /// <exception cref="T:System.ArgumentOutOfRangeException">
340         /// The exception is thrown, if the year or the era are not valid.
341         /// </exception>
342         public override int GetMonthsInYear(int year, int era) {
343                 M_CheckYE(year, ref era);
344                 return 12;
345         }
346
347         [ComVisible (false)]
348         public override int GetWeekOfYear (DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek)
349         {
350                 return base.GetWeekOfYear (time, rule, firstDayOfWeek);
351         }
352
353         /// <summary>
354         /// Overridden. Gives the number of the year of the specified
355         /// date.
356         /// </summary>
357         /// <param name="time">The
358         /// <see cref="T:System.DateTime"/> that specifies a
359         /// date.
360         /// </param>
361         /// <returns>An integer representing the year, 
362         /// starting with 1.</returns>
363         public override int GetYear(DateTime time) {
364                 return CCGregorianCalendar.GetYear(time);
365         }
366
367         /// <summary>
368         /// Overridden. Tells whether the given day 
369         /// is a leap day.
370         /// </summary>
371         /// <param name="year">An integer that specifies the year in the
372         /// given era.
373         /// </param>
374         /// <param name="month">An integer that specifies the month.
375         /// </param>
376         /// <param name="day">An integer that specifies the day.
377         /// </param>
378         /// <param name="era">An integer that specifies the era.
379         /// </param>
380         /// <returns>A boolean that tells whether the given day is a leap
381         /// day.
382         /// </returns>
383         /// <exception cref="T:System.ArgumentOutOfRangeException">
384         /// The exception is thrown, if the year, month, day, or era is not
385         /// valid.
386         /// </exception>
387         public override bool IsLeapDay(int year, int month, int day, int era)
388         {
389                 M_CheckYMDE(year, month, day, ref era);
390                 return CCGregorianCalendar.IsLeapDay(year, month, day);
391         }
392
393
394         /// <summary>
395         /// Overridden. Tells whether the given month 
396         /// is a leap month.
397         /// </summary>
398         /// <param name="year">An integer that specifies the year in the
399         /// given era.
400         /// </param>
401         /// <param name="month">An integer that specifies the month.
402         /// </param>
403         /// <param name="era">An integer that specifies the era.
404         /// </param>
405         /// <returns>A boolean that tells whether the given month is a leap
406         /// month.
407         /// </returns>
408         /// <exception cref="T:System.ArgumentOutOfRangeException">
409         /// The exception is thrown, if the year, month, or era is not
410         /// valid.
411         /// </exception>
412         public override bool IsLeapMonth(int year, int month, int era) {
413                 M_CheckYME(year, month, ref era);
414                 return false;
415         }
416
417         /// <summary>
418         /// Overridden. Tells whether the given year
419         /// is a leap year.
420         /// </summary>
421         /// <param name="year">An integer that specifies the year in the
422         /// given era.
423         /// </param>
424         /// <param name="era">An integer that specifies the era.
425         /// </param>
426         /// <returns>A boolean that tells whether the given year is a leap
427         /// year.
428         /// </returns>
429         /// <exception cref="T:System.ArgumentOutOfRangeException">
430         /// The exception is thrown, if the year or era is not
431         /// valid.
432         /// </exception>
433         public override bool IsLeapYear(int year, int era) {
434                 M_CheckYE(year, ref era);
435                 return CCGregorianCalendar.is_leap_year(year);
436         }
437
438         /// <summary>
439         /// Overridden. Creates the
440         /// <see cref="T:System.DateTime"/> from the parameters.
441         /// </summary>
442         /// <param name="year">An integer that gives the year in the
443         /// <paramref name="era"/>.
444         /// </param>
445         /// <param name="month">An integer that specifies the month.
446         /// </param>
447         /// <param name="day">An integer that specifies the day.
448         /// </param>
449         /// <param name="hour">An integer that specifies the hour.
450         /// </param>
451         /// <param name="minute">An integer that specifies the minute.
452         /// </param>
453         /// <param name="second">An integer that gives the second.
454         /// </param>
455         /// <param name="milliseconds">An integer that gives the
456         /// milliseconds.
457         /// </param>
458         /// <param name="era">An integer that specifies the era.
459         /// </param>
460         /// <returns>
461         /// <see cref="T:system.DateTime"/> representig the date and time.
462         /// </returns>
463         /// <exception cref="T:System.ArgumentOutOfRangeException">
464         /// The exception is thrown, if at least one of the parameters
465         /// is out of range.
466         /// </exception>
467         public override DateTime ToDateTime(int year, int month, int day,
468                 int hour, int minute, int second, int millisecond,
469                 int era)
470         {
471                 M_CheckYMDE(year, month, day, ref era);
472                 M_CheckHMSM(hour, minute, second, millisecond);
473                 return CCGregorianCalendar.ToDateTime(
474                         year, month, day,
475                         hour, minute, second, millisecond);
476         }
477
478         public override int ToFourDigitYear(int year)
479         {
480                 return base.ToFourDigitYear (year);
481         }
482                                         
483         /// <summary>
484         /// Constructor that sets the
485         /// Gregorian calendar type (
486         /// <see cref="T:System.Globalization.GregorianCalendarTypes"/>).
487         /// </summary>
488         /// <param name="type">The parameter specifies the Gregorian 
489         /// calendar type.
490         /// </param>
491         public GregorianCalendar(GregorianCalendarTypes type) {
492                 CalendarType = type;
493                 M_AbbrEraNames = new string[] {"AD"};
494                 M_EraNames = new string[] {"A.D."};
495                 if (twoDigitYearMax == 99)
496                         twoDigitYearMax = 2029;
497         }
498         
499 #if !NET_2_1
500         [ComVisible (false)]
501         public override CalendarAlgorithmType AlgorithmType {
502                 get {
503                         return CalendarAlgorithmType.SolarCalendar;
504                 }
505         }
506 #endif
507
508         static DateTime? Min, Max;
509                 
510         [ComVisible (false)]
511         public override DateTime MinSupportedDateTime {
512                 get {
513                         if (Min == null)
514                                 Min = new DateTime (1, 1, 1, 0, 0, 0);
515                         return Min.Value;
516                 }
517         }
518
519         [ComVisible (false)]
520         public override DateTime MaxSupportedDateTime {
521                 get {
522                         if (Max == null)
523                                 Max = new DateTime (9999, 12, 31, 11, 59, 59);
524                         return Max.Value;
525                 }
526         }
527         
528         /// <summary>
529         /// Default constructor. Sets the Gregorian calendar type to 
530         /// <see
531         /// cref="F:System.Globalization.GregorianCalendarTypes.Localized"/>.
532         /// </summary>
533         public GregorianCalendar() : this(GregorianCalendarTypes.Localized) {}
534 } // class GregorianCalendar
535         
536 } // namespace System.Globalization