Bug fixes and more implementation from Martin Baulig
[mono.git] / mcs / class / corlib / System / DateTime.cs
1 //
2 // System.DateTime.cs
3 //
4 // author:
5 //   Marcel Narings (marcel@narings.nl)
6 //
7 //   (C) 2001 Marcel Narings
8
9 using System;
10 using System.Globalization;
11 using System.Runtime.CompilerServices;
12
13
14 namespace System
15 {
16         /// <summary>
17         /// The DateTime structure represents dates and time ranging from
18         /// 1-1-0001 12:00:00 AM to 31-12-9999 23:59:00 Common Era.
19         /// </summary>
20         /// 
21         public struct DateTime : IComparable , IFormattable  , IConvertible
22         {
23                 private TimeSpan ticks;
24                 private TimeSpan utcoffset;
25
26                 private const int dp400 = 146097;
27                 private const int dp100 = 36524;
28                 private const int dp4 = 1461;
29
30                 // w32 file time starts counting from 1/1/1601 00:00 GMT
31                 // which is the constant ticks from the .NET epoch
32                 private const long w32file_epoch = 504911232000000000L;
33
34                 //
35                 // The UnixEpoch, it begins on Jan 1, 1970 at 0:0:0, expressed
36                 // in Ticks
37                 //
38                 internal const long UnixEpoch = 621355968000000000L;
39                 
40                 public static readonly DateTime MaxValue = new DateTime (false,TimeSpan.MaxValue);
41                 public static readonly DateTime MinValue = new DateTime (false,TimeSpan.MinValue);
42                 
43                 private enum Which 
44                 {
45                         Day,
46                         DayYear,
47                         Month,
48                         Year
49                 };
50         
51                 private static int[] daysmonth = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 
52                 private static int[] daysmonthleap = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };     
53
54                 private static int AbsoluteDays (int year, int month, int day)
55                 {
56                         int[] days;
57                         int temp = 0, m=1 ;
58                 
59                         days = (IsLeapYear(year) ? daysmonthleap  : daysmonth);
60                         
61                         while (m < month)
62                                 temp += days[m++];
63                         return ((day-1) + temp + (365* (year-1)) + ((year-1)/4) - ((year-1)/100) + ((year-1)/400));
64                 }
65
66                 private int FromTicks(Which what)
67                 {
68                         int num400, num100, num4, numyears; 
69                         int M =1;
70
71                         int[] days = daysmonth;
72                         int totaldays = this.ticks.Days;
73
74                         num400 = (totaldays / dp400);
75                         totaldays -=  num400 * dp400;
76                 
77                         num100 = (totaldays / dp100);
78                         if (num100 == 4)   // leap
79                                 num100 = 3;
80                         totaldays -= (num100 * dp100);
81
82                         num4 = totaldays / dp4;
83                         totaldays -= (num4 * dp4);
84
85                         numyears = totaldays / 365 ;
86
87                         if (numyears == 4)  //leap
88                                 numyears =3 ;
89                         if (what == Which.Year )
90                                 return num400*400 + num100*100 + num4*4 + numyears + 1;
91
92                         totaldays -= (numyears * 365) ;
93                         if (what == Which.DayYear )
94                                 return totaldays + 1;
95                         
96                         if  ((numyears==3) && ((num100 == 3) || !(num4 == 24)) ) //31 dec leapyear
97                                 days = daysmonthleap;
98                                 
99                         while (totaldays >= days[M])
100                                 totaldays -= days[M++];
101
102                         if (what == Which.Month )
103                                 return M;
104
105                         return totaldays +1; 
106                 }
107
108
109                 // Constructors
110                 
111                 /// <summary>
112                 /// Constructs a DateTime for specified ticks
113                 /// </summary>
114                 /// 
115                 public DateTime (long newticks)
116                         // `local' must default to false here to avoid
117                         // a recursion loop.
118                         : this (false, newticks) {}
119
120                 internal DateTime (bool local, long newticks)
121                         : this (true, new TimeSpan (newticks))
122                 {
123                         if (local) {
124                                 TimeZone tz = TimeZone.CurrentTimeZone;
125
126                                 utcoffset = tz.GetUtcOffset (this);
127
128                                 ticks = ticks + utcoffset;
129                         }
130                 }
131
132                 public DateTime (int year, int month, int day)
133                         : this (year, month, day,0,0,0,0) {}
134
135                 public DateTime (int year, int month, int day, int hour, int minute, int second)
136                         : this (year, month, day, hour, minute, second, 0)      {}
137
138                 public DateTime (int year, int month, int day, int hour, int minute, int second, int millisecond)
139                 {
140                         if ( year < 1 || year > 9999 || 
141                                 month < 1 || month >12  ||
142                                 day < 1 || day > DaysInMonth(year, month) ||
143                                 hour < 0 || hour > 23 ||
144                                 minute < 0 || minute > 59 ||
145                                 second < 0 || second > 59 )
146                                 throw new ArgumentOutOfRangeException() ;
147
148                         ticks = new TimeSpan (AbsoluteDays(year,month,day), hour, minute, second, millisecond);
149                         utcoffset = new TimeSpan (0);
150                 }
151
152                 public DateTime (int year, int month, int day, Calendar calendar)
153                         : this (year, month, day, 0, 0, 0, 0, calendar) {}
154
155                 
156                 public DateTime (int year, int month, int day, int hour, int minute, int second, Calendar calendar)
157                         : this (year, month, day, hour, minute, second, 0, calendar)    {}
158
159
160                 public DateTime (int year, int month, int day, int hour, int minute, int second, int millisecond, Calendar calendar)
161                         : this(year, month, day, hour, minute, second, millisecond) 
162                 {
163                         if ( calendar == null)
164                                 throw new ArgumentNullException();
165                 }
166
167                 internal DateTime (bool check, TimeSpan value)
168                 {
169                         if (check && (value.Ticks < MinValue.Ticks || value.Ticks > MaxValue.Ticks))
170                                 throw new ArgumentOutOfRangeException ();
171
172                         ticks = value;
173
174                         utcoffset = new TimeSpan (0);
175                 }
176
177                 /* Properties  */
178                  
179                 public DateTime Date 
180                 {
181                         get     
182                         { 
183                                 return new DateTime (Year, Month, Day);
184                         }
185                 }
186         
187                 public int Month 
188                 {
189                         get     
190                         { 
191                                 return FromTicks(Which.Month); 
192                         }
193                 }
194
195                
196                 public int Day
197                 {
198                         get 
199                         { 
200                                 return FromTicks(Which.Day); 
201                         }
202                 }
203
204                 public DayOfWeek DayOfWeek 
205                 {
206                         get 
207                         { 
208                                 return ( (DayOfWeek) ((ticks.Days+1) % 7) ); 
209                         }
210                 }
211
212                 public int DayOfYear 
213                 {
214                         get 
215                         { 
216                                 return FromTicks(Which.DayYear); 
217                         }
218                 }
219
220                 public TimeSpan TimeOfDay 
221                 {
222                         get     
223                         { 
224                                 return new TimeSpan(ticks.Ticks % TimeSpan.TicksPerDay );
225                         }
226                         
227                 }
228
229                 public int Hour 
230                 {
231                         get 
232                         { 
233                                 return ticks.Hours;
234                         }
235                 }
236
237                 public int Minute 
238                 {
239                         get 
240                         { 
241                                 return ticks.Minutes;
242                         }
243                 }
244
245                 public int Second 
246                 {
247                         get     
248                         { 
249                                 return ticks.Seconds;
250                         }
251                 }
252
253                 public int Millisecond 
254                 {
255                         get 
256                         { 
257                                 return ticks.Milliseconds;
258                         }
259                 }
260                 
261                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
262                 private static extern long GetNow ();
263
264                 public static DateTime Now 
265                 {
266                         get     
267                         {
268                                 return new DateTime (true, GetNow ());
269                         }
270                 }
271
272                 public long Ticks
273                 { 
274                         get     
275                         { 
276                                 return ticks.Ticks;
277                         }
278                 }
279         
280                 public static DateTime Today 
281                 {
282                         get     
283                         {
284                                 return new DateTime (true, (GetNow () / TimeSpan.TicksPerDay) * TimeSpan.TicksPerDay);
285                         }
286                 }
287
288                 public static DateTime UtcNow 
289                 {
290                         get {
291                                 return new DateTime (GetNow ());
292                         }
293                 }
294
295                 public int Year 
296                 {
297                         get 
298                         { 
299                                 return FromTicks(Which.Year); 
300                         }
301                 }
302
303                 /* methods */
304
305                 public DateTime Add (TimeSpan ts)
306                 {
307                         return new DateTime (true, ticks) + ts;
308                 }
309
310                 public DateTime AddDays (double days)
311                 {
312                         return AddMilliseconds (days * 86400000);
313                 }
314                 
315                 public DateTime AddTicks (long t)
316                 {
317                         return Add (new TimeSpan (t));
318                 }
319
320                 public DateTime AddHours (double hours)
321                 {
322                         return AddMilliseconds (hours * 3600000);
323                 }
324
325                 public DateTime AddMilliseconds (double ms)
326                 {
327                         long msticks;
328                         
329                         msticks = (long) (ms += ms > 0 ? 0.5 : -0.5) * TimeSpan.TicksPerMillisecond ; 
330
331                         return AddTicks (msticks);
332                 }
333
334                 public DateTime AddMinutes (double minutes)
335                 {
336                         return AddMilliseconds (minutes * 60000);
337                 }
338                 
339                 public DateTime AddMonths (int months)
340                 {
341                         int day, month, year,  maxday ;
342                         DateTime temp ;
343
344                         day = this.Day;
345                         month = this.Month + (months % 12);
346                         year = this.Year + months/12 ;
347                         
348                         if (month < 1)
349                         {
350                                 month = 12 + month ;
351                                 year -- ;
352                         }
353                         else if (month>12) 
354                         {
355                                 month = month -12;
356                                 year ++;
357                         }
358                         maxday = DaysInMonth(year, month);
359                         if (day > maxday)
360                                 day = maxday;
361
362                         temp = new DateTime (year, month, day);
363                         return  temp.Add (this.TimeOfDay);
364                 }
365
366                 public DateTime AddSeconds (double seconds)
367                 {
368                         return AddMilliseconds (seconds*1000);
369                 }
370
371                 public DateTime AddYears (int years )
372                 {
373                         return AddMonths(years * 12);
374                 }
375
376                 public static int Compare (DateTime t1, DateTime t2)
377                 {
378                         if (t1.ticks < t2.ticks) 
379                                 return -1;
380                         else if (t1.ticks > t2.ticks) 
381                                 return 1;
382                         else
383                                 return 0;
384                 }
385
386                 public int CompareTo (object v)
387                 {
388                         if ( v == null)
389                                 return 1;
390
391                         if (!(v is System.DateTime))
392                                 throw new ArgumentException (Locale.GetText (
393                                         "Value is not a System.DateTime"));
394
395                         return Compare (this, (DateTime) v);
396                 }
397
398                 public static int DaysInMonth (int year, int month)
399                 {
400                         int[] days ;
401
402                         if (month < 1 || month >12)
403                                 throw new ArgumentOutOfRangeException ();
404
405                         days = (IsLeapYear(year) ? daysmonthleap  : daysmonth);
406                         return days[month];                     
407                 }
408                 
409                 public override bool Equals (object o)
410                 {
411                         if (!(o is System.DateTime))
412                                 return false;
413
414                         return ((DateTime) o).ticks == ticks;
415                 }
416
417                 public static bool Equals (DateTime t1, DateTime t2 )
418                 {
419                         return (t1.ticks == t2.ticks );
420                 }
421
422                 public static DateTime FromFileTime (long fileTime) 
423                 {
424                         return new DateTime (w32file_epoch + fileTime);
425                 }
426
427                 // TODO: Implement me.
428                 [MonoTODO]
429                 public static DateTime FromOADate (double d)
430                 {
431                                 return new DateTime(0);
432                 }
433                 
434                 // TODO: Implement me.
435                 [MonoTODO]
436                 public string[] GetDateTimeFormats() 
437                 {
438                         return null;
439                 }
440
441                 //TODO: implement me
442                 [MonoTODO]
443                 public string[] GetDateTimeFormats(char format)
444                 {
445                         return null;
446                 }
447                 
448                 // TODO: implement me
449                 [MonoTODO]
450                 public string[] GetDateTimeFormats(IFormatProvider provider)
451                 {
452                         return null;
453                 }
454
455                 //TODO: implement me 
456                 [MonoTODO]
457                 public string[] GetDateTimeFormats(char format,IFormatProvider provider )
458                 {
459                         return null;
460                 }
461
462                 public override int GetHashCode ()
463                 {
464                         return (int) ticks.Ticks;
465                 }
466
467                 public TypeCode GetTypeCode ()
468                 {
469                         return TypeCode.DateTime;
470                 }
471
472                 public static bool IsLeapYear (int year)
473                 {
474                         return  ( (year % 4 == 0 && year % 100 != 0) || year % 400 == 0) ;
475                 }
476
477                 [MonoTODO]
478                 public static DateTime Parse (string s)
479                 {
480                         // TODO: Implement me
481                         return new DateTime (0);
482                 }
483
484                 [MonoTODO]
485                 public static DateTime Parse (string s, IFormatProvider fp)
486                 {
487                         // TODO: Implement me
488                         return new DateTime (0);
489                 }
490
491                 [MonoTODO]
492                 public static DateTime Parse (string s, NumberStyles style, IFormatProvider fp)
493                 {
494                         // TODO: Implement me
495                         return new DateTime (0);
496                 }
497
498                 [MonoTODO]
499                 public static DateTime ParseExact(string s,     string format, IFormatProvider provider )
500                 {
501                         // TODO: Implement me
502                         return new DateTime (0);
503                 }
504
505                 [MonoTODO]
506                 public static DateTime ParseExact(string s, string format, IFormatProvider provider, DateTimeStyles style )
507                 {
508                         // TODO: Implement me
509                         return new DateTime (0);
510                 
511                 }
512
513                 [MonoTODO]
514                 public static DateTime ParseExact( string s, string[] formats, IFormatProvider provider,
515                                                    DateTimeStyles style )
516                 {
517                         // TODO: Implement me
518                         return new DateTime (0);
519                 
520                 }
521                 
522                 public TimeSpan Subtract(DateTime dt)
523                 {   
524                         return new TimeSpan(ticks.Ticks) - dt.ticks;
525                 }
526
527                 public DateTime Subtract(TimeSpan ts)
528                 {
529                         TimeSpan newticks;
530
531                         newticks = (new TimeSpan (ticks.Ticks)) - ts;
532                         return new DateTime(true,newticks);
533                 }
534
535                 public long ToFileTime()
536                 {
537                         if(ticks.Ticks < w32file_epoch) {
538                                 throw new ArgumentOutOfRangeException("file time is not valid");
539                         }
540                         
541                         return(ticks.Ticks - w32file_epoch);
542                 }
543
544                 public string ToLongDateString()
545                 {
546                         return ToString ("D");
547                 }
548
549                 public string ToLongTimeString()
550                 {
551                         return ToString ("T");
552                 }
553
554                 [MonoTODO]
555                 public double ToOADate()
556                 {
557                         // TODO implement me 
558                         return 0;
559                 }
560
561                 public string ToShortDateString()
562                 {
563                         return ToString ("d");
564                 }
565
566                 public string ToShortTimeString()
567                 {
568                         return ToString ("t");
569                 }
570                 
571                 public override string ToString ()
572                 {
573                         return ToString (null, null);
574                 }
575
576                 public string ToString (IFormatProvider fp)
577                 {
578                         return ToString (null, fp);
579                 }
580
581                 public string ToString (string format)
582                 {
583                         return ToString (format, null);
584                 }
585
586                 internal string _GetStandardPattern (char format, DateTimeFormatInfo dfi, out bool useutc)
587                 {
588                         String pattern, f1, f2;
589
590                         useutc = false;
591
592                         switch (format)
593                         {
594                         case 'd':
595                                 pattern = dfi.ShortDatePattern;
596                                 break;
597                         case 'D':
598                                 pattern = dfi.LongDatePattern;
599                                 break;
600                         case 'f':
601                                 f1 = dfi.LongDatePattern;
602                                 f2 = dfi.ShortTimePattern;
603                                 pattern = String.Concat (f1, " ");
604                                 pattern = String.Concat (pattern, f2);
605                                 break;
606                         case 'F':
607                                 pattern = dfi.FullDateTimePattern;
608                                 break;
609                         case 'g':
610                                 f1 = dfi.ShortDatePattern;
611                                 f2 = dfi.ShortTimePattern;
612                                 pattern = String.Concat (f1, " ");
613                                 pattern = String.Concat (pattern, f2);
614                                 break;
615                         case 'G':
616                                 f1 = dfi.ShortDatePattern;
617                                 f2 = dfi.LongTimePattern;
618                                 pattern = String.Concat (f1, " ");
619                                 pattern = String.Concat (pattern, f2);
620                                 break;
621                         case 'm':
622                         case 'M':
623                                 pattern = dfi.MonthDayPattern;
624                                 break;
625                         case 'r':
626                         case 'R':
627                                 pattern = dfi.RFC1123Pattern;
628                                 break;
629                         case 's':
630                                 pattern = dfi.SortableDateTimePattern;
631                                 break;
632                         case 't':
633                                 pattern = dfi.ShortTimePattern;
634                                 break;
635                         case 'T':
636                                 pattern = dfi.LongTimePattern;
637                                 break;
638                         case 'u':
639                                 pattern = dfi.UniversalSortableDateTimePattern;
640                                 useutc = true;
641                                 break;
642                         case 'U':
643                                 f1 = dfi.LongDatePattern;
644                                 f2 = dfi.LongTimePattern;
645                                 pattern = String.Concat (f1, " ");
646                                 pattern = String.Concat (pattern, f2);
647                                 useutc = true;
648                                 break;
649                         case 'y':
650                         case 'Y':
651                                 pattern = dfi.YearMonthPattern;
652                                 break;
653                         default:
654                                 pattern = null;
655                                 break;
656                         }
657
658                         Console.Write ("Pattern: ");
659                         Console.WriteLine (pattern);
660
661                         return pattern;
662                 }
663
664                 internal string _ToString (string format, DateTimeFormatInfo dfi)
665                 {
666                         String str = null, result = null;
667                         char[] chars = format.ToCharArray ();
668                         int len = format.Length, pos = 0, num = 0;
669
670                         while (pos+num < len)
671                         {
672                                 if (chars[pos] == '\'')
673                                 {
674                                         num = 1;
675                                         while (pos+num < len)
676                                         {
677                                                 if (chars[pos+num] == '\'')
678                                                         break;
679
680                                                 result = String.Concat (result, chars[pos+num]);
681
682                                                 num = num + 1;
683                                         }
684                                         if (pos+num > len)
685                                                 throw new FormatException (Locale.GetText ("The specified format is invalid"));
686
687                                         pos = pos + num + 1;
688                                         num = 0;
689                                         continue;
690                                 }
691                                 else if (chars[pos] == '\\')
692                                 {
693                                         if (pos+1 >= len)
694                                                 throw new FormatException (Locale.GetText ("The specified format is invalid"));
695
696                                         result = String.Concat (result, chars[pos]);
697                                         pos = pos + 1;
698                                         continue;
699                                 }
700                                 else if (chars[pos] == '%')
701                                 {
702                                         pos = pos + 1;
703                                         continue;
704                                 }
705
706
707                                 if ((pos+num+1 < len) && (chars[pos+num+1] == chars[pos+num]))
708                                 {
709                                         num = num + 1;
710                                         continue;
711                                 }
712
713                                 switch (chars[pos])
714                                 {
715                                 case 'd':
716                                         if (num == 0)
717                                                 str = Day.ToString ("d");
718                                         else if (num == 1)
719                                                 str = Day.ToString ("d02");
720                                         else if (num == 2)
721                                                 str = dfi.GetAbbreviatedDayName (DayOfWeek);
722                                         else
723                                         {
724                                                 str = dfi.GetDayName (DayOfWeek);
725                                                 num = 3;
726                                         }
727                                         break;
728                                 case 'M':
729                                         if (num == 0)
730                                                 str = Month.ToString ("d");
731                                         else if (num == 1)
732                                                 str = Month.ToString ("d02");
733                                         else if (num == 2)
734                                                 str = dfi.GetAbbreviatedMonthName (Month);
735                                         else
736                                         {
737                                                 str = dfi.GetMonthName (Month);
738                                                 num = 3;
739                                         }
740                                         break;
741                                 case 'y':
742                                         if (num == 0)
743                                         {
744                                                 int shortyear = Year % 100;
745                                                 str = shortyear.ToString ("d");
746                                         }
747                                         else if (num < 3)
748                                         {
749                                                 int shortyear = Year % 100;
750                                                 str = shortyear.ToString ("d02");
751                                                 num = 1;
752                                         }
753                                         else
754                                         {
755                                                 str = Year.ToString ("d");
756                                                 num = 3;
757                                         }
758                                         break;
759                                 case 'g':
760                                         // FIXME
761                                         break;
762                                 case 'f':
763                                         num = Math.Min (num, 6);
764
765                                         long ms = (long) Millisecond;
766                                         long exp = 10;
767                                         for (int i = 0; i < num; i++)
768                                                 exp = exp * 10;
769                                         long maxexp = TimeSpan.TicksPerMillisecond;
770
771                                         exp = Math.Min (exp, maxexp);
772                                         ms = ms * exp / maxexp;
773
774                                         String prec = (num+1).ToString ("d02");
775                                         str = ms.ToString (String.Concat ("d", prec));
776
777                                         break;
778                                 case 'h':
779                                         if (num == 0)
780                                         {
781                                                 int shorthour = Hour % 12;
782                                                 str = shorthour.ToString ("d");
783                                         }
784                                         else
785                                         {
786                                                 int shorthour = Hour % 12;
787                                                 str = shorthour.ToString ("d02");
788                                                 num = 1;
789                                         }
790                                         break;
791                                 case 'H':
792                                         if (num == 0)
793                                                 str = Hour.ToString ("d");
794                                         else
795                                         {
796                                                 str = Hour.ToString ("d02");
797                                                 num = 1;
798                                         }
799                                         break;
800                                 case 'm':
801                                         if (num == 0)
802                                                 str = Minute.ToString ("d");
803                                         else
804                                         {
805                                                 str = Minute.ToString ("d02");
806                                                 num = 1;
807                                         }
808                                         break;
809                                 case 's':
810                                         if (num == 0)
811                                                 str = Second.ToString ("d");
812                                         else
813                                         {
814                                                 str = Second.ToString ("d02");
815                                                 num = 1;
816                                         }
817                                         break;
818                                 case 't':
819                                         if (Hour < 12)
820                                                 str = dfi.AMDesignator;
821                                         else
822                                                 str = dfi.PMDesignator;
823
824                                         if (num == 0)
825                                                 str = str.Substring (0,1);
826                                         else
827                                                 num = 1;
828                                         break;
829                                 case 'z':
830                                         if (num == 0)
831                                         {
832                                                 int offset = utcoffset.Hours;
833                                                 str = offset.ToString ("d");
834                                                 if (offset > 0)
835                                                         str = String.Concat ("+", str);
836                                         }
837                                         else if (num == 1)
838                                         {
839                                                 int offset = utcoffset.Hours;
840                                                 str = offset.ToString ("d02");
841                                                 if (offset > 0)
842                                                         str = String.Concat ("+", str);
843                                         }
844                                         else if (num == 2)
845                                         {
846                                                 int offhour = utcoffset.Hours;
847                                                 int offminute = utcoffset.Minutes;
848                                                 str = offhour.ToString ("d02");
849                                                 str = String.Concat (str, dfi.TimeSeparator);
850                                                 str = String.Concat (str, offminute.ToString ("d02"));
851                                                 if (offhour > 0)
852                                                         str = String.Concat ("+", str);
853                                                 num = 2;
854                                         }
855                                         break;
856                                 case ':':
857                                         str = dfi.TimeSeparator;
858                                         num = 1;
859                                         break;
860                                 case '/':
861                                         str = dfi.DateSeparator;
862                                         num = 1;
863                                         break;
864                                 default:
865                                         str = String.Concat (chars [pos]);
866                                         num = 0;
867                                         break;
868                                 }
869
870                                 result = String.Concat (result, str);
871                                                 
872                                 pos = pos + num + 1;
873                                 num = 0;
874                         }
875
876                         return result;
877                 }
878
879                 [MonoTODO]
880                 public string ToString (string format, IFormatProvider fp)
881                 {
882                         DateTimeFormatInfo dfi = DateTimeFormatInfo.GetInstance(fp);
883
884                         if (format == null)
885                                 format = dfi.FullDateTimePattern;
886
887                         bool useutc = false;
888
889                         if (format.Length == 1) {
890                                 char fchar = (format.ToCharArray ())[0];
891                                 format = this._GetStandardPattern (fchar, dfi, out useutc);
892                         }
893
894                         if (useutc)
895                                 return this.ToUniversalTime ()._ToString (format, dfi);
896                         else
897                                 return this._ToString (format, dfi);
898                 }
899
900                 public DateTime ToLocalTime()
901                 {
902                         TimeZone tz = TimeZone.CurrentTimeZone;
903
904                         TimeSpan offset = tz.GetUtcOffset (this);
905
906                         return new DateTime (true, ticks + offset);
907                 }
908
909                 public DateTime ToUniversalTime()
910                 {
911                         TimeZone tz = TimeZone.CurrentTimeZone;
912
913                         TimeSpan offset = tz.GetUtcOffset (this);
914
915                         return new DateTime (true, ticks - offset);
916                 }
917
918                 /*  OPERATORS */
919
920                 public static DateTime operator +(DateTime d, TimeSpan t)
921                 {
922                         return new DateTime (true, d.ticks + t);
923                 }
924
925                 public static bool operator ==(DateTime d1, DateTime d2)
926                 {
927                         return (d1.ticks == d2.ticks);
928                 }
929
930                 public static bool operator >(DateTime t1,DateTime t2)
931                 {
932                         return (t1.ticks > t2.ticks);
933                 }
934
935                 public static bool operator >=(DateTime t1,DateTime t2)
936                 {
937                         return (t1.ticks >= t2.ticks);
938                 }
939
940                 public static bool operator !=(DateTime d1, DateTime d2)
941                 {
942                         return (d1.ticks != d2.ticks);
943                 }
944
945                 public static bool operator <(DateTime t1,      DateTime t2)
946                 {
947                         return (t1.ticks < t2.ticks );
948                 }
949
950                 public static bool operator <=(DateTime t1,DateTime t2)
951                 {
952                         return (t1.ticks <= t2.ticks);
953                 }
954
955                 public static TimeSpan operator -(DateTime d1,DateTime d2)
956                 {
957                         return new TimeSpan((d1.ticks - d2.ticks).Ticks);
958                 }
959
960                 public static DateTime operator -(DateTime d,TimeSpan t)
961                 {
962                         return new DateTime (true, d.ticks - t);
963                 }
964
965                 public bool ToBoolean(IFormatProvider provider)
966                 {
967                         throw new InvalidCastException();
968                 }
969                 
970                 public byte ToByte(IFormatProvider provider)
971                 {
972                         throw new InvalidCastException();
973                 }
974
975                 public char ToChar(IFormatProvider provider)
976                 {
977                         throw new InvalidCastException();
978                 }
979
980                 // TODO Implement me
981                 [MonoTODO]
982                 public System.DateTime ToDateTime(IFormatProvider provider)
983                 {
984                         return new System.DateTime(true,this.ticks);
985                 } 
986                 
987                 public decimal ToDecimal(IFormatProvider provider)
988                 {
989                          throw new InvalidCastException();
990                 }
991
992                 public double ToDouble(IFormatProvider provider)
993                 {
994                         throw new InvalidCastException();
995                 }
996
997                 public Int16 ToInt16(IFormatProvider provider)
998                 {
999                         throw new InvalidCastException();
1000                 }
1001
1002                 public Int32 ToInt32(IFormatProvider provider)
1003                 {
1004                         throw new InvalidCastException();
1005                 }
1006
1007                 public Int64 ToInt64(IFormatProvider provider)
1008                 {
1009                         throw new InvalidCastException();
1010                 }
1011
1012                 [CLSCompliant(false)]
1013                 public SByte ToSByte(IFormatProvider provider)
1014                 {
1015                         throw new InvalidCastException();
1016                 }
1017
1018                 public Single ToSingle(IFormatProvider provider)
1019                 {
1020                         throw new InvalidCastException();
1021                 }
1022
1023                 public object ToType(Type conversionType,IFormatProvider provider)
1024                 {
1025                         throw new InvalidCastException();
1026                 }
1027
1028                 UInt16 System.IConvertible.ToUInt16(IFormatProvider provider)
1029                 {
1030                         throw new InvalidCastException();
1031                 }
1032                 
1033                 [CLSCompliant(false)]
1034                 public UInt32 ToUInt32(IFormatProvider provider)
1035                 {
1036                         throw new InvalidCastException();
1037                 }
1038
1039                 [CLSCompliant(false)]
1040                 public UInt64 ToUInt64(IFormatProvider provider)
1041                 {
1042                         throw new InvalidCastException();
1043                 }
1044         }
1045 }
1046
1047 namespace System
1048 {
1049         public enum DayOfWeek
1050         {
1051                 Sunday,
1052                 Monday,
1053                 Tuesday,
1054                 Wednesday,
1055                 Thursday,
1056                 Friday,
1057                 Saturday
1058         }
1059 }