Merge pull request #1388 from schani/fix-23401
[mono.git] / mcs / class / corlib / System.Globalization / EastAsianLunisolarCalendar.cs
1 //
2 // System.Globalization.EastAsianLunisolarCalendar.cs
3 //
4 // Author
5 //      Ulrich Kunitz 2002
6 //      Atsushi Enomoto  <atsushi@ximian.com>
7 //
8 // (C) Ulrich Kunitz 2002
9 // Copyright (C) 2007 Novell, Inc.  http://www.novell.com
10 //
11
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32
33 namespace System.Globalization {
34
35 using System;
36
37 [Serializable]
38 [System.Runtime.InteropServices.ComVisible (true)]
39 public abstract class EastAsianLunisolarCalendar : Calendar {
40         // FIXME: This is ok and it does not have to be something like 
41         // CCEastAsianLunisolarEraHandler since it does not depend on
42         // any lunisolar stuff.
43         internal readonly CCEastAsianLunisolarEraHandler M_EraHandler;
44
45         internal EastAsianLunisolarCalendar (CCEastAsianLunisolarEraHandler eraHandler)
46         {
47                 M_EraHandler = eraHandler;
48         }
49
50         public override int TwoDigitYearMax 
51         {
52                 get {
53                         return twoDigitYearMax;
54                 }
55                 set {
56                         CheckReadOnly ();
57                         M_ArgumentInRange ("value", value, 100, M_MaxYear);
58
59                         twoDigitYearMax = value;
60                 }
61         }
62         
63         internal void M_CheckDateTime(DateTime time) {
64                 M_EraHandler.CheckDateTime(time);
65         }
66
67         internal virtual int ActualCurrentEra {
68                 get { return 1; }
69         }
70
71         internal void M_CheckEra(ref int era) {
72                 if (era == CurrentEra)
73                         era = ActualCurrentEra;
74                 if (!M_EraHandler.ValidEra(era))
75                         throw new ArgumentException("Era value was not valid.");
76         }
77
78         internal int M_CheckYEG(int year, ref int era) {
79                 M_CheckEra(ref era);
80                 return M_EraHandler.GregorianYear(year, era);
81         }
82
83         internal override void M_CheckYE(int year, ref int era) {
84                 M_CheckYEG(year, ref era);
85         }
86
87         internal int M_CheckYMEG(int year, int month, ref int era) {
88                 int gregorianYear = M_CheckYEG(year, ref era);
89                 if (month < 1 || month > 12)
90                         throw new ArgumentOutOfRangeException("month",
91                                 "Month must be between one and twelve.");
92                 return gregorianYear;
93         }
94
95         internal int M_CheckYMDEG(int year, int month, int day, ref int era)
96         {
97                 int gregorianYear = M_CheckYMEG(year, month, ref era);
98                 M_ArgumentInRange("day", day, 1, GetDaysInMonth(year, month, era));
99                 return gregorianYear;
100         }
101
102         [MonoTODO]
103         public override DateTime AddMonths(DateTime time, int months) {
104                 DateTime t = CCEastAsianLunisolarCalendar.AddMonths(time, months);
105                 M_CheckDateTime(t);
106                 return t;
107         }
108
109         [MonoTODO]
110         public override DateTime AddYears(DateTime time, int years) {
111                 DateTime t = CCEastAsianLunisolarCalendar.AddYears(time, years);
112                 M_CheckDateTime(t);
113                 return t;
114         }
115                 
116         [MonoTODO]
117         public override int GetDayOfMonth(DateTime time) {
118                 M_CheckDateTime(time);
119                 return CCEastAsianLunisolarCalendar.GetDayOfMonth(time);
120         }
121
122         [MonoTODO]
123         public override DayOfWeek GetDayOfWeek(DateTime time) {
124                 M_CheckDateTime(time);
125                 int rd = CCFixed.FromDateTime(time);
126                 return (DayOfWeek)CCFixed.day_of_week(rd);
127         }
128
129         [MonoTODO]
130         public override int GetDayOfYear(DateTime time) {
131                 M_CheckDateTime(time);
132                 return CCEastAsianLunisolarCalendar.GetDayOfYear(time);
133         }
134
135         [MonoTODO]
136         public override int GetDaysInMonth(int year, int month, int era) {
137                 int gregorianYear = M_CheckYMEG(year, month, ref era);
138                 return CCEastAsianLunisolarCalendar.GetDaysInMonth(gregorianYear, month);
139         }
140
141         [MonoTODO]
142         public override int GetDaysInYear(int year, int era) {
143                 int gregorianYear = M_CheckYEG(year, ref era);
144                 return CCEastAsianLunisolarCalendar.GetDaysInYear(gregorianYear);
145         }
146                 
147
148         [MonoTODO]
149         public override int GetLeapMonth(int year, int era)
150         {
151                 return base.GetLeapMonth(year, era);
152         }
153
154         [MonoTODO]
155         public override int GetMonth(DateTime time) {
156                 M_CheckDateTime(time);
157                 return CCEastAsianLunisolarCalendar.GetMonth(time);
158         }
159
160         [MonoTODO]
161         public override int GetMonthsInYear(int year, int era) {
162                 M_CheckYE(year, ref era);
163                 return IsLeapYear (year, era) ? 13: 12;
164         }
165
166         public override int GetYear(DateTime time) {
167                 // M_CheckDateTime not needed, because EraYeat does the
168                 // right thing.
169                 int rd = CCFixed.FromDateTime(time);
170                 int era;
171                 return M_EraHandler.EraYear(out era, rd);
172         }
173
174         public override bool IsLeapDay(int year, int month, int day, int era)
175         {
176                 int gregorianYear = M_CheckYMDEG(year, month, day, ref era);
177                 // every day in LeapMonth is a LeapDay.
178                 return CCEastAsianLunisolarCalendar.IsLeapMonth (gregorianYear, month);
179         }
180
181         [MonoTODO]
182         public override bool IsLeapMonth(int year, int month, int era) {
183                 int gregorianYear = M_CheckYMEG(year, month, ref era);
184                 return CCEastAsianLunisolarCalendar.IsLeapMonth(gregorianYear, month);
185         }
186
187         public override bool IsLeapYear(int year, int era) {
188                 int gregorianYear = M_CheckYEG(year, ref era);
189                 return CCEastAsianLunisolarCalendar.IsLeapYear (gregorianYear);
190         }
191
192         [MonoTODO]
193         public override DateTime ToDateTime(int year, int month, int day,
194                 int hour, int minute, int second, int millisecond,
195                 int era)
196         {
197                 int gregorianYear = M_CheckYMDEG(year, month, day, ref era);
198                 M_CheckHMSM(hour, minute, second, millisecond);
199                 return CCGregorianCalendar.ToDateTime(
200                         gregorianYear, month, day,
201                         hour, minute, second, millisecond);
202         }
203
204         [MonoTODO]
205         public override int ToFourDigitYear(int year) {
206                 if (year < 0)
207                         throw new ArgumentOutOfRangeException(
208                                 "year", "Non-negative number required.");
209                 int era = CurrentEra;
210                 M_CheckYE(year, ref era);
211                 return year;
212         }
213
214         public override CalendarAlgorithmType AlgorithmType {
215                 get {
216                         return CalendarAlgorithmType.LunisolarCalendar;
217                 }
218         }
219
220
221         #region celestial/terrestial thingy
222         public int GetCelestialStem (int sexagenaryYear)
223         {
224                 if (sexagenaryYear < 1 || 60 < sexagenaryYear)
225                         throw new ArgumentOutOfRangeException ("sexagendaryYear is less than 0 or greater than 60");
226                 return (sexagenaryYear - 1) % 10 + 1;
227         }
228
229         public virtual int GetSexagenaryYear (DateTime time)
230         {
231                 return (GetYear (time) - 1900) % 60;
232         }
233
234         public int GetTerrestrialBranch (int sexagenaryYear)
235         {
236                 if (sexagenaryYear < 1 || 60 < sexagenaryYear)
237                         throw new ArgumentOutOfRangeException ("sexagendaryYear is less than 0 or greater than 60");
238                 return (sexagenaryYear - 1) % 12 + 1;
239         }
240         #endregion
241 }
242 }