Remove negatives from z format; patch from Ed Thomson <ethomson@sourcegear.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 //   Martin Baulig (martin@gnome.org)\r
7 //\r
8 //   (C) 2001 Marcel Narings\r
9 \r
10 using System;\r
11 using System.Globalization;\r
12 using System.Runtime.CompilerServices;\r
13 \r
14 \r
15 namespace System\r
16 {\r
17         /// <summary>\r
18         /// The DateTime structure represents dates and time ranging from\r
19         /// 1-1-0001 12:00:00 AM to 31-12-9999 23:59:00 Common Era.\r
20         /// </summary>\r
21         /// \r
22         [Serializable]\r
23         public struct DateTime : IComparable, IFormattable, IConvertible\r
24         {\r
25                 private TimeSpan ticks;\r
26 \r
27                 private const int dp400 = 146097;\r
28                 private const int dp100 = 36524;\r
29                 private const int dp4 = 1461;\r
30 \r
31                 // w32 file time starts counting from 1/1/1601 00:00 GMT\r
32                 // which is the constant ticks from the .NET epoch\r
33                 private const long w32file_epoch = 504911232000000000L;\r
34 \r
35                 //\r
36                 // The UnixEpoch, it begins on Jan 1, 1970 at 0:0:0, expressed\r
37                 // in Ticks\r
38                 //\r
39                 internal const long UnixEpoch = 621355968000000000L;\r
40                 \r
41                 public static readonly DateTime MaxValue = new DateTime (false,TimeSpan.MaxValue);\r
42                 public static readonly DateTime MinValue = new DateTime (false,0);\r
43 \r
44                 private static string[] formats = {\r
45                         // For compatibility with MS's CLR, this format (which\r
46                         // doesn't have a one-letter equivalent) is parsed\r
47                         // too. It's important because it's used in XML\r
48                         // serialization.\r
49                         "yyyy-MM-ddTHH:mm:sszzz",\r
50                         // Full date and time\r
51                         "F", "G", "r", "s", "u", "U",\r
52                         // Full date and time, but no seconds\r
53                         "f", "g",\r
54                         // Only date\r
55                         "d", "D",\r
56                         // Only time\r
57                         "T", "t",\r
58                         // Only date, but no year\r
59                         "m",\r
60                         // Only date, but no day\r
61                         "y" \r
62                 };\r
63 \r
64                 private enum Which \r
65                 {\r
66                         Day,\r
67                         DayYear,\r
68                         Month,\r
69                         Year\r
70                 };\r
71         \r
72                 private static int[] daysmonth = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; \r
73                 private static int[] daysmonthleap = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };     \r
74 \r
75                 private static int AbsoluteDays (int year, int month, int day)\r
76                 {\r
77                         int[] days;\r
78                         int temp = 0, m=1 ;\r
79 \r
80 \r
81 \r
82                 \r
83                         days = (IsLeapYear(year) ? daysmonthleap  : daysmonth);\r
84                         \r
85                         while (m < month)\r
86                                 temp += days[m++];\r
87                         return ((day-1) + temp + (365* (year-1)) + ((year-1)/4) - ((year-1)/100) + ((year-1)/400));\r
88                 }\r
89 \r
90                 private int FromTicks(Which what)\r
91                 {\r
92                         int num400, num100, num4, numyears; \r
93                         int M =1;\r
94 \r
95                         int[] days = daysmonth;\r
96                         int totaldays = this.ticks.Days;\r
97 \r
98                         num400 = (totaldays / dp400);\r
99                         totaldays -=  num400 * dp400;\r
100                 \r
101                         num100 = (totaldays / dp100);\r
102                         if (num100 == 4)   // leap\r
103                                 num100 = 3;\r
104                         totaldays -= (num100 * dp100);\r
105 \r
106                         num4 = totaldays / dp4;\r
107                         totaldays -= (num4 * dp4);\r
108 \r
109                         numyears = totaldays / 365 ;\r
110 \r
111                         if (numyears == 4)  //leap\r
112                                 numyears =3 ;\r
113                         if (what == Which.Year )\r
114                                 return num400*400 + num100*100 + num4*4 + numyears + 1;\r
115 \r
116                         totaldays -= (numyears * 365) ;\r
117                         if (what == Which.DayYear )\r
118                                 return totaldays + 1;\r
119                         \r
120                         if  ((numyears==3) && ((num100 == 3) || !(num4 == 24)) ) //31 dec leapyear\r
121                                 days = daysmonthleap;\r
122                                 \r
123                         while (totaldays >= days[M])\r
124                                 totaldays -= days[M++];\r
125 \r
126                         if (what == Which.Month )\r
127                                 return M;\r
128 \r
129                         return totaldays +1; \r
130                 }\r
131 \r
132 \r
133                 // Constructors\r
134                 \r
135                 /// <summary>\r
136                 /// Constructs a DateTime for specified ticks\r
137                 /// </summary>\r
138                 /// \r
139                 public DateTime (long newticks)\r
140                         // `local' must default to false here to avoid\r
141                         // a recursion loop.\r
142                         : this (false, newticks) {}\r
143 \r
144                 internal DateTime (bool local, long newticks)\r
145                 {\r
146                         ticks = new TimeSpan (newticks);\r
147                         if (local) {\r
148                                 TimeZone tz = TimeZone.CurrentTimeZone;\r
149 \r
150                                 TimeSpan utcoffset = tz.GetUtcOffset (this);\r
151 \r
152                                 ticks = ticks + utcoffset;\r
153                         }\r
154                         if (ticks.Ticks < MinValue.Ticks || ticks.Ticks > MaxValue.Ticks)\r
155                             throw new ArgumentOutOfRangeException ();\r
156                 }\r
157 \r
158                 public DateTime (int year, int month, int day)\r
159                         : this (year, month, day,0,0,0,0) {}\r
160 \r
161                 public DateTime (int year, int month, int day, int hour, int minute, int second)\r
162                         : this (year, month, day, hour, minute, second, 0)      {}\r
163 \r
164                 public DateTime (int year, int month, int day, int hour, int minute, int second, int millisecond)\r
165                         {\r
166                         if ( year < 1 || year > 9999 || \r
167                                 month < 1 || month >12  ||\r
168                                 day < 1 || day > DaysInMonth(year, month) ||\r
169                                 hour < 0 || hour > 23 ||\r
170                                 minute < 0 || minute > 59 ||\r
171                                 second < 0 || second > 59 )\r
172                                 throw new ArgumentOutOfRangeException ("Parameters describe an " +\r
173                                                                         "unrepresentable DateTime.");\r
174 \r
175                         ticks = new TimeSpan (AbsoluteDays(year,month,day), hour, minute, second, millisecond);\r
176                 }\r
177 \r
178                 public DateTime (int year, int month, int day, Calendar calendar)\r
179                         : this (year, month, day, 0, 0, 0, 0, calendar) {}\r
180 \r
181                 \r
182                 public DateTime (int year, int month, int day, int hour, int minute, int second, Calendar calendar)\r
183                         : this (year, month, day, hour, minute, second, 0, calendar)    {}\r
184 \r
185 \r
186                 public DateTime (int year, int month, int day, int hour, int minute, int second, int millisecond, Calendar calendar)\r
187                         : this (year, month, day, hour, minute, second, millisecond) \r
188                 {\r
189                         if (calendar == null)\r
190                                 throw new ArgumentNullException();\r
191                 }\r
192 \r
193                 internal DateTime (bool check, TimeSpan value)\r
194                 {\r
195                         if (check && (value.Ticks < MinValue.Ticks || value.Ticks > MaxValue.Ticks))\r
196                             throw new ArgumentOutOfRangeException ();\r
197 \r
198                         ticks = value;\r
199                 }\r
200 \r
201                 /* Properties  */\r
202 \r
203                 public DateTime Date \r
204                 {\r
205                         get     \r
206                         { \r
207                                 return new DateTime (Year, Month, Day);\r
208                         }\r
209                 }\r
210         \r
211                 public int Month \r
212                 {\r
213                         get     \r
214                         { \r
215                                 return FromTicks(Which.Month); \r
216                         }\r
217                 }\r
218 \r
219                \r
220                 public int Day\r
221                 {\r
222                         get \r
223                         { \r
224                                 return FromTicks(Which.Day); \r
225                         }\r
226                 }\r
227 \r
228                 public DayOfWeek DayOfWeek \r
229                 {\r
230                         get \r
231                         { \r
232                                 return ( (DayOfWeek) ((ticks.Days+1) % 7) ); \r
233                         }\r
234                 }\r
235 \r
236                 public int DayOfYear \r
237                 {\r
238                         get \r
239                         { \r
240                                 return FromTicks(Which.DayYear); \r
241                         }\r
242                 }\r
243 \r
244                 public TimeSpan TimeOfDay \r
245                 {\r
246                         get     \r
247                         { \r
248                                 return new TimeSpan(ticks.Ticks % TimeSpan.TicksPerDay );\r
249                         }\r
250                         \r
251                 }\r
252 \r
253                 public int Hour \r
254                 {\r
255                         get \r
256                         { \r
257                                 return ticks.Hours;\r
258                         }\r
259                 }\r
260 \r
261                 public int Minute \r
262                 {\r
263                         get \r
264                         { \r
265                                 return ticks.Minutes;\r
266                         }\r
267                 }\r
268 \r
269                 public int Second \r
270                 {\r
271                         get     \r
272                         { \r
273                                 return ticks.Seconds;\r
274                         }\r
275                 }\r
276 \r
277                 public int Millisecond \r
278                 {\r
279                         get \r
280                         { \r
281                                 return ticks.Milliseconds;\r
282                         }\r
283                 }\r
284                 \r
285                 [MethodImplAttribute(MethodImplOptions.InternalCall)]\r
286                 internal static extern long GetNow ();\r
287 \r
288                 public static DateTime Now \r
289                 {\r
290                         get     \r
291                         {\r
292                                 return new DateTime (true, GetNow ());\r
293                         }\r
294                 }\r
295 \r
296                 public long Ticks\r
297                 { \r
298                         get     \r
299                         { \r
300                                 return ticks.Ticks;\r
301                         }\r
302                 }\r
303         \r
304                 public static DateTime Today \r
305                 {\r
306                         get {\r
307                                 DateTime now = Now;\r
308                                 return new DateTime (now.Year, now.Month, now.Day);\r
309                         }\r
310                 }\r
311 \r
312                 public static DateTime UtcNow \r
313                 {\r
314                         get {\r
315                                 return new DateTime (GetNow ());\r
316                         }\r
317                 }\r
318 \r
319                 public int Year \r
320                 {\r
321                         get \r
322                         { \r
323                                 return FromTicks(Which.Year); \r
324                         }\r
325                 }\r
326 \r
327                 /* methods */\r
328 \r
329                 public DateTime Add (TimeSpan ts)\r
330                 {\r
331                         return new DateTime (true, ticks) + ts;\r
332                 }\r
333 \r
334                 public DateTime AddDays (double days)\r
335                 {\r
336                         return AddMilliseconds (days * 86400000);\r
337                 }\r
338                 \r
339                 public DateTime AddTicks (long t)\r
340                 {\r
341                         return Add (new TimeSpan (t));\r
342                 }\r
343 \r
344                 public DateTime AddHours (double hours)\r
345                 {\r
346                         return AddMilliseconds (hours * 3600000);\r
347                 }\r
348 \r
349                 public DateTime AddMilliseconds (double ms)\r
350                 {\r
351                         long msticks;\r
352                         \r
353                         msticks = (long) (ms += ms > 0 ? 0.5 : -0.5) * TimeSpan.TicksPerMillisecond ; \r
354 \r
355                         return AddTicks (msticks);\r
356                 }\r
357 \r
358                 public DateTime AddMinutes (double minutes)\r
359                 {\r
360                         return AddMilliseconds (minutes * 60000);\r
361                 }\r
362                 \r
363                 public DateTime AddMonths (int months)\r
364                 {\r
365                         int day, month, year,  maxday ;\r
366                         DateTime temp ;\r
367 \r
368                         day = this.Day;\r
369                         month = this.Month + (months % 12);\r
370                         year = this.Year + months/12 ;\r
371                         \r
372                         if (month < 1)\r
373                         {\r
374                                 month = 12 + month ;\r
375                                 year -- ;\r
376                         }\r
377                         else if (month>12) \r
378                         {\r
379                                 month = month -12;\r
380                                 year ++;\r
381                         }\r
382                         maxday = DaysInMonth(year, month);\r
383                         if (day > maxday)\r
384                                 day = maxday;\r
385 \r
386                         temp = new DateTime (year, month, day);\r
387                         return  temp.Add (this.TimeOfDay);\r
388                 }\r
389 \r
390                 public DateTime AddSeconds (double seconds)\r
391                 {\r
392                         return AddMilliseconds (seconds*1000);\r
393                 }\r
394 \r
395                 public DateTime AddYears (int years )\r
396                 {\r
397                         return AddMonths(years * 12);\r
398                 }\r
399 \r
400                 public static int Compare (DateTime t1, DateTime t2)\r
401                 {\r
402                         if (t1.ticks < t2.ticks) \r
403                                 return -1;\r
404                         else if (t1.ticks > t2.ticks) \r
405                                 return 1;\r
406                         else\r
407                                 return 0;\r
408                 }\r
409 \r
410                 public int CompareTo (object v)\r
411                 {\r
412                         if ( v == null)\r
413                                 return 1;\r
414 \r
415                         if (!(v is System.DateTime))\r
416                                 throw new ArgumentException (Locale.GetText (\r
417                                         "Value is not a System.DateTime"));\r
418 \r
419                         return Compare (this, (DateTime) v);\r
420                 }\r
421 \r
422                 public static int DaysInMonth (int year, int month)\r
423                 {\r
424                         int[] days ;\r
425 \r
426                         if (month < 1 || month >12)\r
427                                 throw new ArgumentOutOfRangeException ();\r
428 \r
429                         days = (IsLeapYear(year) ? daysmonthleap  : daysmonth);\r
430                         return days[month];                     \r
431                 }\r
432                 \r
433                 public override bool Equals (object o)\r
434                 {\r
435                         if (!(o is System.DateTime))\r
436                                 return false;\r
437 \r
438                         return ((DateTime) o).ticks == ticks;\r
439                 }\r
440 \r
441                 public static bool Equals (DateTime t1, DateTime t2 )\r
442                 {\r
443                         return (t1.ticks == t2.ticks );\r
444                 }\r
445 \r
446                 public static DateTime FromFileTime (long fileTime) \r
447                 {\r
448                         return new DateTime (true, w32file_epoch + fileTime);\r
449                 }\r
450 \r
451                 public static DateTime FromOADate (double d)\r
452                 {\r
453                         // An OLE Automation date is implemented as a floating-point number\r
454                         // whose value is the number of days from midnight, 30 December 1899.\r
455 \r
456                         // d must be negative 657435.0 through positive 2958466.0.\r
457 \r
458                         if ((d < -657435.0) || (d > 2958466.0))\r
459                                 throw new OverflowException();\r
460 \r
461                         return (new DateTime(1899, 12, 30, 0, 0, 0)).AddDays(d);\r
462                 }\r
463 \r
464                 public string[] GetDateTimeFormats() \r
465                 {\r
466                         string[] result = new string[formats.Length];\r
467                         int index=0;\r
468                         foreach (string format in formats) {\r
469                                 result [index] = this.ToString(format);\r
470                                 index++;\r
471                         }\r
472                         return result;\r
473                 }\r
474 \r
475                 public string[] GetDateTimeFormats(char format)\r
476                 {\r
477                         string[] result = new string[1];\r
478                         result[0] = this.ToString(format.ToString());\r
479                         return result;\r
480                 }\r
481                 \r
482                 // TODO: implement me\r
483                 [MonoTODO]\r
484                 public string[] GetDateTimeFormats(IFormatProvider provider)\r
485                 {\r
486                         return null;\r
487                 }\r
488 \r
489                 //TODO: implement me \r
490                 [MonoTODO]\r
491                 public string[] GetDateTimeFormats(char format,IFormatProvider provider )\r
492                 {\r
493                         return null;\r
494                 }\r
495 \r
496                 public override int GetHashCode ()\r
497                 {\r
498                         return (int) ticks.Ticks;\r
499                 }\r
500 \r
501                 public TypeCode GetTypeCode ()\r
502                 {\r
503                         return TypeCode.DateTime;\r
504                 }\r
505 \r
506                 public static bool IsLeapYear (int year)\r
507                 {\r
508                         return  ( (year % 4 == 0 && year % 100 != 0) || year % 400 == 0) ;\r
509                 }\r
510 \r
511                 public static DateTime Parse (string s)\r
512                 {\r
513                         return Parse (s, null);\r
514                 }\r
515 \r
516                 public static DateTime Parse (string s, IFormatProvider fp)\r
517                 {\r
518                         return Parse (s, null, DateTimeStyles.AllowWhiteSpaces);\r
519                 }\r
520 \r
521                 public static DateTime Parse (string s, IFormatProvider fp, DateTimeStyles styles)\r
522                 {\r
523                         return ParseExact (s, formats, fp, styles);\r
524                 }\r
525 \r
526                 public static DateTime ParseExact (string s, string format, IFormatProvider fp)\r
527                 {\r
528                         return ParseExact (s, format, fp, DateTimeStyles.None);\r
529                 }\r
530 \r
531                 internal static int _ParseNumber (string s, int digits, bool leadingzero,\r
532                                                   bool sloppy_parsing, out int num_parsed)\r
533                 {\r
534                         int number = 0, i;\r
535 \r
536                         if (sloppy_parsing)\r
537                                 leadingzero = false;\r
538 \r
539                         if (!leadingzero) {\r
540                                 int real_digits = 0;\r
541                                 for (i = 0; i < s.Length && i < digits; i++) {\r
542                                         if (!Char.IsDigit (s[i]))\r
543                                                 break;\r
544 \r
545                                         real_digits++;\r
546                                 }\r
547 \r
548                                 digits = real_digits;\r
549                         }\r
550 \r
551                         if (s.Length < digits) {\r
552                                 num_parsed = -1;\r
553                                 return 0;\r
554                         }\r
555 \r
556                         for (i = 0; i < digits; i++) {\r
557                                 char c = s[i];\r
558                                 if (!Char.IsDigit (c)) {\r
559                                         num_parsed = -1;\r
560                                         return 0;\r
561                                 }\r
562 \r
563                                 number = number * 10 + (byte) (c - '0');\r
564                         }\r
565 \r
566                         num_parsed = digits;\r
567                         return number;\r
568                 }\r
569 \r
570                 internal static int _ParseEnum (string s, string[] values, out int num_parsed)\r
571                 {\r
572                         int i;\r
573 \r
574                         for (i = 0; i < values.Length; i++) {\r
575                                 if (s.Length < values[i].Length)\r
576                                         continue;\r
577                                 String tmp = s.Substring (0, values[i].Length);\r
578                                 if (String.Compare (tmp, values[i], true) == 0) {\r
579                                         num_parsed = values[i].Length;\r
580                                         return i;\r
581                                 }\r
582                         }\r
583 \r
584                         num_parsed = -1;\r
585                         return -1;\r
586                 }\r
587 \r
588                 internal static bool _ParseString (string s, int maxlength, string value, out int num_parsed)\r
589                 {\r
590                         if (maxlength > 0)\r
591                                 value = value.Substring (0, maxlength);\r
592 \r
593                         s = s.Substring (0, value.Length);\r
594 \r
595                         if (String.Compare (s, value, true) == 0) {\r
596                                 num_parsed = value.Length;\r
597                                 return true;\r
598                         }\r
599 \r
600                         num_parsed = -1;\r
601                         return false;\r
602                 }\r
603 \r
604                 internal static bool _DoParse (string s, string format, bool exact,\r
605                                                out DateTime result,\r
606                                                DateTimeFormatInfo dfi,\r
607                                                DateTimeStyles style)\r
608                 {\r
609                         bool useutc = false, use_localtime = true;\r
610                         bool sloppy_parsing = false;\r
611 \r
612                         if (format.Length == 1)\r
613                                 format = _GetStandardPattern (format[0], dfi, out useutc);\r
614 \r
615                         if ((style & DateTimeStyles.AllowLeadingWhite) != 0) {\r
616                                 format = format.TrimStart (null);\r
617 \r
618                                 s = s.TrimStart (null);\r
619                         }\r
620 \r
621                         if ((style & DateTimeStyles.AllowTrailingWhite) != 0) {\r
622                                 format = format.TrimEnd (null);\r
623                                 s = s.TrimEnd (null);\r
624                         }\r
625 \r
626                         if ((style & DateTimeStyles.AllowInnerWhite) != 0)\r
627                                 sloppy_parsing = true;\r
628 \r
629                         char[] chars = format.ToCharArray ();\r
630                         int len = format.Length, pos = 0, num = 0;\r
631 \r
632                         int day = -1, dayofweek = -1, month = -1, year = -1;\r
633                         int hour = -1, minute = -1, second = -1, millisecond = -1;\r
634                         int ampm = -1;\r
635                         int tzsign = -1, tzoffset = -1, tzoffmin = -1;\r
636 \r
637                         result = new DateTime (0);\r
638                         while (pos+num < len)\r
639                         {\r
640                                 if (s.Length == 0)\r
641                                         break;\r
642 \r
643                                 if (Char.IsWhiteSpace (s[0])) {\r
644                                         s = s.Substring (1);\r
645 \r
646                                         if (Char.IsWhiteSpace (chars[pos])) {\r
647                                                 pos++;\r
648                                                 continue;\r
649                                         }\r
650 \r
651                                         if ((style & DateTimeStyles.AllowInnerWhite) == 0)\r
652                                                 return false;\r
653                                 }\r
654 \r
655                                 if (chars[pos] == '\'') {\r
656                                         num = 1;\r
657                                         while (pos+num < len) {\r
658                                                 if (chars[pos+num] == '\'')\r
659                                                         break;\r
660 \r
661                                                 if (s.Length == 0)\r
662                                                         return false;\r
663                                                 if (s[0] != chars[pos+num])\r
664                                                         return false;\r
665                                                 s = s.Substring (1);\r
666 \r
667                                                 num++;\r
668                                         }\r
669                                         if (pos+num > len)\r
670                                                 return false;\r
671 \r
672                                         pos += num + 1;\r
673                                         num = 0;\r
674                                         continue;\r
675                                 } else if (chars[pos] == '\\') {\r
676                                         if (pos+1 >= len)\r
677                                                 return false;\r
678 \r
679                                         if (s[0] != chars[pos+num])\r
680                                                 return false;\r
681                                         s = s.Substring (1);\r
682                                         if (s.Length == 0)\r
683                                                 return false;\r
684 \r
685                                         pos++;\r
686                                         continue;\r
687                                 } else if (chars[pos] == '%') {\r
688                                         pos++;\r
689                                         continue;\r
690                                 }\r
691 \r
692                                 if ((pos+num+1 < len) && (chars[pos+num+1] == chars[pos+num])) {\r
693                                         num++;\r
694                                         continue;\r
695                                 }\r
696 \r
697                                 int num_parsed = 0;\r
698 \r
699                                 switch (chars[pos])\r
700                                 {\r
701                                 case 'd':\r
702                                         if (day != -1)\r
703                                                 return false;\r
704                                         if (num == 0)\r
705                                                 day = _ParseNumber (s, 2, false, sloppy_parsing, out num_parsed);\r
706                                         else if (num == 1)\r
707                                                 day = _ParseNumber (s, 2, true, sloppy_parsing, out num_parsed);\r
708                                         else if (num == 2)\r
709                                                 dayofweek = _ParseEnum (s, dfi.AbbreviatedDayNames, out num_parsed);\r
710                                         else\r
711                                         {\r
712                                                 dayofweek = _ParseEnum (s, dfi.DayNames, out num_parsed);\r
713                                                 num = 3;\r
714                                         }\r
715                                         break;\r
716                                 case 'M':\r
717                                         if (month != -1)\r
718                                                 return false;\r
719                                         if (num == 0)\r
720                                                 month = _ParseNumber (s, 2, false, sloppy_parsing, out num_parsed);\r
721                                         else if (num == 1)\r
722                                                 month = _ParseNumber (s, 2, true, sloppy_parsing, out num_parsed);\r
723                                         else if (num == 2)\r
724                                                 month = _ParseEnum (s, dfi.AbbreviatedMonthNames , out num_parsed) + 1;\r
725                                         else\r
726                                         {\r
727                                                 month = _ParseEnum (s, dfi.MonthNames, out num_parsed) + 1;\r
728                                                 num = 3;\r
729                                         }\r
730                                         break;\r
731                                 case 'y':\r
732                                         if (year != -1)\r
733                                                 return false;\r
734 \r
735                                         if (num == 0) {\r
736                                                 year = _ParseNumber (s, 2, false, sloppy_parsing, out num_parsed);\r
737                                                 year += (year < 30) ? 2000 : 1900;\r
738                                         } else if (num < 3) {\r
739                                                 year = _ParseNumber (s, 2, true, sloppy_parsing, out num_parsed);\r
740                                                 year += (year < 30) ? 2000 : 1900;\r
741                                         } else {\r
742                                                 year = _ParseNumber (s, 4, false, sloppy_parsing, out num_parsed);\r
743                                                 num = 3;\r
744                                         }\r
745                                         // if there is another digit next to the ones we just parsed, then the year value\r
746                                         // is too big for sure.\r
747                                         //if (num_parsed < s.Length && Char.IsDigit(s[num_parsed]) || (year != 0 && (year < 1 || year > 9999)))\r
748                                         if (year != 0 && (year < 1 || year > 9999))\r
749                                                 throw new ArgumentOutOfRangeException ("year", "Valid " + \r
750                                                                 "values are between 1 and 9999 inclusive");\r
751                                         break;\r
752                                 case 'h':\r
753                                         if (hour != -1)\r
754                                                 return false;\r
755                                         if (num == 0)\r
756                                                 hour = _ParseNumber (s, 2, false, sloppy_parsing, out num_parsed);\r
757                                         else\r
758                                         {\r
759                                                 hour = _ParseNumber (s, 2, true, sloppy_parsing, out num_parsed);\r
760                                                 num = 1;\r
761                                         }\r
762 \r
763                                         if (hour >= 12)\r
764                                                 return false;\r
765 \r
766                                         break;\r
767                                 case 'H':\r
768                                         if ((hour != -1) || (ampm >= 0))\r
769                                                 return false;\r
770                                         if (num == 0)\r
771                                                 hour = _ParseNumber (s, 2, false, sloppy_parsing, out num_parsed);\r
772                                         else\r
773                                         {\r
774                                                 hour = _ParseNumber (s, 2, true, sloppy_parsing, out num_parsed);\r
775                                                 num = 1;\r
776                                         }\r
777                                         if (hour >= 24)\r
778                                                 return false;\r
779 \r
780                                         ampm = -2;\r
781                                         break;\r
782                                 case 'm':\r
783                                         if (minute != -1)\r
784                                                 return false;\r
785                                         if (num == 0)\r
786                                                 minute = _ParseNumber (s, 2, false, sloppy_parsing, out num_parsed);\r
787                                         else\r
788                                         {\r
789                                                 minute = _ParseNumber (s, 2, true, sloppy_parsing, out num_parsed);\r
790                                                 num = 1;\r
791                                         }\r
792                                         if (minute >= 60)\r
793                                                 return false;\r
794 \r
795                                         break;\r
796                                 case 's':\r
797                                         if (second != -1)\r
798                                                 return false;\r
799                                         if (num == 0)\r
800                                                 second = _ParseNumber (s, 2, false, sloppy_parsing, out num_parsed);\r
801                                         else\r
802                                         {\r
803                                                 second = _ParseNumber (s, 2, true, sloppy_parsing, out num_parsed);\r
804                                                 num = 1;\r
805                                         }\r
806                                         if (second >= 60)\r
807                                                 return false;\r
808 \r
809                                         break;\r
810                                 case 'f':\r
811                                         if (millisecond != -1)\r
812                                                 return false;\r
813                                         num = Math.Min (num, 6);\r
814                                         millisecond = _ParseNumber (s, num+1, true, sloppy_parsing, out num_parsed);\r
815                                         if (millisecond >= 1000)\r
816                                                 return false;\r
817                                         break;\r
818                                 case 't':\r
819                                         if (ampm != -1)\r
820                                                 return false;\r
821                                         if (num == 0)\r
822                                         {\r
823                                                 if (_ParseString (s, 1, dfi.AMDesignator, out num_parsed))\r
824                                                         ampm = 0;\r
825                                                 else if (_ParseString (s, 1, dfi.PMDesignator, out num_parsed))\r
826                                                         ampm = 1;\r
827                                                 else\r
828                                                         return false;\r
829                                         }\r
830                                         else\r
831                                         {\r
832                                                 if (_ParseString (s, 0, dfi.AMDesignator, out num_parsed))\r
833                                                         ampm = 0;\r
834                                                 else if (_ParseString (s, 0, dfi.PMDesignator, out num_parsed))\r
835                                                         ampm = 1;\r
836                                                 else\r
837                                                         return false;\r
838                                                 num = 1;\r
839                                         }\r
840                                         break;\r
841                                 case 'z':\r
842                                         if (tzsign != -1)\r
843                                                 return false;\r
844                                         if (s[0] == '+')\r
845                                                 tzsign = 0;\r
846                                         else if (s[0] == '-')\r
847                                                 tzsign = 1;\r
848                                         else\r
849                                                 return false;\r
850                                         s = s.Substring (1);\r
851                                         if (num == 0)\r
852                                                 tzoffset = _ParseNumber (s, 2, false, sloppy_parsing, out num_parsed);\r
853                                         else if (num == 1)\r
854                                                 tzoffset = _ParseNumber (s, 2, true, sloppy_parsing, out num_parsed);\r
855                                         else\r
856                                         {\r
857                                                 tzoffset = _ParseNumber (s, 2, true, sloppy_parsing, out num_parsed);\r
858                                                 if (num_parsed < 0)\r
859                                                         return false;\r
860                                                 s = s.Substring (num_parsed);\r
861                                                 if (!_ParseString (s, 0, dfi.TimeSeparator, out num_parsed))\r
862                                                         return false;\r
863                                                 s = s.Substring (num_parsed);\r
864                                                 tzoffmin = _ParseNumber (s, 2, true, sloppy_parsing, out num_parsed);\r
865                                                 if (num_parsed < 0)\r
866                                                         return false;\r
867                                                 num = 2;\r
868                                         }\r
869                                         break;\r
870                                 case ':':\r
871                                         if (!_ParseString (s, 0, dfi.TimeSeparator, out num_parsed))\r
872                                                 return false;\r
873                                         break;\r
874                                 case '/':\r
875                                         if (!_ParseString (s, 0, dfi.DateSeparator, out num_parsed))\r
876                                                 return false;\r
877                                         break;\r
878                                 default:\r
879                                         if (s[0] != chars[pos])\r
880                                                 return false;\r
881                                         num = 0;\r
882                                         num_parsed = 1;\r
883                                         break;\r
884                                 }\r
885 \r
886                                 if (num_parsed < 0)\r
887                                         return false;\r
888 \r
889                                 s = s.Substring (num_parsed);\r
890 \r
891                                 pos = pos + num + 1;\r
892                                 num = 0;\r
893                         }\r
894 \r
895                         if (hour == -1)\r
896                                 hour = 0;\r
897                         if (minute == -1)\r
898                                 minute = 0;\r
899 \r
900                         if (second == -1)\r
901                                 second = 0;\r
902                         if (millisecond == -1)\r
903                                 millisecond = 0;\r
904 \r
905                         // If no date was given\r
906                         if ((day == -1) && (month == -1) && (year == -1)) {\r
907                                 if ((style & DateTimeStyles.NoCurrentDateDefault) != 0) {\r
908                                         day = 1;\r
909                                         month = 1;\r
910                                         year = 1;\r
911                                 } else {\r
912                                         day = Today.Day;\r
913                                         month = Today.Month;\r
914                                         year = Today.Year;\r
915                                 }\r
916                         }\r
917 \r
918                         if (day == -1)\r
919                                 day = 1;\r
920                         if (month == -1)\r
921                                 month = 1;\r
922                         if (year == -1) {\r
923                                 if ((style & DateTimeStyles.NoCurrentDateDefault) != 0)\r
924                                         year = 1;\r
925                                 else\r
926                                         year = Today.Year;\r
927                         }\r
928 \r
929                         if (ampm == 1)\r
930                                 hour = hour + 12;\r
931 \r
932                         result = new DateTime (year, month, day, hour, minute, second, millisecond);\r
933 \r
934                         if ((dayofweek != -1) && (dayofweek != (int) result.DayOfWeek))\r
935                                 throw new FormatException (Locale.GetText ("String was not recognized as valid DateTime because the day of week was incorrect."));\r
936 \r
937                         // If no timezone was specified, default to the local timezone.\r
938                         TimeSpan utcoffset;\r
939 \r
940                         if (useutc)\r
941                                 utcoffset = new TimeSpan (0, 0, 0);\r
942                         else if (tzsign == -1) {\r
943                                 TimeZone tz = TimeZone.CurrentTimeZone;\r
944                                 utcoffset = tz.GetUtcOffset (result);\r
945                         } else {\r
946                                 if ((style & DateTimeStyles.AdjustToUniversal) != 0)\r
947                                         use_localtime = false;\r
948 \r
949                                 if (tzoffmin == -1)\r
950                                         tzoffmin = 0;\r
951                                 if (tzoffset == -1)\r
952                                         tzoffset = 0;\r
953                                 if (tzsign == 1)\r
954                                         tzoffset = -tzoffset;\r
955 \r
956                                 utcoffset = new TimeSpan (tzoffset, tzoffmin, 0);\r
957                         }\r
958 \r
959                         long newticks = (result.ticks - utcoffset).Ticks;\r
960 \r
961                         result = new DateTime (newticks);\r
962 \r
963                         return true;\r
964                 }\r
965 \r
966 \r
967                 public static DateTime ParseExact (string s, string format,\r
968                                                    IFormatProvider fp, DateTimeStyles style)\r
969                 {\r
970                         string[] formats;\r
971 \r
972                         formats = new string [1];\r
973                         formats[0] = format;\r
974 \r
975                         return ParseExact (s, formats, fp, style);\r
976                 }\r
977 \r
978                 public static DateTime ParseExact (string s, string[] formats,\r
979                                                    IFormatProvider fp,\r
980                                                    DateTimeStyles style)\r
981                 {\r
982                         DateTimeFormatInfo dfi = DateTimeFormatInfo.GetInstance (fp);\r
983 \r
984                         if (s == null)\r
985                                 throw new ArgumentNullException (Locale.GetText ("s is null"));\r
986                         if (formats.Length == 0)\r
987                                 throw new ArgumentNullException (Locale.GetText ("format is null"));\r
988 \r
989                         int i;\r
990                         for (i = 0; i < formats.Length; i++)\r
991                         {\r
992                                 DateTime result;\r
993 \r
994                                 if (_DoParse (s, formats[i], true, out result, dfi, style))\r
995                                         return result;\r
996                         }\r
997 \r
998                         throw new FormatException ();\r
999                 }\r
1000                 \r
1001                 public TimeSpan Subtract(DateTime dt)\r
1002                 {   \r
1003                         return new TimeSpan(ticks.Ticks) - dt.ticks;\r
1004                 }\r
1005 \r
1006                 public DateTime Subtract(TimeSpan ts)\r
1007                 {\r
1008                         TimeSpan newticks;\r
1009 \r
1010                         newticks = (new TimeSpan (ticks.Ticks)) - ts;\r
1011                         return new DateTime(true,newticks);\r
1012                 }\r
1013 \r
1014                 public long ToFileTime()\r
1015                 {\r
1016                         DateTime universalTime = ToUniversalTime();\r
1017                         \r
1018                         if (universalTime.Ticks < w32file_epoch) {\r
1019                                 throw new ArgumentOutOfRangeException("file time is not valid");\r
1020                         }\r
1021                         \r
1022                         return(universalTime.Ticks - w32file_epoch);\r
1023                 }\r
1024 \r
1025                 public string ToLongDateString()\r
1026                 {\r
1027                         return ToString ("D");\r
1028                 }\r
1029 \r
1030                 public string ToLongTimeString()\r
1031                 {\r
1032                         return ToString ("T");\r
1033                 }\r
1034 \r
1035                 public double ToOADate()\r
1036                 {\r
1037                         DateTime p = new DateTime(1899, 12, 30, 0, 0, 0);\r
1038                         TimeSpan t = new TimeSpan (this.Ticks - p.Ticks);\r
1039                         return t.TotalDays;\r
1040                 }\r
1041 \r
1042                 public string ToShortDateString()\r
1043                 {\r
1044                         return ToString ("d");\r
1045                 }\r
1046 \r
1047                 public string ToShortTimeString()\r
1048                 {\r
1049                         return ToString ("t");\r
1050                 }\r
1051                 \r
1052                 public override string ToString ()\r
1053                 {\r
1054                         return ToString ("G", null);\r
1055                 }\r
1056 \r
1057                 public string ToString (IFormatProvider fp)\r
1058                 {\r
1059                         return ToString (null, fp);\r
1060                 }\r
1061 \r
1062                 public string ToString (string format)\r
1063                 {\r
1064                         return ToString (format, null);\r
1065                 }\r
1066 \r
1067                 internal static string _GetStandardPattern (char format, DateTimeFormatInfo dfi, out bool useutc)\r
1068                 {\r
1069                         String pattern;\r
1070 \r
1071                         useutc = false;\r
1072 \r
1073                         switch (format)\r
1074                         {\r
1075                         case 'd':\r
1076                                 pattern = dfi.ShortDatePattern;\r
1077                                 break;\r
1078                         case 'D':\r
1079                                 pattern = dfi.LongDatePattern;\r
1080                                 break;\r
1081                         case 'f':\r
1082                                 pattern = dfi.LongDatePattern + " " + dfi.ShortTimePattern;\r
1083                                 break;\r
1084                         case 'F':\r
1085                                 pattern = dfi.FullDateTimePattern;\r
1086                                 break;\r
1087                         case 'g':\r
1088                                 pattern = dfi.ShortDatePattern + " " + dfi.ShortTimePattern;\r
1089                                 break;\r
1090                         case 'G':\r
1091                                 pattern = dfi.ShortDatePattern + " " + dfi.LongTimePattern;\r
1092                                 break;\r
1093                         case 'm':\r
1094                         case 'M':\r
1095                                 pattern = dfi.MonthDayPattern;\r
1096                                 break;\r
1097                         case 'r':\r
1098                         case 'R':\r
1099                                 pattern = dfi.RFC1123Pattern;\r
1100                                 // commented by LP 09/jun/2002, rfc 1123 pattern is always in GMT\r
1101                                 // useutc= true;\r
1102                                 break;\r
1103                         case 's':\r
1104                                 pattern = dfi.SortableDateTimePattern;\r
1105                                 break;\r
1106                         case 't':\r
1107                                 pattern = dfi.ShortTimePattern;\r
1108                                 break;\r
1109                         case 'T':\r
1110                                 pattern = dfi.LongTimePattern;\r
1111                                 break;\r
1112                         case 'u':\r
1113                                 pattern = dfi.UniversalSortableDateTimePattern;\r
1114                                 useutc = true;\r
1115                                 break;\r
1116                         case 'U':\r
1117                                 pattern = dfi.LongDatePattern + " " + dfi.LongTimePattern;\r
1118                                 useutc = true;\r
1119                                 break;\r
1120                         case 'y':\r
1121                         case 'Y':\r
1122                                 pattern = dfi.YearMonthPattern;\r
1123                                 break;\r
1124                         default:\r
1125                                 pattern = null;\r
1126                                 break;\r
1127                         }\r
1128 \r
1129                         return pattern;\r
1130                 }\r
1131 \r
1132                 internal string _ToString (string format, DateTimeFormatInfo dfi)\r
1133                 {\r
1134                         String str = null, result = null;\r
1135                         char[] chars = format.ToCharArray ();\r
1136                         int len = format.Length, pos = 0, num = 0;\r
1137 \r
1138                         TimeZone tz = TimeZone.CurrentTimeZone;\r
1139                         TimeSpan utcoffset = tz.GetUtcOffset (this);\r
1140 \r
1141                         while (pos < len)\r
1142                         {\r
1143                                 if (chars[pos] == '\'') {\r
1144                                         num = 1;\r
1145                                         while (pos+num <= len) {\r
1146                                                 if (chars[pos+num] == '\'')\r
1147                                                         break;\r
1148 \r
1149                                                 result += chars[pos+num];\r
1150                                                 num++;\r
1151                                         }\r
1152                                         if (pos+num > len)\r
1153                                                 throw new FormatException (Locale.GetText ("The specified format is invalid"));\r
1154 \r
1155                                         pos += num+1;\r
1156                                         num = 0;\r
1157                                         continue;\r
1158                                 } else if (chars[pos] == '\\') {\r
1159                                         if (pos+1 >= len)\r
1160                                                 throw new FormatException (Locale.GetText ("The specified format is invalid"));\r
1161 \r
1162                                         result += chars[pos+1];\r
1163                                         pos += 2;\r
1164                                         continue;\r
1165                                 } else if (chars[pos] == '%') {\r
1166                                         pos++;\r
1167                                         continue;\r
1168                                 }\r
1169 \r
1170                                 if ((pos+num+1 < len) && (chars[pos+num+1] == chars[pos+num])) {\r
1171                                         num++;\r
1172                                         continue;\r
1173                                 }\r
1174 \r
1175                                 switch (chars[pos])\r
1176                                 {\r
1177                                 case 'd':\r
1178                                         if (num == 0)\r
1179                                                 str = Day.ToString ("d");\r
1180                                         else if (num == 1)\r
1181                                                 str = Day.ToString ("d02");\r
1182                                         else if (num == 2)\r
1183                                                 str = dfi.GetAbbreviatedDayName (DayOfWeek);\r
1184                                         else {\r
1185                                                 str = dfi.GetDayName (DayOfWeek);\r
1186                                                 num = 3;\r
1187                                         }\r
1188                                         break;\r
1189                                 case 'M':\r
1190                                         if (num == 0)\r
1191                                                 str = Month.ToString ("d");\r
1192                                         else if (num == 1)\r
1193                                                 str = Month.ToString ("d02");\r
1194                                         else if (num == 2)\r
1195                                                 str = dfi.GetAbbreviatedMonthName (Month);\r
1196                                         else {\r
1197                                                 str = dfi.GetMonthName (Month);\r
1198                                                 num = 3;\r
1199                                         }\r
1200                                         break;\r
1201                                 case 'y':\r
1202                                         if (num == 0) {\r
1203                                                 int shortyear = Year % 100;\r
1204                                                 str = shortyear.ToString ("d");\r
1205                                         } else if (num == 1) {\r
1206                                                 int shortyear = Year % 100;\r
1207                                                 str = shortyear.ToString ("d02");\r
1208                                         } else {\r
1209                                                 str = Year.ToString ("d04");\r
1210                                                 num = 3;\r
1211                                         }\r
1212                                         break;\r
1213                                 case 'g':\r
1214                                         // FIXME\r
1215                                         break;\r
1216                                 case 'f':\r
1217                                         num = Math.Min (num, 6);\r
1218 \r
1219                                         long relativeTicks = ticks.Ticks % TimeSpan.TicksPerSecond;
1220 \r
1221                                         long exp = 10;\r
1222                                         for (int i = 0; i < num; i++)\r
1223                                                 exp = exp * 10;\r
1224 \r
1225                                         long frac = relativeTicks * exp / TimeSpan.TicksPerSecond;\r
1226 \r
1227                                         String prec = (num+1).ToString ("d02");\r
1228                                         str = frac.ToString (String.Concat ("d", prec));\r
1229 \r
1230                                         break;\r
1231                                 case 'h':\r
1232 \r
1233                                         if (num == 0) {\r
1234                                                 int shorthour = Hour % 12;\r
1235                                                 str = shorthour.ToString ("d");\r
1236                                         } else {\r
1237                                                 int shorthour = Hour % 12;\r
1238                                                 str = shorthour.ToString ("d02");\r
1239                                                 num = 1;\r
1240                                         }\r
1241                                         break;\r
1242                                 case 'H':\r
1243                                         if (num == 0)\r
1244                                                 str = Hour.ToString ("d");\r
1245                                         else {\r
1246                                                 str = Hour.ToString ("d02");\r
1247                                                 num = 1;\r
1248                                         }\r
1249                                         break;\r
1250                                 case 'm':\r
1251                                         if (num == 0)\r
1252                                                 str = Minute.ToString ("d");\r
1253                                         else {\r
1254                                                 str = Minute.ToString ("d02");\r
1255                                                 num = 1;\r
1256                                         }\r
1257                                         break;\r
1258                                 case 's':\r
1259                                         if (num == 0)\r
1260                                                 str = Second.ToString ("d");\r
1261                                         else {\r
1262                                                 str = Second.ToString ("d02");\r
1263                                                 num = 1;\r
1264                                         }\r
1265                                         break;\r
1266                                 case 't':\r
1267                                         if (Hour < 12)\r
1268                                                 str = dfi.AMDesignator;\r
1269                                         else\r
1270                                                 str = dfi.PMDesignator;\r
1271 \r
1272                                         if (num == 0)\r
1273                                                 str = str.Substring (0,1);\r
1274                                         else\r
1275                                                 num = 1;\r
1276                                         break;\r
1277                                 case 'z':\r
1278                                         if (num == 0) {\r
1279                                                 int offset = utcoffset.Hours;\r
1280                                                 str = offset.ToString ("d");\r
1281                                                 str = String.Concat ((offset >= 0) ? "+" : "", str);\r
1282                                         } \r
1283                                         else if (num == 1) \r
1284                                         {\r
1285                                                 int offset = utcoffset.Hours;\r
1286                                                 str = offset.ToString ("d02");\r
1287                                                 str = String.Concat ((offset >= 0) ? "+" : "", str);\r
1288                                         } \r
1289                                         else if (num == 2) \r
1290                                         {\r
1291                                                 int offhour = utcoffset.Hours;\r
1292                                                 int offminute = utcoffset.Minutes;\r
1293                                                 str = offhour.ToString ("d02");\r
1294                                                 str = String.Concat (str, dfi.TimeSeparator);\r
1295                                                 str = String.Concat (str, offminute.ToString ("d02"));\r
1296                                                 str = String.Concat ((offhour >= 0) ? "+" : "", str);\r
1297                                                 num = 2;\r
1298                                         }\r
1299                                         break;\r
1300                                 case ':':\r
1301                                         str = dfi.TimeSeparator;\r
1302                                         num = 0;\r
1303                                         break;\r
1304                                 case '/':\r
1305                                         str = dfi.DateSeparator;\r
1306                                         num = 0;\r
1307                                         break;\r
1308                                 default:\r
1309                                         str = String.Concat (chars [pos]);\r
1310                                         num = 0;\r
1311                                         break;\r
1312                                 }\r
1313 \r
1314                                 result = String.Concat (result, str);\r
1315                                                 \r
1316                                 pos += num + 1;\r
1317                                 num = 0;\r
1318                         }\r
1319 \r
1320                         return result;\r
1321                 }\r
1322 \r
1323                 public string ToString (string format, IFormatProvider fp)\r
1324 \r
1325                 {\r
1326                         DateTimeFormatInfo dfi = DateTimeFormatInfo.GetInstance(fp);\r
1327 \r
1328                         if (format == null)\r
1329                                 format = dfi.FullDateTimePattern;\r
1330 \r
1331                         bool useutc = false;\r
1332 \r
1333                         if (format.Length == 1) {\r
1334                                 char fchar = (format.ToCharArray ())[0];\r
1335                                 format = _GetStandardPattern (fchar, dfi, out useutc);\r
1336                         }\r
1337 \r
1338                         if (useutc)\r
1339                                 return this.ToUniversalTime ()._ToString (format, dfi);\r
1340                         else\r
1341                                 return this._ToString (format, dfi);\r
1342                 }\r
1343 \r
1344                 public DateTime ToLocalTime()\r
1345                 {\r
1346                         TimeZone tz = TimeZone.CurrentTimeZone;\r
1347 \r
1348                         TimeSpan offset = tz.GetUtcOffset (this);\r
1349 \r
1350                         return new DateTime (true, ticks + offset);\r
1351                 }\r
1352 \r
1353                 public DateTime ToUniversalTime()\r
1354                 {\r
1355                         TimeZone tz = TimeZone.CurrentTimeZone;\r
1356 \r
1357                         TimeSpan offset = tz.GetUtcOffset (this);\r
1358 \r
1359                         return new DateTime (false, ticks - offset);\r
1360                 }\r
1361 \r
1362                 /*  OPERATORS */\r
1363 \r
1364                 public static DateTime operator +(DateTime d, TimeSpan t)\r
1365                 {\r
1366                         return new DateTime (true, d.ticks + t);\r
1367                 }\r
1368 \r
1369                 public static bool operator ==(DateTime d1, DateTime d2)\r
1370                 {\r
1371                         return (d1.ticks == d2.ticks);\r
1372                 }\r
1373 \r
1374                 public static bool operator >(DateTime t1,DateTime t2)\r
1375                 {\r
1376                         return (t1.ticks > t2.ticks);\r
1377                 }\r
1378 \r
1379                 public static bool operator >=(DateTime t1,DateTime t2)\r
1380                 {\r
1381                         return (t1.ticks >= t2.ticks);\r
1382                 }\r
1383 \r
1384                 public static bool operator !=(DateTime d1, DateTime d2)\r
1385                 {\r
1386                         return (d1.ticks != d2.ticks);\r
1387                 }\r
1388 \r
1389                 public static bool operator <(DateTime t1,      DateTime t2)\r
1390                 {\r
1391                         return (t1.ticks < t2.ticks );\r
1392                 }\r
1393 \r
1394                 public static bool operator <=(DateTime t1,DateTime t2)\r
1395                 {\r
1396                         return (t1.ticks <= t2.ticks);\r
1397                 }\r
1398 \r
1399                 public static TimeSpan operator -(DateTime d1,DateTime d2)\r
1400                 {\r
1401                         return new TimeSpan((d1.ticks - d2.ticks).Ticks);\r
1402                 }\r
1403 \r
1404                 public static DateTime operator -(DateTime d,TimeSpan t)\r
1405                 {\r
1406                         return new DateTime (true, d.ticks - t);\r
1407                 }\r
1408 \r
1409                 bool IConvertible.ToBoolean(IFormatProvider provider)\r
1410                 {\r
1411                         throw new InvalidCastException();\r
1412                 }\r
1413                 \r
1414                 byte IConvertible.ToByte(IFormatProvider provider)\r
1415                 {\r
1416                         throw new InvalidCastException();\r
1417 \r
1418                 }\r
1419 \r
1420                 char IConvertible.ToChar(IFormatProvider provider)\r
1421                 {\r
1422                         throw new InvalidCastException();\r
1423                 }\r
1424 \r
1425                 // TODO Implement me\r
1426                 [MonoTODO]\r
1427                 public System.DateTime ToDateTime(IFormatProvider provider)\r
1428                 {\r
1429                         return new System.DateTime(true,this.ticks);\r
1430                 } \r
1431                 \r
1432                 decimal IConvertible.ToDecimal(IFormatProvider provider)\r
1433                 {\r
1434                          throw new InvalidCastException();\r
1435                 }\r
1436 \r
1437                 double IConvertible.ToDouble(IFormatProvider provider)\r
1438                 {\r
1439                         throw new InvalidCastException();\r
1440                 }\r
1441 \r
1442                 Int16 IConvertible.ToInt16(IFormatProvider provider)\r
1443                 {\r
1444                         throw new InvalidCastException();\r
1445                 }\r
1446 \r
1447                 Int32 IConvertible.ToInt32(IFormatProvider provider)\r
1448                 {\r
1449                         throw new InvalidCastException();\r
1450                 }\r
1451 \r
1452                 Int64 IConvertible.ToInt64(IFormatProvider provider)\r
1453                 {\r
1454                         throw new InvalidCastException();\r
1455                 }\r
1456 \r
1457                 [CLSCompliant(false)]\r
1458                 SByte IConvertible.ToSByte(IFormatProvider provider)\r
1459                 {\r
1460                         throw new InvalidCastException();\r
1461                 }\r
1462 \r
1463                 Single IConvertible.ToSingle(IFormatProvider provider)\r
1464                 {\r
1465                         throw new InvalidCastException();\r
1466                 }\r
1467 \r
1468                 object IConvertible.ToType(Type conversionType,IFormatProvider provider)\r
1469                 {\r
1470                         throw new InvalidCastException();\r
1471                 }\r
1472 \r
1473                 UInt16 IConvertible.ToUInt16(IFormatProvider provider)\r
1474                 {\r
1475                         throw new InvalidCastException();\r
1476                 }\r
1477                 \r
1478                 [CLSCompliant(false)]\r
1479                 UInt32 IConvertible.ToUInt32(IFormatProvider provider)\r
1480                 {\r
1481                         throw new InvalidCastException();\r
1482                 }\r
1483 \r
1484                 [CLSCompliant(false)]\r
1485                 UInt64 IConvertible.ToUInt64(IFormatProvider provider)\r
1486 \r
1487                 {\r
1488                         throw new InvalidCastException();\r
1489                 }\r
1490         }\r
1491 }\r
1492 \r
1493 namespace System\r
1494 {\r
1495         public enum DayOfWeek\r
1496         {\r
1497                 Sunday,\r
1498                 Monday,\r
1499                 Tuesday,\r
1500                 Wednesday,\r
1501                 Thursday,\r
1502                 Friday,\r
1503                 Saturday\r
1504         }\r
1505 }\r