2 // System.DateTime.cs
\r
5 // Marcel Narings (marcel@narings.nl)
\r
6 // Martin Baulig (martin@gnome.org)
\r
8 // (C) 2001 Marcel Narings
\r
11 using System.Globalization;
\r
12 using System.Runtime.CompilerServices;
\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
23 public struct DateTime : IComparable, IFormattable, IConvertible
\r
25 private TimeSpan ticks;
\r
27 private const int dp400 = 146097;
\r
28 private const int dp100 = 36524;
\r
29 private const int dp4 = 1461;
\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
36 // The UnixEpoch, it begins on Jan 1, 1970 at 0:0:0, expressed
\r
39 internal const long UnixEpoch = 621355968000000000L;
\r
41 public static readonly DateTime MaxValue = new DateTime (false,TimeSpan.MaxValue);
\r
42 public static readonly DateTime MinValue = new DateTime (false,0);
\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
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
58 // Only date, but no year
\r
60 // Only date, but no day
\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
75 private static int AbsoluteDays (int year, int month, int day)
\r
83 days = (IsLeapYear(year) ? daysmonthleap : daysmonth);
\r
87 return ((day-1) + temp + (365* (year-1)) + ((year-1)/4) - ((year-1)/100) + ((year-1)/400));
\r
90 private int FromTicks(Which what)
\r
92 int num400, num100, num4, numyears;
\r
95 int[] days = daysmonth;
\r
96 int totaldays = this.ticks.Days;
\r
98 num400 = (totaldays / dp400);
\r
99 totaldays -= num400 * dp400;
\r
101 num100 = (totaldays / dp100);
\r
102 if (num100 == 4) // leap
\r
104 totaldays -= (num100 * dp100);
\r
106 num4 = totaldays / dp4;
\r
107 totaldays -= (num4 * dp4);
\r
109 numyears = totaldays / 365 ;
\r
111 if (numyears == 4) //leap
\r
113 if (what == Which.Year )
\r
114 return num400*400 + num100*100 + num4*4 + numyears + 1;
\r
116 totaldays -= (numyears * 365) ;
\r
117 if (what == Which.DayYear )
\r
118 return totaldays + 1;
\r
120 if ((numyears==3) && ((num100 == 3) || !(num4 == 24)) ) //31 dec leapyear
\r
121 days = daysmonthleap;
\r
123 while (totaldays >= days[M])
\r
124 totaldays -= days[M++];
\r
126 if (what == Which.Month )
\r
129 return totaldays +1;
\r
136 /// Constructs a DateTime for specified ticks
\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
144 internal DateTime (bool local, long newticks)
\r
146 ticks = new TimeSpan (newticks);
\r
148 TimeZone tz = TimeZone.CurrentTimeZone;
\r
150 TimeSpan utcoffset = tz.GetUtcOffset (this);
\r
152 ticks = ticks + utcoffset;
\r
154 if (ticks.Ticks < MinValue.Ticks || ticks.Ticks > MaxValue.Ticks)
\r
155 throw new ArgumentOutOfRangeException ();
\r
158 public DateTime (int year, int month, int day)
\r
159 : this (year, month, day,0,0,0,0) {}
\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
164 public DateTime (int year, int month, int day, int hour, int minute, int second, int millisecond)
\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
175 ticks = new TimeSpan (AbsoluteDays(year,month,day), hour, minute, second, millisecond);
\r
178 public DateTime (int year, int month, int day, Calendar calendar)
\r
179 : this (year, month, day, 0, 0, 0, 0, calendar) {}
\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
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
189 if (calendar == null)
\r
190 throw new ArgumentNullException();
\r
193 internal DateTime (bool check, TimeSpan value)
\r
195 if (check && (value.Ticks < MinValue.Ticks || value.Ticks > MaxValue.Ticks))
\r
196 throw new ArgumentOutOfRangeException ();
\r
203 public DateTime Date
\r
207 return new DateTime (Year, Month, Day);
\r
215 return FromTicks(Which.Month);
\r
224 return FromTicks(Which.Day);
\r
228 public DayOfWeek DayOfWeek
\r
232 return ( (DayOfWeek) ((ticks.Days+1) % 7) );
\r
236 public int DayOfYear
\r
240 return FromTicks(Which.DayYear);
\r
244 public TimeSpan TimeOfDay
\r
248 return new TimeSpan(ticks.Ticks % TimeSpan.TicksPerDay );
\r
257 return ticks.Hours;
\r
265 return ticks.Minutes;
\r
273 return ticks.Seconds;
\r
277 public int Millisecond
\r
281 return ticks.Milliseconds;
\r
285 [MethodImplAttribute(MethodImplOptions.InternalCall)]
\r
286 internal static extern long GetNow ();
\r
288 public static DateTime Now
\r
292 return new DateTime (true, GetNow ());
\r
300 return ticks.Ticks;
\r
304 public static DateTime Today
\r
307 DateTime now = Now;
\r
308 return new DateTime (now.Year, now.Month, now.Day);
\r
312 public static DateTime UtcNow
\r
315 return new DateTime (GetNow ());
\r
323 return FromTicks(Which.Year);
\r
329 public DateTime Add (TimeSpan ts)
\r
331 return new DateTime (true, ticks) + ts;
\r
334 public DateTime AddDays (double days)
\r
336 return AddMilliseconds (days * 86400000);
\r
339 public DateTime AddTicks (long t)
\r
341 return Add (new TimeSpan (t));
\r
344 public DateTime AddHours (double hours)
\r
346 return AddMilliseconds (hours * 3600000);
\r
349 public DateTime AddMilliseconds (double ms)
\r
353 msticks = (long) (ms += ms > 0 ? 0.5 : -0.5) * TimeSpan.TicksPerMillisecond ;
\r
355 return AddTicks (msticks);
\r
358 public DateTime AddMinutes (double minutes)
\r
360 return AddMilliseconds (minutes * 60000);
\r
363 public DateTime AddMonths (int months)
\r
365 int day, month, year, maxday ;
\r
369 month = this.Month + (months % 12);
\r
370 year = this.Year + months/12 ;
\r
374 month = 12 + month ;
\r
377 else if (month>12)
\r
382 maxday = DaysInMonth(year, month);
\r
386 temp = new DateTime (year, month, day);
\r
387 return temp.Add (this.TimeOfDay);
\r
390 public DateTime AddSeconds (double seconds)
\r
392 return AddMilliseconds (seconds*1000);
\r
395 public DateTime AddYears (int years )
\r
397 return AddMonths(years * 12);
\r
400 public static int Compare (DateTime t1, DateTime t2)
\r
402 if (t1.ticks < t2.ticks)
\r
404 else if (t1.ticks > t2.ticks)
\r
410 public int CompareTo (object v)
\r
415 if (!(v is System.DateTime))
\r
416 throw new ArgumentException (Locale.GetText (
\r
417 "Value is not a System.DateTime"));
\r
419 return Compare (this, (DateTime) v);
\r
422 public static int DaysInMonth (int year, int month)
\r
426 if (month < 1 || month >12)
\r
427 throw new ArgumentOutOfRangeException ();
\r
429 days = (IsLeapYear(year) ? daysmonthleap : daysmonth);
\r
430 return days[month];
\r
433 public override bool Equals (object o)
\r
435 if (!(o is System.DateTime))
\r
438 return ((DateTime) o).ticks == ticks;
\r
441 public static bool Equals (DateTime t1, DateTime t2 )
\r
443 return (t1.ticks == t2.ticks );
\r
446 public static DateTime FromFileTime (long fileTime)
\r
448 return new DateTime (true, w32file_epoch + fileTime);
\r
451 public static DateTime FromOADate (double d)
\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
456 // d must be negative 657435.0 through positive 2958466.0.
\r
458 if ((d < -657435.0) || (d > 2958466.0))
\r
459 throw new OverflowException();
\r
461 return (new DateTime(1899, 12, 30, 0, 0, 0)).AddDays(d);
\r
464 public string[] GetDateTimeFormats()
\r
466 string[] result = new string[formats.Length];
\r
468 foreach (string format in formats) {
\r
469 result [index] = this.ToString(format);
\r
475 public string[] GetDateTimeFormats(char format)
\r
477 string[] result = new string[1];
\r
478 result[0] = this.ToString(format.ToString());
\r
482 // TODO: implement me
\r
484 public string[] GetDateTimeFormats(IFormatProvider provider)
\r
489 //TODO: implement me
\r
491 public string[] GetDateTimeFormats(char format,IFormatProvider provider )
\r
496 public override int GetHashCode ()
\r
498 return (int) ticks.Ticks;
\r
501 public TypeCode GetTypeCode ()
\r
503 return TypeCode.DateTime;
\r
506 public static bool IsLeapYear (int year)
\r
508 return ( (year % 4 == 0 && year % 100 != 0) || year % 400 == 0) ;
\r
511 public static DateTime Parse (string s)
\r
513 return Parse (s, null);
\r
516 public static DateTime Parse (string s, IFormatProvider fp)
\r
518 return Parse (s, null, DateTimeStyles.AllowWhiteSpaces);
\r
521 public static DateTime Parse (string s, IFormatProvider fp, DateTimeStyles styles)
\r
523 return ParseExact (s, formats, fp, styles);
\r
526 public static DateTime ParseExact (string s, string format, IFormatProvider fp)
\r
528 return ParseExact (s, format, fp, DateTimeStyles.None);
\r
531 internal static int _ParseNumber (string s, int digits, bool leadingzero,
\r
532 bool sloppy_parsing, out int num_parsed)
\r
536 if (sloppy_parsing)
\r
537 leadingzero = false;
\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
548 digits = real_digits;
\r
551 if (s.Length < digits) {
\r
556 for (i = 0; i < digits; i++) {
\r
558 if (!Char.IsDigit (c)) {
\r
563 number = number * 10 + (byte) (c - '0');
\r
566 num_parsed = digits;
\r
570 internal static int _ParseEnum (string s, string[] values, out int num_parsed)
\r
574 for (i = 0; i < values.Length; i++) {
\r
575 if (s.Length < values[i].Length)
\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
588 internal static bool _ParseString (string s, int maxlength, string value, out int num_parsed)
\r
591 value = value.Substring (0, maxlength);
\r
593 s = s.Substring (0, value.Length);
\r
595 if (String.Compare (s, value, true) == 0) {
\r
596 num_parsed = value.Length;
\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
609 bool useutc = false, use_localtime = true;
\r
610 bool sloppy_parsing = false;
\r
612 if (format.Length == 1)
\r
613 format = _GetStandardPattern (format[0], dfi, out useutc);
\r
615 if ((style & DateTimeStyles.AllowLeadingWhite) != 0) {
\r
616 format = format.TrimStart (null);
\r
618 s = s.TrimStart (null);
\r
621 if ((style & DateTimeStyles.AllowTrailingWhite) != 0) {
\r
622 format = format.TrimEnd (null);
\r
623 s = s.TrimEnd (null);
\r
626 if ((style & DateTimeStyles.AllowInnerWhite) != 0)
\r
627 sloppy_parsing = true;
\r
629 char[] chars = format.ToCharArray ();
\r
630 int len = format.Length, pos = 0, num = 0;
\r
632 int day = -1, dayofweek = -1, month = -1, year = -1;
\r
633 int hour = -1, minute = -1, second = -1, millisecond = -1;
\r
635 int tzsign = -1, tzoffset = -1, tzoffmin = -1;
\r
637 result = new DateTime (0);
\r
638 while (pos+num < len)
\r
643 if (Char.IsWhiteSpace (s[0])) {
\r
644 s = s.Substring (1);
\r
646 if (Char.IsWhiteSpace (chars[pos])) {
\r
651 if ((style & DateTimeStyles.AllowInnerWhite) == 0)
\r
655 if (chars[pos] == '\'') {
\r
657 while (pos+num < len) {
\r
658 if (chars[pos+num] == '\'')
\r
663 if (s[0] != chars[pos+num])
\r
665 s = s.Substring (1);
\r
675 } else if (chars[pos] == '\\') {
\r
679 if (s[0] != chars[pos+num])
\r
681 s = s.Substring (1);
\r
687 } else if (chars[pos] == '%') {
\r
692 if ((pos+num+1 < len) && (chars[pos+num+1] == chars[pos+num])) {
\r
697 int num_parsed = 0;
\r
699 switch (chars[pos])
\r
705 day = _ParseNumber (s, 2, false, sloppy_parsing, out num_parsed);
\r
707 day = _ParseNumber (s, 2, true, sloppy_parsing, out num_parsed);
\r
709 dayofweek = _ParseEnum (s, dfi.AbbreviatedDayNames, out num_parsed);
\r
712 dayofweek = _ParseEnum (s, dfi.DayNames, out num_parsed);
\r
720 month = _ParseNumber (s, 2, false, sloppy_parsing, out num_parsed);
\r
722 month = _ParseNumber (s, 2, true, sloppy_parsing, out num_parsed);
\r
724 month = _ParseEnum (s, dfi.AbbreviatedMonthNames , out num_parsed) + 1;
\r
727 month = _ParseEnum (s, dfi.MonthNames, out num_parsed) + 1;
\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
742 year = _ParseNumber (s, 4, false, sloppy_parsing, out num_parsed);
\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
756 hour = _ParseNumber (s, 2, false, sloppy_parsing, out num_parsed);
\r
759 hour = _ParseNumber (s, 2, true, sloppy_parsing, out num_parsed);
\r
768 if ((hour != -1) || (ampm >= 0))
\r
771 hour = _ParseNumber (s, 2, false, sloppy_parsing, out num_parsed);
\r
774 hour = _ParseNumber (s, 2, true, sloppy_parsing, out num_parsed);
\r
786 minute = _ParseNumber (s, 2, false, sloppy_parsing, out num_parsed);
\r
789 minute = _ParseNumber (s, 2, true, sloppy_parsing, out num_parsed);
\r
800 second = _ParseNumber (s, 2, false, sloppy_parsing, out num_parsed);
\r
803 second = _ParseNumber (s, 2, true, sloppy_parsing, out num_parsed);
\r
811 if (millisecond != -1)
\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
823 if (_ParseString (s, 1, dfi.AMDesignator, out num_parsed))
\r
825 else if (_ParseString (s, 1, dfi.PMDesignator, out num_parsed))
\r
832 if (_ParseString (s, 0, dfi.AMDesignator, out num_parsed))
\r
834 else if (_ParseString (s, 0, dfi.PMDesignator, out num_parsed))
\r
846 else if (s[0] == '-')
\r
850 s = s.Substring (1);
\r
852 tzoffset = _ParseNumber (s, 2, false, sloppy_parsing, out num_parsed);
\r
854 tzoffset = _ParseNumber (s, 2, true, sloppy_parsing, out num_parsed);
\r
857 tzoffset = _ParseNumber (s, 2, true, sloppy_parsing, out num_parsed);
\r
858 if (num_parsed < 0)
\r
860 s = s.Substring (num_parsed);
\r
861 if (!_ParseString (s, 0, dfi.TimeSeparator, out num_parsed))
\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
871 if (!_ParseString (s, 0, dfi.TimeSeparator, out num_parsed))
\r
875 if (!_ParseString (s, 0, dfi.DateSeparator, out num_parsed))
\r
879 if (s[0] != chars[pos])
\r
886 if (num_parsed < 0)
\r
889 s = s.Substring (num_parsed);
\r
891 pos = pos + num + 1;
\r
902 if (millisecond == -1)
\r
905 // If no date was given
\r
906 if ((day == -1) && (month == -1) && (year == -1)) {
\r
907 if ((style & DateTimeStyles.NoCurrentDateDefault) != 0) {
\r
913 month = Today.Month;
\r
923 if ((style & DateTimeStyles.NoCurrentDateDefault) != 0)
\r
932 result = new DateTime (year, month, day, hour, minute, second, millisecond);
\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
937 // If no timezone was specified, default to the local timezone.
\r
938 TimeSpan utcoffset;
\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
946 if ((style & DateTimeStyles.AdjustToUniversal) != 0)
\r
947 use_localtime = false;
\r
949 if (tzoffmin == -1)
\r
951 if (tzoffset == -1)
\r
954 tzoffset = -tzoffset;
\r
956 utcoffset = new TimeSpan (tzoffset, tzoffmin, 0);
\r
959 long newticks = (result.ticks - utcoffset).Ticks;
\r
961 result = new DateTime (newticks);
\r
967 public static DateTime ParseExact (string s, string format,
\r
968 IFormatProvider fp, DateTimeStyles style)
\r
972 formats = new string [1];
\r
973 formats[0] = format;
\r
975 return ParseExact (s, formats, fp, style);
\r
978 public static DateTime ParseExact (string s, string[] formats,
\r
979 IFormatProvider fp,
\r
980 DateTimeStyles style)
\r
982 DateTimeFormatInfo dfi = DateTimeFormatInfo.GetInstance (fp);
\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
990 for (i = 0; i < formats.Length; i++)
\r
994 if (_DoParse (s, formats[i], true, out result, dfi, style))
\r
998 throw new FormatException ();
\r
1001 public TimeSpan Subtract(DateTime dt)
\r
1003 return new TimeSpan(ticks.Ticks) - dt.ticks;
\r
1006 public DateTime Subtract(TimeSpan ts)
\r
1008 TimeSpan newticks;
\r
1010 newticks = (new TimeSpan (ticks.Ticks)) - ts;
\r
1011 return new DateTime(true,newticks);
\r
1014 public long ToFileTime()
\r
1016 DateTime universalTime = ToUniversalTime();
\r
1018 if (universalTime.Ticks < w32file_epoch) {
\r
1019 throw new ArgumentOutOfRangeException("file time is not valid");
\r
1022 return(universalTime.Ticks - w32file_epoch);
\r
1025 public string ToLongDateString()
\r
1027 return ToString ("D");
\r
1030 public string ToLongTimeString()
\r
1032 return ToString ("T");
\r
1035 public double ToOADate()
\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
1042 public string ToShortDateString()
\r
1044 return ToString ("d");
\r
1047 public string ToShortTimeString()
\r
1049 return ToString ("t");
\r
1052 public override string ToString ()
\r
1054 return ToString ("G", null);
\r
1057 public string ToString (IFormatProvider fp)
\r
1059 return ToString (null, fp);
\r
1062 public string ToString (string format)
\r
1064 return ToString (format, null);
\r
1067 internal static string _GetStandardPattern (char format, DateTimeFormatInfo dfi, out bool useutc)
\r
1076 pattern = dfi.ShortDatePattern;
\r
1079 pattern = dfi.LongDatePattern;
\r
1082 pattern = dfi.LongDatePattern + " " + dfi.ShortTimePattern;
\r
1085 pattern = dfi.FullDateTimePattern;
\r
1088 pattern = dfi.ShortDatePattern + " " + dfi.ShortTimePattern;
\r
1091 pattern = dfi.ShortDatePattern + " " + dfi.LongTimePattern;
\r
1095 pattern = dfi.MonthDayPattern;
\r
1099 pattern = dfi.RFC1123Pattern;
\r
1100 // commented by LP 09/jun/2002, rfc 1123 pattern is always in GMT
\r
1104 pattern = dfi.SortableDateTimePattern;
\r
1107 pattern = dfi.ShortTimePattern;
\r
1110 pattern = dfi.LongTimePattern;
\r
1113 pattern = dfi.UniversalSortableDateTimePattern;
\r
1117 pattern = dfi.LongDatePattern + " " + dfi.LongTimePattern;
\r
1122 pattern = dfi.YearMonthPattern;
\r
1132 internal string _ToString (string format, DateTimeFormatInfo dfi)
\r
1134 String str = null, result = null;
\r
1135 char[] chars = format.ToCharArray ();
\r
1136 int len = format.Length, pos = 0, num = 0;
\r
1138 TimeZone tz = TimeZone.CurrentTimeZone;
\r
1139 TimeSpan utcoffset = tz.GetUtcOffset (this);
\r
1143 if (chars[pos] == '\'') {
\r
1145 while (pos+num <= len) {
\r
1146 if (chars[pos+num] == '\'')
\r
1149 result += chars[pos+num];
\r
1152 if (pos+num > len)
\r
1153 throw new FormatException (Locale.GetText ("The specified format is invalid"));
\r
1158 } else if (chars[pos] == '\\') {
\r
1160 throw new FormatException (Locale.GetText ("The specified format is invalid"));
\r
1162 result += chars[pos+1];
\r
1165 } else if (chars[pos] == '%') {
\r
1170 if ((pos+num+1 < len) && (chars[pos+num+1] == chars[pos+num])) {
\r
1175 switch (chars[pos])
\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
1185 str = dfi.GetDayName (DayOfWeek);
\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
1197 str = dfi.GetMonthName (Month);
\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
1209 str = Year.ToString ("d04");
\r
1217 num = Math.Min (num, 6);
\r
1219 long relativeTicks = ticks.Ticks % TimeSpan.TicksPerSecond;
1222 for (int i = 0; i < num; i++)
\r
1225 long frac = relativeTicks * exp / TimeSpan.TicksPerSecond;
\r
1227 String prec = (num+1).ToString ("d02");
\r
1228 str = frac.ToString (String.Concat ("d", prec));
\r
1234 int shorthour = Hour % 12;
\r
1235 str = shorthour.ToString ("d");
\r
1237 int shorthour = Hour % 12;
\r
1238 str = shorthour.ToString ("d02");
\r
1244 str = Hour.ToString ("d");
\r
1246 str = Hour.ToString ("d02");
\r
1252 str = Minute.ToString ("d");
\r
1254 str = Minute.ToString ("d02");
\r
1260 str = Second.ToString ("d");
\r
1262 str = Second.ToString ("d02");
\r
1268 str = dfi.AMDesignator;
\r
1270 str = dfi.PMDesignator;
\r
1273 str = str.Substring (0,1);
\r
1279 int offset = utcoffset.Hours;
\r
1280 str = offset.ToString ("d");
\r
1281 str = String.Concat ((offset >= 0) ? "+" : "", str);
\r
1283 else if (num == 1)
\r
1285 int offset = utcoffset.Hours;
\r
1286 str = offset.ToString ("d02");
\r
1287 str = String.Concat ((offset >= 0) ? "+" : "", str);
\r
1289 else if (num == 2)
\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
1301 str = dfi.TimeSeparator;
\r
1305 str = dfi.DateSeparator;
\r
1309 str = String.Concat (chars [pos]);
\r
1314 result = String.Concat (result, str);
\r
1323 public string ToString (string format, IFormatProvider fp)
\r
1326 DateTimeFormatInfo dfi = DateTimeFormatInfo.GetInstance(fp);
\r
1328 if (format == null)
\r
1329 format = dfi.FullDateTimePattern;
\r
1331 bool useutc = false;
\r
1333 if (format.Length == 1) {
\r
1334 char fchar = (format.ToCharArray ())[0];
\r
1335 format = _GetStandardPattern (fchar, dfi, out useutc);
\r
1339 return this.ToUniversalTime ()._ToString (format, dfi);
\r
1341 return this._ToString (format, dfi);
\r
1344 public DateTime ToLocalTime()
\r
1346 TimeZone tz = TimeZone.CurrentTimeZone;
\r
1348 TimeSpan offset = tz.GetUtcOffset (this);
\r
1350 return new DateTime (true, ticks + offset);
\r
1353 public DateTime ToUniversalTime()
\r
1355 TimeZone tz = TimeZone.CurrentTimeZone;
\r
1357 TimeSpan offset = tz.GetUtcOffset (this);
\r
1359 return new DateTime (false, ticks - offset);
\r
1364 public static DateTime operator +(DateTime d, TimeSpan t)
\r
1366 return new DateTime (true, d.ticks + t);
\r
1369 public static bool operator ==(DateTime d1, DateTime d2)
\r
1371 return (d1.ticks == d2.ticks);
\r
1374 public static bool operator >(DateTime t1,DateTime t2)
\r
1376 return (t1.ticks > t2.ticks);
\r
1379 public static bool operator >=(DateTime t1,DateTime t2)
\r
1381 return (t1.ticks >= t2.ticks);
\r
1384 public static bool operator !=(DateTime d1, DateTime d2)
\r
1386 return (d1.ticks != d2.ticks);
\r
1389 public static bool operator <(DateTime t1, DateTime t2)
\r
1391 return (t1.ticks < t2.ticks );
\r
1394 public static bool operator <=(DateTime t1,DateTime t2)
\r
1396 return (t1.ticks <= t2.ticks);
\r
1399 public static TimeSpan operator -(DateTime d1,DateTime d2)
\r
1401 return new TimeSpan((d1.ticks - d2.ticks).Ticks);
\r
1404 public static DateTime operator -(DateTime d,TimeSpan t)
\r
1406 return new DateTime (true, d.ticks - t);
\r
1409 bool IConvertible.ToBoolean(IFormatProvider provider)
\r
1411 throw new InvalidCastException();
\r
1414 byte IConvertible.ToByte(IFormatProvider provider)
\r
1416 throw new InvalidCastException();
\r
1420 char IConvertible.ToChar(IFormatProvider provider)
\r
1422 throw new InvalidCastException();
\r
1425 // TODO Implement me
\r
1427 public System.DateTime ToDateTime(IFormatProvider provider)
\r
1429 return new System.DateTime(true,this.ticks);
\r
1432 decimal IConvertible.ToDecimal(IFormatProvider provider)
\r
1434 throw new InvalidCastException();
\r
1437 double IConvertible.ToDouble(IFormatProvider provider)
\r
1439 throw new InvalidCastException();
\r
1442 Int16 IConvertible.ToInt16(IFormatProvider provider)
\r
1444 throw new InvalidCastException();
\r
1447 Int32 IConvertible.ToInt32(IFormatProvider provider)
\r
1449 throw new InvalidCastException();
\r
1452 Int64 IConvertible.ToInt64(IFormatProvider provider)
\r
1454 throw new InvalidCastException();
\r
1457 [CLSCompliant(false)]
\r
1458 SByte IConvertible.ToSByte(IFormatProvider provider)
\r
1460 throw new InvalidCastException();
\r
1463 Single IConvertible.ToSingle(IFormatProvider provider)
\r
1465 throw new InvalidCastException();
\r
1468 object IConvertible.ToType(Type conversionType,IFormatProvider provider)
\r
1470 throw new InvalidCastException();
\r
1473 UInt16 IConvertible.ToUInt16(IFormatProvider provider)
\r
1475 throw new InvalidCastException();
\r
1478 [CLSCompliant(false)]
\r
1479 UInt32 IConvertible.ToUInt32(IFormatProvider provider)
\r
1481 throw new InvalidCastException();
\r
1484 [CLSCompliant(false)]
\r
1485 UInt64 IConvertible.ToUInt64(IFormatProvider provider)
\r
1488 throw new InvalidCastException();
\r
1495 public enum DayOfWeek
\r