2001-11-28 Miguel de Icaza <miguel@ximian.com>
[mono.git] / mcs / class / corlib / System / DateTime.cs
1 //\r
2 // System.DateTime.cs\r
3 //\r
4 // author:\r
5 //   Marcel Narings (marcel@narings.nl)\r
6 //\r
7 //   (C) 2001 Marcel Narings\r
8 \r
9 using System;\r
10 using System.Globalization ;\r
11 \r
12 \r
13 namespace System\r
14 {\r
15         /// <summary>\r
16         /// The DateTime structure represents dates and time ranging from\r
17         /// 1-1-0001 12:00:00 AM to 31-12-9999 23:59:00 Common Era.\r
18         /// </summary>\r
19         /// \r
20         public struct DateTime : IComparable , IFormattable  , IConvertible\r
21         {\r
22                 long ticks;\r
23 \r
24                 private const long MaxTicks = 3155378975999999999L;\r
25                 private const long MinTicks = 0L;\r
26                 private const int dp400 = 146097;\r
27                 private const int dp100 = 36524;\r
28                 private const int dp4 = 1461;\r
29                 \r
30                 public static readonly DateTime MaxValue = new DateTime (MaxTicks);\r
31                 public static readonly DateTime MinValue = new DateTime (MinTicks);\r
32                 \r
33                 private enum Which \r
34                 {\r
35                         Day,\r
36                         DayYear,\r
37                         Month,\r
38                         Year\r
39                 };\r
40         \r
41                 private static int[] daysmonth = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; \r
42                 private static int[] daysmonthleap = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };     \r
43 \r
44                 private static long AbsoluteDays (int year, int month, int day)\r
45                 {\r
46                         int[] days;\r
47                         int temp = 0, m=1 ;\r
48                 \r
49                         days = (IsLeapYear(year) ? daysmonthleap  : daysmonth);\r
50                         \r
51                         while (m < month)\r
52                                 temp += days[m++];\r
53                         return ((day-1) + temp + (365* (year-1)) + ((year-1)/4) - ((year-1)/100) + ((year-1)/400));\r
54                 }\r
55 \r
56                 private int FromTicks(Which what)\r
57                 {\r
58                         int num400, num100, num4, numyears; \r
59                         int M =1;\r
60 \r
61                         int[] days = daysmonth;\r
62                         int totaldays = (int) (ticks / TimeSpan.TicksPerDay);\r
63                         \r
64                         num400 = (totaldays / dp400);\r
65                         totaldays -=  num400 * dp400;\r
66                 \r
67                         num100 = (totaldays / dp100);\r
68                         if (num100 == 4)   // leap\r
69                                 num100 = 3;\r
70                         totaldays -= (num100 * dp100);\r
71 \r
72                         num4 = totaldays / dp4;\r
73                         totaldays -= (num4 * dp4);\r
74 \r
75                         numyears = totaldays / 365 ;\r
76                         \r
77                         if (numyears == 4)  //leap\r
78                                 numyears =3 ;\r
79                         if (what == Which.Year )\r
80                                 return num400*400 + num100*100 + num4*4 + numyears + 1;\r
81 \r
82                         totaldays -= (numyears * 365) ;\r
83                         if (what == Which.DayYear )\r
84                                 return totaldays + 1;\r
85                         \r
86                         if  ((numyears==3) && ((num100 == 3) || !(num4 == 24)) ) //31 dec leapyear\r
87                                 days = daysmonthleap;\r
88                                 \r
89                         while (totaldays >= days[M])\r
90                                 totaldays -= days[M++];\r
91 \r
92                         if (what == Which.Month )\r
93                                 return M;\r
94 \r
95                         return totaldays +1; \r
96 \r
97 \r
98                 }\r
99 \r
100 \r
101                 // Constructors\r
102                 \r
103                 /// <summary>\r
104                 /// Constructs a DateTime for specified ticks\r
105                 /// </summary>\r
106                 /// \r
107                 public DateTime (long newticks) \r
108                 {\r
109                         ticks = newticks;\r
110                 \r
111                         if ( newticks < MinValue.ticks || newticks > MaxValue.ticks)\r
112                                 throw new ArgumentOutOfRangeException ();\r
113                 }\r
114 \r
115                 public DateTime (int year, int month, int day)\r
116                         : this (year, month, day,0,0,0,0) {}\r
117 \r
118                 public DateTime (int year, int month, int day, int hour, int minute, int second)\r
119                         : this (year, month, day, hour, minute, second, 0)      {}\r
120 \r
121                 public DateTime (int year, int month, int day, int hour, int minute, int second, int millisecond)\r
122                 {\r
123                         if ( year < 1 || year > 9999 || \r
124                                 month < 1 || month >12  ||\r
125                                 day < 1 || day > DaysInMonth(year, month) ||\r
126                                 hour < 0 || hour > 23 ||\r
127                                 minute < 0 || minute > 59 ||\r
128                                 second < 0 || second > 59 )\r
129                                 throw new ArgumentOutOfRangeException() ;\r
130                                 \r
131                         ticks = AbsoluteDays(year,month,day) * TimeSpan.TicksPerDay + \r
132                                 hour * TimeSpan.TicksPerHour + \r
133                                 minute * TimeSpan.TicksPerMinute + \r
134                                 second * TimeSpan.TicksPerSecond + \r
135                                 millisecond * TimeSpan.TicksPerMillisecond ; \r
136                         \r
137                         if (ticks < MinValue.ticks || ticks > MaxValue.ticks )\r
138                                 throw new ArgumentException() ;\r
139                 }\r
140 \r
141                 public DateTime (int year, int month, int day, Calendar calendar)\r
142                         : this (year, month, day, 0, 0, 0, 0, calendar) {}\r
143 \r
144                 \r
145                 public DateTime (int year, int month, int day, int hour, int minute, int second, Calendar calendar)\r
146                         : this (year, month, day, hour, minute, second, 0, calendar)    {}\r
147 \r
148 \r
149                 public DateTime (int year, int month, int day, int hour, int minute, int second, int millisecond, Calendar calendar)\r
150                         : this(year, month, day, hour, minute, second, millisecond) \r
151                 {\r
152                         if ( calendar == null)\r
153                                 throw new ArgumentNullException();\r
154                 }\r
155 \r
156 \r
157                 /* Properties  */\r
158                  \r
159                 public DateTime Date \r
160                 {\r
161                         get     \r
162                         { \r
163                                 return new DateTime(ticks - (ticks % TimeSpan.TicksPerDay )) ; \r
164                         }\r
165                 }\r
166         \r
167                 public int Day\r
168                 {\r
169                         get \r
170                         { \r
171                                 return FromTicks(Which.Day); \r
172                         }\r
173                 }\r
174 \r
175                 public DayOfWeek DayOfWeek \r
176                 {\r
177                         get \r
178                         { \r
179                                 return ( (DayOfWeek) (((ticks / TimeSpan.TicksPerDay)+1) % 7) ); \r
180                         }\r
181                 }\r
182 \r
183                 public int DayOfYear \r
184                 {\r
185                         get \r
186                         { \r
187                                 return FromTicks(Which.DayYear); \r
188                         }\r
189                 }\r
190 \r
191                 public int Hour \r
192                 {\r
193                         get \r
194                         { \r
195                                 return ( (int) ((ticks % TimeSpan.TicksPerDay) / TimeSpan.TicksPerHour) );  \r
196                         }\r
197                 }\r
198 \r
199                 public int Millisecond \r
200                 {\r
201                         get \r
202                         { \r
203                                 return ( (int) (ticks % TimeSpan.TicksPerSecond / TimeSpan.TicksPerMillisecond) ); \r
204                         }\r
205                 }\r
206                 \r
207                 public int Minute \r
208                 {\r
209                         get \r
210                         { \r
211                                 return ( (int) (ticks % TimeSpan.TicksPerHour / TimeSpan.TicksPerMinute) ); \r
212                         }\r
213                 }\r
214 \r
215                 public int Month \r
216                 {\r
217                         get     \r
218                         { \r
219                                 return FromTicks(Which.Month); \r
220                         }\r
221                 }\r
222 \r
223                 // TODO implement me             \r
224                 public static DateTime Now \r
225                 {\r
226                         get     \r
227                         { \r
228                                 return new DateTime (0); \r
229                         }\r
230                 }\r
231 \r
232                 public int Second \r
233                 {\r
234                         get     \r
235                         { \r
236                                 return (int) (ticks % TimeSpan.TicksPerMinute / TimeSpan.TicksPerSecond); \r
237                         }\r
238                 }\r
239 \r
240                 public long Ticks\r
241                 { \r
242                         get     \r
243                         { \r
244                                 return ticks ; \r
245                         }\r
246                 }\r
247         \r
248                 public TimeSpan TimeOfDay \r
249                 {\r
250                         get     \r
251                         { \r
252                                 return new TimeSpan(ticks % TimeSpan.TicksPerDay );\r
253                         }\r
254                         \r
255                 }\r
256 \r
257                 //TODO implement\r
258                 public static DateTime Today \r
259                 {\r
260                         get     \r
261                         {\r
262                                 return new DateTime (0);\r
263                         }\r
264                 }\r
265 \r
266                 //TODO implement\r
267                 public static DateTime UtcNow \r
268                 {\r
269                         get {\r
270                                 return new DateTime (0);\r
271                         }\r
272                 }\r
273 \r
274                 public int Year \r
275                 {\r
276                         get \r
277                         { \r
278                                 return FromTicks(Which.Year); \r
279                         }\r
280                 }\r
281 \r
282                 /* methods */\r
283 \r
284                 public DateTime Add (TimeSpan ts)\r
285                 {\r
286                         long newticks ;\r
287 \r
288                         newticks = ticks + ts.Ticks ;\r
289 \r
290                         if (ts.Ticks < MinTicks || ts.Ticks > MaxTicks || \r
291                                 newticks < MinTicks || newticks > MaxTicks)\r
292                                 throw new ArgumentException ();\r
293                         \r
294                         return new DateTime (newticks);\r
295                 }\r
296 \r
297                 public DateTime AddDays (double days)\r
298                 {\r
299                         return AddMilliseconds (days * 86400000);\r
300                 }\r
301                 \r
302                 public DateTime AddTicks (long t)\r
303                 {\r
304                         long newticks = ticks + t; \r
305 \r
306                         if (t<MinTicks || t>MaxTicks || newticks<MinTicks || newticks>MaxTicks)\r
307                                 throw new ArgumentException ();\r
308 \r
309                         return new DateTime(newticks);\r
310                 }\r
311 \r
312                 public DateTime AddHours (double hours)\r
313                 {\r
314                         return AddMilliseconds (hours * 3600000);\r
315                 }\r
316 \r
317                 public DateTime AddMilliseconds (double ms)\r
318                 {\r
319                         long msticks, newticks;\r
320                         \r
321                         msticks = (long) (ms += ms > 0 ? 0.5 : -0.5) * TimeSpan.TicksPerMillisecond ; \r
322                         newticks = ticks + msticks ;\r
323 \r
324                         if (msticks < MinTicks || msticks > MaxTicks ||\r
325                                 newticks < MinTicks || newticks > MaxTicks)\r
326                                 throw new ArgumentException ();\r
327 \r
328                         return new DateTime (newticks);\r
329                 }\r
330 \r
331                 public DateTime AddMinutes (double minutes)\r
332                 {\r
333                         return AddMilliseconds (minutes * 60000);\r
334                 }\r
335                 \r
336                 public DateTime AddMonths (int months)\r
337                 {\r
338                         int day, month, year,  maxday ;\r
339                         DateTime temp ;\r
340 \r
341                         day = this.Day;\r
342                         month = this.Month + (months % 12);\r
343                         year = this.Year + months/12 ;\r
344                         \r
345                         if (month < 1)\r
346                         {\r
347                                 month = 12 + month ;\r
348                                 year -- ;\r
349                         }\r
350                         else if (month>12) \r
351                         {\r
352                                 month = month -12;\r
353                                 year ++;\r
354                         }\r
355                         maxday = DaysInMonth(year, month);\r
356                         if (day > maxday)\r
357                                 day = maxday;\r
358 \r
359                         temp = new DateTime (year, month, day);\r
360             return  temp.Add (this.TimeOfDay);\r
361                 }\r
362 \r
363                 public DateTime AddSeconds (double seconds)\r
364                 {\r
365                         return AddMilliseconds (seconds*1000);\r
366                 }\r
367 \r
368                 public DateTime AddYears (int years )\r
369                 {\r
370                         return AddMonths(years * 12);\r
371                 }\r
372 \r
373                 public static int Compare (DateTime t1, DateTime t2)\r
374                 {\r
375                         if (t1.ticks < t2.ticks) \r
376                                 return -1;\r
377                         else if (t1.ticks > t2.ticks) \r
378                                 return 1;\r
379                         else\r
380                                 return 0;\r
381                 }\r
382 \r
383                 public int CompareTo (object v)\r
384                 {\r
385                         if ( v == null)\r
386                                 return 1;\r
387 \r
388                         if (!(v is System.DateTime))\r
389                                 throw new ArgumentException (Locale.GetText (\r
390                                         "Value is not a System.DateTime"));\r
391 \r
392                         return Compare (this, (DateTime) v);\r
393                 }\r
394 \r
395                 public static int DaysInMonth (int year, int month)\r
396                 {\r
397                         int[] days ;\r
398 \r
399                         if (month < 1 || month >12)\r
400                                 throw new ArgumentOutOfRangeException ();\r
401 \r
402                         days = (IsLeapYear(year) ? daysmonthleap  : daysmonth);\r
403                         return days[month];                     \r
404                 }\r
405                 \r
406                 public override bool Equals (object o)\r
407                 {\r
408                         if (!(o is System.DateTime))\r
409                                 return false;\r
410 \r
411                         return ((DateTime) o).ticks == ticks;\r
412                 }\r
413 \r
414                 public static bool Equals (DateTime t1, DateTime t2 )\r
415                 {\r
416                         return (t1.ticks == t2.ticks );\r
417                 }\r
418 \r
419                 // TODO: Implement me.\r
420                 public static DateTime FromFileTime (long fileTime) \r
421                 {\r
422                         return new DateTime (0);\r
423                 }\r
424 \r
425                 // TODO: Implement me.\r
426                 public static DateTime FromOADate (double d)\r
427                 {\r
428                                 return new DateTime(0);\r
429                 }\r
430                 \r
431                 // TODO: Implement me.\r
432                 public string[] GetDateTimeFormats() \r
433                 {\r
434                         return null;\r
435                 }\r
436 \r
437                 //TODO: implement me \r
438                 public string[] GetDateTimeFormats(     char format     )\r
439                 {\r
440                         return null;\r
441                 }\r
442                 \r
443                 // TODO: implement me \r
444                 public string[] GetDateTimeFormats(     IFormatProvider provider)\r
445                 {\r
446                         return null;\r
447                 }\r
448 \r
449                 //TODO: implement me \r
450                 public string[] GetDateTimeFormats(char format,IFormatProvider provider )\r
451                 {\r
452                         return null;\r
453                 }\r
454 \r
455                 public override int GetHashCode ()\r
456                 {\r
457                         return (int) ticks;\r
458                 }\r
459 \r
460                 public TypeCode GetTypeCode ()\r
461                 {\r
462                         return TypeCode.DateTime;\r
463                 }\r
464 \r
465                 public static bool IsLeapYear (int year)\r
466                 {\r
467                         return  ( (year % 4 == 0 && year % 100 != 0) || year % 400 == 0) ;\r
468                 }\r
469 \r
470                 public static DateTime Parse (string s)\r
471                 {\r
472                         // TODO: Implement me\r
473                         return new DateTime (0);\r
474                 }\r
475 \r
476                 public static DateTime Parse (string s, IFormatProvider fp)\r
477                 {\r
478                         // TODO: Implement me\r
479                         return new DateTime (0);\r
480                 }\r
481 \r
482                 public static DateTime Parse (string s, NumberStyles style, IFormatProvider fp)\r
483                 {\r
484                         // TODO: Implement me\r
485                         return new DateTime (0);\r
486                 }\r
487 \r
488                 public static DateTime ParseExact(string s,     string format, IFormatProvider provider )\r
489                 {\r
490                         // TODO: Implement me\r
491                         return new DateTime (0);\r
492                 }\r
493 \r
494                 public static DateTime ParseExact(string s, string format, IFormatProvider provider, DateTimeStyles style )\r
495                 {\r
496                         // TODO: Implement me\r
497                         return new DateTime (0);\r
498                 \r
499                 }\r
500 \r
501                 public static DateTime ParseExact( string s, string[] formats, IFormatProvider provider, DateTimeStyles style )\r
502                 {\r
503                         // TODO: Implement me\r
504                         return new DateTime (0);\r
505                 \r
506                 }\r
507                 \r
508                 public TimeSpan Subtract(DateTime dt )\r
509                 {   \r
510                         return new TimeSpan(ticks - dt.ticks );\r
511                 }\r
512 \r
513                 public DateTime Subtract(TimeSpan ts)\r
514                 {       \r
515                         return new DateTime(ticks - ts.Ticks );\r
516                 }\r
517 \r
518                 public long ToFileTime()\r
519                 {\r
520                                 // TODO: Implement me\r
521                         return 0 ;\r
522                 }\r
523 \r
524                 public DateTime ToLocalTime()\r
525                 {\r
526                         // TODO Implement me \r
527                         return new DateTime (0);\r
528                 }\r
529 \r
530                 public string ToLongDateString()\r
531                 {\r
532                         // TODO implement me\r
533                         throw new NotImplementedException ();\r
534                 }\r
535 \r
536                 public string ToLongTimeString()\r
537                 {\r
538                         // TODO implement me\r
539                         throw new NotImplementedException ();\r
540                 }\r
541 \r
542                 public double ToOADate()\r
543                 {\r
544                         // TODO implement me \r
545                         return 0;\r
546                 }\r
547 \r
548                 public string ToShortDateString()\r
549                 {\r
550                         // TODO implement me \r
551                         throw new NotImplementedException ();\r
552                 }\r
553 \r
554                 public string ToShortTimeString()\r
555                 {\r
556                         // TODO implement me\r
557                         throw new NotImplementedException ();\r
558                 }\r
559         \r
560                 public override string ToString ()\r
561                 {\r
562                         // TODO: Implement me\r
563                         throw new NotImplementedException ();\r
564                 }\r
565 \r
566                 public string ToString (IFormatProvider fp)\r
567                 {\r
568                         // TODO: Implement me.\r
569                         throw new NotImplementedException ();\r
570                 }\r
571 \r
572                 public string ToString (string format)\r
573                 {\r
574                         // TODO: Implement me.\r
575                         throw new NotImplementedException ();\r
576                 }\r
577 \r
578                 public string ToString (string format, IFormatProvider fp)\r
579                 {\r
580                         // TODO: Implement me.\r
581                         throw new NotImplementedException ();\r
582                 }\r
583 \r
584                 public DateTime ToUniversalTime()\r
585                 {\r
586                         // TODO: implement me \r
587                         return new DateTime(0);\r
588                 }\r
589 \r
590                 /*  OPERATORS */\r
591 \r
592                 public static DateTime operator +(DateTime d, TimeSpan t)\r
593                 {\r
594                         return new DateTime (d.ticks + t.Ticks);\r
595                 }\r
596 \r
597                 public static bool operator ==(DateTime d1, DateTime d2)\r
598                 {\r
599                         return (d1.ticks == d2.ticks);\r
600                 }\r
601 \r
602                 public static bool operator >(DateTime t1,DateTime t2)\r
603                 {\r
604                         return (t1.ticks > t2.ticks);\r
605                 }\r
606 \r
607                 public static bool operator >=(DateTime t1,DateTime t2)\r
608                 {\r
609                         return (t1.ticks >= t2.ticks);\r
610                 }\r
611 \r
612                 public static bool operator !=(DateTime d1, DateTime d2)\r
613                 {\r
614                         return (d1.ticks != d2.ticks);\r
615                 }\r
616 \r
617                 public static bool operator <(DateTime t1,      DateTime t2)\r
618                 {\r
619                         return (t1.ticks < t2.ticks );\r
620                 }\r
621 \r
622                 public static bool operator <=(DateTime t1,DateTime t2)\r
623                 {\r
624                         return (t1.ticks <= t2.ticks);\r
625                 }\r
626 \r
627                 public static TimeSpan operator -(DateTime d1,DateTime d2)\r
628                 {\r
629                         return new TimeSpan(d1.ticks - d2.ticks);\r
630                 }\r
631 \r
632                 public static DateTime operator -(DateTime d,TimeSpan t )\r
633                 {\r
634                         return new DateTime (d.ticks - t.Ticks);\r
635                 }\r
636 \r
637                 public bool ToBoolean(IFormatProvider provider)\r
638                 {\r
639                         throw new InvalidCastException();\r
640                 }\r
641                 \r
642                 public byte ToByte(IFormatProvider provider)\r
643                 {\r
644                         throw new InvalidCastException();\r
645                 }\r
646 \r
647                 public char ToChar(IFormatProvider provider)\r
648                 {\r
649                         throw new InvalidCastException();\r
650                 }\r
651 \r
652                 // TODO Implement me  \r
653                 public System.DateTime ToDateTime(IFormatProvider provider)\r
654                 {\r
655                         return new System.DateTime(this.ticks);\r
656                 } \r
657                 \r
658                 public decimal ToDecimal(IFormatProvider provider)\r
659                 {\r
660                          throw new InvalidCastException();\r
661                 }\r
662 \r
663                 public double ToDouble(IFormatProvider provider)\r
664                 {\r
665                         throw new InvalidCastException();\r
666                 }\r
667 \r
668                 public Int16 ToInt16(IFormatProvider provider)\r
669                 {\r
670                         throw new InvalidCastException();\r
671                 }\r
672 \r
673                 public Int32 ToInt32(IFormatProvider provider)\r
674                 {\r
675                         throw new InvalidCastException();\r
676                 }\r
677 \r
678                 public Int64 ToInt64(IFormatProvider provider)\r
679                 {\r
680                         throw new InvalidCastException();\r
681                 }\r
682 \r
683                 [CLSCompliant(false)]\r
684                 public SByte ToSByte(IFormatProvider provider)\r
685                 {\r
686                         throw new InvalidCastException();\r
687                 }\r
688 \r
689                 public Single ToSingle(IFormatProvider provider)\r
690                 {\r
691                         throw new InvalidCastException();\r
692                 }\r
693 \r
694                 public object ToType(Type conversionType,IFormatProvider provider)\r
695                 {\r
696                         throw new InvalidCastException();\r
697                 }\r
698 \r
699                 UInt16 System.IConvertible.ToUInt16(IFormatProvider provider)\r
700                 {\r
701                         throw new InvalidCastException();\r
702                 }\r
703                 \r
704                 [CLSCompliant(false)]\r
705                 public UInt32 ToUInt32(IFormatProvider provider)\r
706                 {\r
707                         throw new InvalidCastException();\r
708                 }\r
709 \r
710                 [CLSCompliant(false)]\r
711                 public UInt64 ToUInt64(IFormatProvider provider)\r
712                 {\r
713                         throw new InvalidCastException();\r
714                 }\r
715         }\r
716 }\r
717 \r
718 namespace System\r
719 {\r
720         public enum DayOfWeek\r
721         {\r
722                 Sunday,\r
723                 Monday,\r
724                 Tuesday,\r
725                 Wednesday,\r
726                 Thursday,\r
727                 Friday,\r
728                 Saturday\r
729         }\r
730 }\r
731 \r