2009-07-30 Gonzalo Paniagua Javier <gonzalo@novell.com>
[mono.git] / mcs / class / corlib / System.Globalization / JapaneseCalendar.cs
1 // System.Globalization.JapaneseCalendar.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 Japanese calendar. It differs from the Gregorian calendar
36 /// only in the years.
37 /// </summary>
38 /// <remarks>
39 /// <para>The Japanese calendar support four eras.</para>
40 /// <list type="table">
41 /// <listheader>
42 /// <term>era number</term>
43 /// <term>Gregorian start date</term>
44 /// <term>Gregorian end date</term>
45 /// </listheader>
46 /// <item>
47 /// <term>1</term>
48 /// <term>September 8, 1868</term>
49 /// <term>July 29, 1912</term>
50 /// </item>
51 /// <item>
52 /// <term>2</term>
53 /// <term>July 30, 1912</term>
54 /// <term>December 24, 1926</term>
55 /// </item>
56 /// <item>
57 /// <term>3</term>
58 /// <term>December 25, 1926</term>
59 /// <term>January 7, 1989</term>
60 /// </item>
61 /// <item>
62 /// <term>4</term>
63 /// <term>January 8, 1989</term>
64 /// <term>present</term>
65 /// </item>
66 /// </list>
67 /// <para>The implementation uses the
68 /// <see cref="N:CalendricalCalculations"/> namespace.
69 /// </para>
70 /// </remarks>
71 [Serializable]
72 #if NET_2_0
73 [ComVisible (true)]
74 #endif
75 [MonoTODO ("Serialization format not compatible with .NET")]
76 public class JapaneseCalendar : Calendar {
77         /// <summary>
78         /// Static protected field storing the
79         /// <see cref="T:CalendricalCalculations.GregorianEraHandler"/>.
80         /// </summary>
81         internal static readonly CCGregorianEraHandler M_EraHandler;
82
83         /// <summary>
84         /// Static constructor, who creates and initializes
85         /// <see cref="F:M_EraHandler"/>.
86         /// </summary>
87         static JapaneseCalendar() {
88                 M_EraHandler = new CCGregorianEraHandler();
89                 M_EraHandler.appendEra(1,
90                         CCGregorianCalendar.fixed_from_dmy(8, 9, 1868),
91                         CCGregorianCalendar.fixed_from_dmy(29, 7, 1912));
92                 M_EraHandler.appendEra(2,
93                         CCGregorianCalendar.fixed_from_dmy(30, 7, 1912),
94                         CCGregorianCalendar.fixed_from_dmy(24, 12, 1926));
95                 M_EraHandler.appendEra(3,
96                         CCGregorianCalendar.fixed_from_dmy(25, 12, 1926),
97                         CCGregorianCalendar.fixed_from_dmy(7, 1, 1989));
98                 M_EraHandler.appendEra(4,
99                         CCGregorianCalendar.fixed_from_dmy(8, 1, 1989));
100         }
101
102         /// <summary>
103         /// Default constructor.
104         /// </summary>
105         public JapaneseCalendar() {
106                 M_AbbrEraNames = new string[] { "M", "T", "S", "H" };
107                 M_EraNames = new string[] { "Meiji", "Taisho", "Showa",
108                         "Heisei" };
109         }
110                 
111
112         /// <value>Overridden. Gives the eras supported by the
113         /// calendar as an array of integers.
114         /// </value>
115         public override int[] Eras {
116                 get {
117                         return (int[])M_EraHandler.Eras.Clone();
118                 }
119         }
120
121         public override int TwoDigitYearMax 
122         {
123                 get {
124                         return twoDigitYearMax;
125                 }
126                 set {
127                         CheckReadOnly ();
128                         M_ArgumentInRange ("value", value, 100, M_MaxYear);
129
130                         twoDigitYearMax = value;
131                 }
132         }
133         
134         /// <summary>
135         /// A protected member checking a
136         /// <see cref="T:System.DateTime"/> value.
137         /// </summary>
138         /// <param name="time">The
139         /// <see cref="T:System.DateTime"/>
140         /// to check.
141         /// </param>
142         /// <exception cref="T:System.ArgumentOutOfRangeException">
143         /// The exception is thrown if the
144         /// <see cref="T:System.DateTime"/> parameter is outside all
145         /// supported eras.
146         /// </exception>
147         internal void M_CheckDateTime(DateTime time) {
148                 M_EraHandler.CheckDateTime(time);
149         }
150
151         /// <summary>
152         /// A protected method checking the era number.
153         /// </summary>
154         /// <param name="era">The era number as reference. It is set
155         /// to <see cref="F:CurrentEra"/>, if the input value is 0.</param>
156         /// <exception name="T:System.ArgumentException">
157         /// The exception is thrown if the era is not supported by the class.
158         /// </exception>
159         internal void M_CheckEra(ref int era) {
160                 if (era == CurrentEra)
161                         era = 4;
162                 if (!M_EraHandler.ValidEra(era))
163                         throw new ArgumentException("Era value was not valid.");
164         }
165
166         /// <summary>
167         /// A protected method checking calendar year and the era number.
168         /// </summary>
169         /// <param name="year">An integer representing the calendar year.
170         /// </param>
171         /// <param name="era">The era number as reference.</param>
172         /// <exception name="T:System.ArgumentException">
173         /// The exception is thrown if the era is not supported by the class.
174         /// </exception>
175         /// <exception cref="T:System.ArgumentOutOfRangeException">
176         /// The exception is thrown if the calendar year is outside of
177         /// the supported range.
178         /// </exception>
179         internal int M_CheckYEG(int year, ref int era) {
180                 M_CheckEra(ref era);
181                 return M_EraHandler.GregorianYear(year, era);
182         }
183
184         /// <summary>
185         /// Checks whether the year is the era is valid, if era = CurrentEra
186         /// the right value is set.
187         /// </summary>
188         /// <param name="year">The year to check.</param>
189         /// <param name="era">The era to check.</Param>
190         /// <exception cref="T:ArgumentOutOfRangeException">
191         /// The exception will be thrown, if the year is not valid.
192         /// </exception>
193         internal override void M_CheckYE(int year, ref int era) {
194                 M_CheckYEG(year, ref era);
195         }
196
197         /// <summary>
198         /// A protected method checking the calendar year, month, and
199         /// era number.
200         /// </summary>
201         /// <param name="year">An integer representing the calendar year.
202         /// </param>
203         /// <param name="month">An integer giving the calendar month.
204         /// </param>
205         /// <param name="era">The era number as reference.</param>
206         /// <exception name="T:System.ArgumentException">
207         /// The exception is thrown if the era is not supported by the class.
208         /// </exception>
209         /// <exception cref="T:System.ArgumentOutOfRangeException">
210         /// The exception is thrown if the calendar year or month is
211         /// outside of the supported range.
212         /// </exception>
213         internal int M_CheckYMEG(int year, int month, ref int era) {
214                 int gregorianYear = M_CheckYEG(year, ref era);
215                 if (month < 1 || month > 12)
216                         throw new ArgumentOutOfRangeException("month",
217                                 "Month must be between one and twelve.");
218                 return gregorianYear;
219         }
220
221         /// <summary>
222         /// A protected method checking the calendar day, month, and year
223         /// and the era number.
224         /// </summary>
225         /// <param name="year">An integer representing the calendar year.
226         /// </param>
227         /// <param name="month">An integer giving the calendar month.
228         /// </param>
229         /// <param name="day">An integer giving the calendar day.
230         /// </param>
231         /// <param name="era">The era number as reference.</param>
232         /// <exception name="T:System.ArgumentException">
233         /// The exception is thrown if the era is not supported by the class.
234         /// </exception>
235         /// <exception cref="T:System.ArgumentOutOfRangeException">
236         /// The exception is thrown if the calendar year, month, or day is
237         /// outside of the supported range.
238         /// </exception>
239         internal int M_CheckYMDEG(int year, int month, int day, ref int era)
240         {
241                 int gregorianYear = M_CheckYMEG(year, month, ref era);
242                 M_ArgumentInRange("day", day, 1, GetDaysInMonth(year, month, era));
243                 return gregorianYear;
244         }
245         
246         /// <summary>
247         /// Overrideden. Adds months to a given date.
248         /// </summary>
249         /// <param name="time">The
250         /// <see cref="T:System.DateTime"/> to which to add
251         /// months.
252         /// </param>
253         /// <param name="months">The number of months to add.</param>
254         /// <returns>A new <see cref="T:System.DateTime"/> value, that
255         /// results from adding <paramref name="months"/> to the specified
256         /// DateTime.</returns>
257         /// <exception cref="T:System.ArgumentOutOfRangeException">
258         /// The exception is thrown if
259         /// <see cref="T:System.DateTime"/> return value is outside all
260         /// supported eras.
261         /// </exception>
262         public override DateTime AddMonths(DateTime time, int months) {
263                 DateTime t = CCGregorianCalendar.AddMonths(time, months);
264                 M_CheckDateTime(t);
265                 return t;
266         }
267
268         /// <summary>
269         /// Overridden. Adds years to a given date.
270         /// </summary>
271         /// <param name="time">The
272         /// <see cref="T:System.DateTime"/> to which to add
273         /// years.
274         /// </param>
275         /// <param name="years">The number of years to add.</param>
276         /// <returns>A new <see cref="T:System.DateTime"/> value, that
277         /// results from adding <paramref name="years"/> to the specified
278         /// DateTime.</returns>
279         /// <exception cref="T:System.ArgumentOutOfRangeException">
280         /// The exception is thrown if
281         /// <see cref="T:System.DateTime"/> return value is outside all
282         /// supported eras.
283         /// </exception>
284         public override DateTime AddYears(DateTime time, int years) {
285                 DateTime t = CCGregorianCalendar.AddYears(time, years);
286                 M_CheckDateTime(t);
287                 return t;
288         }
289                 
290         /// <summary>
291         /// Overriden. Gets the day of the month from
292         /// <paramref name="time"/>.
293         /// </summary>
294         /// <param name="time">The
295         /// <see cref="T:System.DateTime"/> that specifies a
296         /// date.
297         /// </param>
298         /// <returns>An integer giving the day of months, starting with 1.
299         /// </returns>
300         /// <exception cref="T:System.ArgumentOutOfRangeException">
301         /// The exception is thrown if the
302         /// <see cref="T:System.DateTime"/> parameter is outside all
303         /// supported eras.
304         /// </exception>
305         public override int GetDayOfMonth(DateTime time) {
306                 M_CheckDateTime(time);
307                 return CCGregorianCalendar.GetDayOfMonth(time);
308         }
309
310         /// <summary>
311         /// Overriden. Gets the day of the week from the specified date.
312         /// </summary>
313         /// <param name="time">The
314         /// <see cref="T:System.DateTime"/> that specifies a
315         /// date.
316         /// </param>
317         /// <returns>An integer giving the day of months, starting with 1.
318         /// </returns>
319         /// <exception cref="T:System.ArgumentOutOfRangeException">
320         /// The exception is thrown if the
321         /// <see cref="T:System.DateTime"/> parameter is outside all
322         /// supported eras.
323         /// </exception>
324         public override DayOfWeek GetDayOfWeek(DateTime time) {
325                 M_CheckDateTime(time);
326                 int rd = CCFixed.FromDateTime(time);
327                 return (DayOfWeek)CCFixed.day_of_week(rd);
328         }
329
330         /// <summary>
331         /// Overridden. Gives the number of the day in the year.
332         /// </summary>
333         /// <param name="time">The
334         /// <see cref="T:System.DateTime"/> that specifies a
335         /// date.
336         /// </param>
337         /// <returns>An integer representing the day of the year,
338         /// starting with 1.</returns>
339         /// <exception cref="T:System.ArgumentOutOfRangeException">
340         /// The exception is thrown if the
341         /// <see cref="T:System.DateTime"/> parameter is outside all
342         /// supported eras.
343         /// </exception>
344         public override int GetDayOfYear(DateTime time) {
345                 M_CheckDateTime(time);
346                 return CCGregorianCalendar.GetDayOfYear(time);
347         }
348
349         /// <summary>
350         /// Overridden. Gives the number of days in the specified month
351         /// of the given year and era.
352         /// </summary>
353         /// <param name="year">An integer that gives the year.
354         /// </param>
355         /// <param name="month">An integer that gives the month, starting
356         /// with 1.</param>
357         /// <param name="era">An integer that gives the era of the specified
358         /// year.</param>
359         /// <returns>An integer that gives the number of days of the
360         /// specified month.</returns>
361         /// <exception cref="T:System.ArgumentOutOfRangeException">
362         /// The exception is thrown, if <paramref name="month"/>,
363         /// <paramref name="year"/> ,or <paramref name="era"/> is outside
364         /// the allowed range.
365         /// </exception>
366         public override int GetDaysInMonth(int year, int month, int era) {
367                 int gregorianYear = M_CheckYMEG(year, month, ref era);
368                 return CCGregorianCalendar.GetDaysInMonth(gregorianYear, month);
369         }
370
371         /// <summary>
372         /// Overridden. Gives the number of days of the specified
373         /// year of the given era. 
374         /// </summary>
375         /// <param name="year">An integer that specifies the year. 
376         /// </param>
377         /// <param name="era">An ineger that specifies the era.
378         /// </param>
379         /// <returns>An integer that gives the number of days of the
380         /// specified year.</returns>
381         /// <exception cref="T:System.ArgumentOutOfRangeExceiption">
382         /// The exception is thrown, if
383         /// <paramref name="year"/> or <paramref name="era"/> are outside the
384         /// allowed range.
385         /// </exception>
386         public override int GetDaysInYear(int year, int era) {
387                 int gregorianYear = M_CheckYEG(year, ref era);
388                 return CCGregorianCalendar.GetDaysInYear(gregorianYear);
389         }
390                 
391
392         /// <summary>
393         /// Overridden. Gives the era of the specified date.
394         /// </summary>
395         /// <param name="time">The
396         /// <see cref="T:System.DateTime"/> that specifies a
397         /// date.
398         /// </param>
399         /// <returns>An integer representing the era of the calendar.
400         /// </returns>
401         /// <exception cref="T:System.ArgumentOutOfRangeException">
402         /// The exception is thrown if the
403         /// <see cref="T:System.DateTime"/> parameter is outside all
404         /// supported eras.
405         /// </exception>
406         public override int GetEra(DateTime time) {
407                 // M_CheckDateTime not needed, because EraYear does the
408                 // right thing.
409                 int rd = CCFixed.FromDateTime(time);
410                 int era;
411                 M_EraHandler.EraYear(out era, rd);
412                 return era;
413         }
414
415 #if NET_2_0
416         [ComVisible (false)]
417         public override int GetLeapMonth (int year, int era)
418         {
419                 return 0;
420         }
421 #endif
422
423         /// <summary>
424         /// Overridden. Gives the number of the month of the specified
425         /// date.
426         /// </summary>
427         /// <param name="time">The
428         /// <see cref="T:System.DateTime"/> that specifies a
429         /// date.
430         /// </param>
431         /// <returns>An integer representing the month, 
432         /// starting with 1.</returns>
433         /// <exception cref="T:System.ArgumentOutOfRangeException">
434         /// The exception is thrown if the
435         /// <see cref="T:System.DateTime"/> parameter is outside all
436         /// supported eras.
437         /// </exception>
438         public override int GetMonth(DateTime time) {
439                 M_CheckDateTime(time);
440                 return CCGregorianCalendar.GetMonth(time);
441         }
442
443         /// <summary>
444         /// Overridden. Gives the number of months in the specified year 
445         /// and era.
446         /// </summary>
447         /// <param name="year">An integer that specifies the year.
448         /// </param>
449         /// <param name="era">An integer that specifies the era.
450         /// </param>
451         /// <returns>An integer that gives the number of the months in the
452         /// specified year.</returns>
453         /// <exception cref="T:System.ArgumentOutOfRangeException">
454         /// The exception is thrown, if the year or the era are not valid.
455         /// </exception>
456         public override int GetMonthsInYear(int year, int era) {
457                 M_CheckYE(year, ref era);
458                 return 12;
459         }
460
461 #if NET_2_0
462         [ComVisible (false)]
463         public override int GetWeekOfYear (DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek)
464         {
465                 return base.GetWeekOfYear (time, rule, firstDayOfWeek);
466         }
467 #endif
468
469         /// <summary>
470         /// Overridden. Gives the number of the year of the specified
471         /// date.
472         /// </summary>
473         /// <param name="time">The
474         /// <see cref="T:System.DateTime"/> that specifies a
475         /// date.
476         /// </param>
477         /// <returns>An integer representing the year, 
478         /// starting with 1.</returns>
479         /// <exception cref="T:System.ArgumentOutOfRangeException">
480         /// The exception is thrown if the
481         /// <see cref="T:System.DateTime"/> parameter is outside all
482         /// supported eras.
483         /// </exception>
484         public override int GetYear(DateTime time) {
485                 // M_CheckDateTime not needed, because EraYeat does the
486                 // right thing.
487                 int rd = CCFixed.FromDateTime(time);
488                 int era;
489                 return M_EraHandler.EraYear(out era, rd);
490         }
491
492         /// <summary>
493         /// Overridden. Tells whether the given day 
494         /// is a leap day.
495         /// </summary>
496         /// <param name="year">An integer that specifies the year in the
497         /// given era.
498         /// </param>
499         /// <param name="month">An integer that specifies the month.
500         /// </param>
501         /// <param name="day">An integer that specifies the day.
502         /// </param>
503         /// <param name="era">An integer that specifies the era.
504         /// </param>
505         /// <returns>A boolean that tells whether the given day is a leap
506         /// day.
507         /// </returns>
508         /// <exception cref="T:System.ArgumentOutOfRangeException">
509         /// The exception is thrown, if the year, month, day, or era is not
510         /// valid.
511         /// </exception>
512         public override bool IsLeapDay(int year, int month, int day, int era)
513         {
514                 int gregorianYear = M_CheckYMDEG(year, month, day, ref era);
515                 return CCGregorianCalendar.IsLeapDay(gregorianYear, month, day);
516         }
517
518         /// <summary>
519         /// Overridden. Tells whether the given month 
520         /// is a leap month.
521         /// </summary>
522         /// <param name="year">An integer that specifies the year in the
523         /// given era.
524         /// </param>
525         /// <param name="month">An integer that specifies the month.
526         /// </param>
527         /// <param name="era">An integer that specifies the era.
528         /// </param>
529         /// <returns>A boolean that tells whether the given month is a leap
530         /// month.
531         /// </returns>
532         /// <exception cref="T:System.ArgumentOutOfRangeException">
533         /// The exception is thrown, if the year, month, or era is not
534         /// valid.
535         /// </exception>
536         public override bool IsLeapMonth(int year, int month, int era) {
537                 M_CheckYMEG(year, month, ref era);
538                 return false;
539         }
540
541         /// <summary>
542         /// Overridden. Tells whether the given year
543         /// is a leap year.
544         /// </summary>
545         /// <param name="year">An integer that specifies the year in the
546         /// given era.
547         /// </param>
548         /// <param name="era">An integer that specifies the era.
549         /// </param>
550         /// <returns>A boolean that tells whether the given year is a leap
551         /// year.
552         /// </returns>
553         /// <exception cref="T:System.ArgumentOutOfRangeException">
554         /// The exception is thrown, if the year or era is not
555         /// valid.
556         /// </exception>
557         public override bool IsLeapYear(int year, int era) {
558                 int gregorianYear = M_CheckYEG(year, ref era);
559                 return CCGregorianCalendar.is_leap_year(gregorianYear);
560         }
561
562         /// <summary>
563         /// Overridden. Creates the
564         /// <see cref="T:System.DateTime"/> from the parameters.
565         /// </summary>
566         /// <param name="year">An integer that gives the year in the
567         /// <paramref name="era"/>.
568         /// </param>
569         /// <param name="month">An integer that specifies the month.
570         /// </param>
571         /// <param name="day">An integer that specifies the day.
572         /// </param>
573         /// <param name="hour">An integer that specifies the hour.
574         /// </param>
575         /// <param name="minute">An integer that specifies the minute.
576         /// </param>
577         /// <param name="second">An integer that gives the second.
578         /// </param>
579         /// <param name="milliseconds">An integer that gives the
580         /// milliseconds.
581         /// </param>
582         /// <param name="era">An integer that specifies the era.
583         /// </param>
584         /// <returns>A
585         /// <see cref="T:system.DateTime"/> representig the date and time.
586         /// </returns>
587         /// <exception cref="T:System.ArgumentOutOfRangeException">
588         /// The exception is thrown, if at least one of the parameters
589         /// is out of range.
590         /// </exception>
591         public override DateTime ToDateTime(int year, int month, int day,
592                 int hour, int minute, int second, int millisecond,
593                 int era)
594         {
595                 int gregorianYear = M_CheckYMDEG(year, month, day, ref era);
596                 M_CheckHMSM(hour, minute, second, millisecond);
597                 return CCGregorianCalendar.ToDateTime(
598                         gregorianYear, month, day,
599                         hour, minute, second, millisecond);
600         }
601
602
603         /// <summary>
604         /// This functions returns simply the year for the Japanese calendar.
605         /// </summary>
606         /// <param name="year">An integer that gives the year.
607         /// </param>
608         /// <returns>The same argument as the year.
609         /// </returns>
610         /// <exception cref="T:System.ArgumentOutOfRangeException">
611         /// The exception is thrown if the year is negative or the resulting 
612         /// year is invalid.
613         /// </exception>
614         public override int ToFourDigitYear(int year) {
615                 if (year < 0)
616                         throw new ArgumentOutOfRangeException(
617                                 "year", "Non-negative number required.");
618                 int era = CurrentEra;
619                 M_CheckYE(year, ref era);
620                 return year;
621         }
622
623 #if NET_2_0
624         [ComVisible (false)]
625         public override CalendarAlgorithmType AlgorithmType {
626                 get {
627                         return CalendarAlgorithmType.SolarCalendar;
628                 }
629         }
630
631         static DateTime JapanMin = new DateTime (1868, 9, 8, 0, 0, 0);
632         static DateTime JapanMax = new DateTime (9999, 12, 31, 11, 59, 59);
633                 
634         [ComVisible (false)]
635         public override DateTime MinSupportedDateTime {
636                 get {
637                         return JapanMin;
638                 }
639         }
640
641         [ComVisible (false)]
642         public override DateTime MaxSupportedDateTime {
643                 get {
644                         return JapanMax;
645                 }
646         }
647 #endif
648
649 } // class JapaneseCalendar
650         
651 } // namespace System.Globalization