Add new files from Wictor Wilen
[mono.git] / mcs / class / corlib / System.Globalization / Calendar.cs
1 // ::MONO
2 //
3 // System.Globalization.Calendar.cs
4 //
5 // Copyright (C) Wictor Wilén 2001 (wictor@iBizkit.se)
6 //
7 // Contributors: Marcel Narings, Wictor Wilén
8 //
9 // Revisions
10 // 2001-09-14:  First draft
11 // 2001-09-15:  First release
12 //
13 //
14 // TODO: testing
15 //
16 //
17
18 using System;
19
20 namespace System.Globalization
21 {
22         /// <summary>
23         /// Implmentation of the System.Globalization.Calendar class
24         /// </summary>
25         public abstract class Calendar
26         {
27                 /// <summary>
28                 /// The Calendar Constructor
29                 /// </summary>
30                 protected Calendar () 
31                 {
32                         _MaxDateTime = DateTime.MaxValue;
33                         _MinDateTime = DateTime.MinValue;
34                 }
35                 protected int _TwoDigitYearMax;
36
37                 protected static int[] _DaysInMonth = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
38                 protected static int[] _DaysInMonthLeap = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
39                 
40
41                 // these can be overridden, for example using "new protected const int _MinYear = 1;"
42                 protected const int _MinYear = 1;
43                 protected const int _MaxYear = 9999;
44                 protected const int _MinDay = 0;
45                 protected const int _MinMonth = 1;
46                 protected const int _MaxMonth = 12;
47                 protected const int _MinHour = 0;
48                 protected const int _MaxHour = 23;
49                 protected const int _MinMinute = 0;
50                 protected const int _MaxMinute = 59;
51                 protected const int _MinSecond = 0;
52                 protected const int _MaxSecond = 59;
53                 protected const int _MinMillisecond = 0;
54                 protected const int _MaxMillisecond = 999;
55
56                 private const long _TicksPerMillisecond = 10000;
57                 private const long _TicksPerSecond = 10000000;
58                 private const long _TicksPerMinute = 600000000;
59                 private const long _TicksPerHour = 36000000000;
60                 private const long _TicksPerDay = 864000000000;
61                 private const long _TicksPerWeek = 6048000000000;
62
63                 protected DateTime _MaxDateTime;
64                 protected DateTime _MinDateTime;
65
66                 
67                 /// <summary>
68                 /// The Currentera constant
69                 /// </summary>
70                 public const int CurrentEra = 0;
71                 
72                 /// <summary>
73                 /// Returns an array of the available eras
74                 /// </summary>
75                 public abstract int[] Eras {get;}
76
77                 // DONE!
78                 /// <summary>
79                 /// The Two digit max
80                 /// </summary>
81                 public virtual int TwoDigitYearMax 
82                 {
83                         get
84                         {
85                                 return _TwoDigitYearMax;
86                         } 
87                         set
88                         {
89                                 _TwoDigitYearMax = value;
90                         }
91                 }
92
93                 // DONE!
94                 public virtual DateTime AddDays ( DateTime time, int days )
95                 {
96                         return new DateTime(time.Ticks).AddTicks(_TicksPerDay*days);
97                 }
98
99                 // DONE!
100                 public virtual DateTime AddHours ( DateTime time, int hours )
101                 {
102                         return new DateTime(time.Ticks).AddTicks(_TicksPerHour*hours);
103                 }
104
105                 // DONE!
106                 public virtual DateTime AddMilliseconds ( DateTime time, double milliseconds )
107                 {
108                         DateTime t = new DateTime(time.Ticks);
109                         return t.AddMilliseconds(milliseconds);
110                 }
111
112                 // DONE!
113                 public virtual DateTime AddMinutes ( DateTime time, int minutes )
114                 {
115                         return new DateTime(time.Ticks).AddTicks(_TicksPerMinute * minutes);
116                 }
117
118                 // DONE!
119                 /// <summary>
120                 /// Returns a DateTime that is the specified number of months away from the specified DateTime
121                 /// </summary>
122                 /// <param name="time"></param>
123                 /// <param name="months"></param>
124                 /// <returns></returns>
125                 /// <remarks>Calculates correct comapared to .NET Beta 2</remarks>
126                 public virtual DateTime AddMonths ( DateTime time, int months )         
127                 {
128                         DateTime t = new DateTime(time.Ticks);
129                         return t.AddMonths(months);
130                 }
131
132                 // DONE!
133                 public virtual DateTime AddSeconds ( DateTime time, int seconds )               
134                 {
135                         return new DateTime(time.Ticks).AddTicks(_TicksPerSecond * seconds);
136                 }
137
138                 // DONE!
139                 public virtual DateTime AddWeeks ( DateTime time, int weeks )           
140                 {
141                         return new DateTime(time.Ticks).AddTicks(_TicksPerWeek * weeks);
142                 }
143
144                 // DONE!
145                 public virtual DateTime AddYears ( DateTime time, int years )           
146                 {
147                         DateTime t = new DateTime(time.Ticks);
148                         return t.AddYears(years);
149                 }
150
151                 
152
153                 // DONE!
154                 public abstract int GetDayOfMonth ( DateTime time );
155
156                 // DONE!
157                 public abstract DayOfWeek GetDayOfWeek ( DateTime time );
158
159                 // DONE!
160                 public abstract int GetDayOfYear ( DateTime time );
161
162                 // DONE!
163                 public virtual int GetDaysInMonth ( int year, int month )
164                 {
165                         if(year < _MinYear || year > _MaxYear || month < _MinMonth || month > _MaxMonth)
166                                 throw new System.ArgumentOutOfRangeException();
167
168                         if(this.IsLeapYear(year))
169                                 return _DaysInMonthLeap[month];
170                         else
171                                 return _DaysInMonth[month];
172                 }
173
174                 // DONE!
175                 public abstract int GetDaysInMonth ( int year, int month, int era );
176
177                 // DONE!
178                 public virtual int GetDaysInYear ( int year)
179                 {
180                         if( year < _MinYear || year > _MaxYear)
181                                 throw new System.ArgumentOutOfRangeException();
182
183                         if(this.IsLeapYear(year))
184                                 return 366;
185                         else
186                                 return 365;
187                 }
188
189                 // DONE!
190                 public abstract int GetDaysInYear ( int year, int era );
191                 
192                 // DONE!
193                 public abstract int GetEra ( DateTime time );
194                 
195                 // DONE!
196                 public virtual int GetHour ( DateTime time )
197                 {
198                         return time.Hour;
199                 }
200                 // DONE!
201                 public virtual double GetMilliseconds ( DateTime time )
202                 {
203                         return time.Millisecond;
204                 }
205                 // DONE!
206                 public virtual int GetMinute ( DateTime time )
207                 {
208                         return time.Minute;
209                 }
210
211                 // DONE!
212                 public abstract int GetMonth ( DateTime time );
213                 
214                 // DONE!
215                 public virtual int GetMonthsInYear ( int year )
216                 {
217                         if( year < _MinYear || year > _MaxYear)
218                                 throw new System.ArgumentException();
219
220                         return _MaxMonth;
221                 }
222
223                 // DONE!
224                 public abstract int GetMonthsInYear ( int year, int era );
225
226                 // DONE!
227                 public virtual int GetSecond ( DateTime time )
228                 {
229                         return time.Second;
230                 }
231
232                 // DONE!
233                 /// <summary>
234                 /// Gets the week of the year that includes the date in the specified DateTime
235                 /// </summary>
236                 /// <param name="time"></param>
237                 /// <param name="rule"></param>
238                 /// <param name="firstDayOfWeek"></param>
239                 /// <returns></returns>
240                 /// <remarks>.NET beta 2 calculates this erroneous, but this one is ok(? I think...)</remarks>
241                 public virtual int GetWeekOfYear ( DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek )
242                 {
243                         if( firstDayOfWeek < DayOfWeek.Sunday || firstDayOfWeek > DayOfWeek.Saturday)
244                                 throw new System.ArgumentOutOfRangeException();
245                         
246                         int week;
247                         int days = 0;
248                         
249                         int[] dim;
250                         if(this.IsLeapYear(time.Year))
251                                 dim = _DaysInMonthLeap;
252                         else
253                                 dim = _DaysInMonth;
254
255                         DateTime jan1 = new DateTime(time.Year, 1, 1);
256
257                         for( int i = 0; i < time.Month-1; i++)
258                                 days += dim[i];
259                         days += time.Day;
260
261                         switch(rule)
262                         {
263                                 case CalendarWeekRule.FirstDay:
264                                         while(jan1.DayOfWeek != firstDayOfWeek)
265                                         {
266                                                 days--;
267                                                 jan1 = jan1.AddTicks(_TicksPerDay);
268                                         }
269                                         break;
270                                 case CalendarWeekRule.FirstFourDayWeek:
271                                         while(jan1.DayOfWeek < firstDayOfWeek)
272                                         {
273                                                 days--;
274                                                 jan1 = jan1.AddTicks(_TicksPerDay);
275                                         }
276                                         break;
277                                 case CalendarWeekRule.FirstFullWeek:
278                                         if(jan1.DayOfWeek != firstDayOfWeek)
279                                         {
280                                                 do
281                                                 {
282                                                         days--;
283                                                         jan1 = jan1.AddTicks(_TicksPerDay);
284                                                 }
285                                                 while(jan1.DayOfWeek != firstDayOfWeek);
286                                         }
287                                         break;
288                                 default:
289                                         throw new System.ArgumentOutOfRangeException();
290                         }
291
292                         if(days <= 0)
293                                 week = GetWeekOfYear(new DateTime(time.Year-1,12,31), rule, firstDayOfWeek);
294                         else
295                                 week = (--days / 7) + 1;
296                         
297                         return week;
298                 }
299
300                 // DONE!
301                 public abstract int GetYear ( DateTime time );
302                 
303                 // DONE!
304                 // TODO: verify this for the Calendar Class
305                 public virtual bool IsLeapDay ( int year, int month, int day )
306                 {
307                         int dim;
308
309                         if(day < _MinDay || month < _MinMonth || month > _MaxMonth)
310                                 throw new System.ArgumentOutOfRangeException();
311
312                         if(this.IsLeapYear(year))
313                                 dim = _DaysInMonthLeap[month-1];
314                         else
315                                 dim = _DaysInMonth[month-1];
316
317                         if( day > dim)
318                                 throw new System.ArgumentOutOfRangeException();
319
320                         if( month == 2 && day == 29)
321                                 return true;
322                         
323                         return false;
324                 }
325
326                 // DONE!
327                 public abstract bool IsLeapDay ( int year, int month, int day, int era );
328
329                 // DONE!
330                 public virtual bool IsLeapMonth ( int year, int month )
331                 {
332                         if( year < _MinYear || year > _MaxYear || month < _MinMonth || month > _MaxMonth)
333                                 throw new System.ArgumentOutOfRangeException();
334
335                         if(this.IsLeapYear(year))
336                         {
337                                 return true;
338                         }
339                         else
340                                 return false;
341                 }
342                 
343                 // DONE!
344                 public abstract bool IsLeapMonth ( int year, int month, int era );
345
346                 public virtual bool IsLeapYear ( int year )
347                 {
348                         if(year < _MinYear || year > _MaxYear )
349                                 throw new System.ArgumentOutOfRangeException();
350                         if(year % 4 == 0) // TODO: verify this for the Calendar class!
351                                 return true;
352                         return false;
353                 }
354
355                 // DONE!
356                 public abstract bool IsLeapYear ( int year, int era );
357
358                 // DONE!
359                 public virtual DateTime ToDateTime ( int year, int month, int day, int hour, int minute, int second, int millisecond )
360                 {
361                         int dim;
362                         dim = GetDaysInMonth(year,month);
363                         if( day < _MinDay || day > dim || 
364                                 hour < _MinHour || hour > _MaxHour ||
365                                 minute < _MinMinute || minute > _MaxMinute ||
366                                 second < _MinSecond || second > _MaxSecond ||
367                                 millisecond < _MinMillisecond || millisecond > _MaxMillisecond)
368                                 throw new System.ArgumentOutOfRangeException();
369
370                         return new DateTime(year,month,day,hour,minute,second,millisecond,this);
371                 }
372
373                 // DONE!
374                 public abstract DateTime ToDateTime ( int year, int month, int date, int hour, int minute, int second, int millisecond, int era );
375
376                 // DONE!
377                 public virtual int ToFourDigitYear ( int year )
378                 {
379                         int i = year - ( _TwoDigitYearMax % 100 );
380                         if( year > 0 )
381                                 return _TwoDigitYearMax - 100 + year;
382                         else
383                                 return _TwoDigitYearMax + year;
384                 }
385         }
386 }