5 // Marcel Narings (marcel@narings.nl)
6 // Martin Baulig (martin@gnome.org)
7 // Atsushi Enomoto (atsushi@ximian.com)
9 // (C) 2001 Marcel Narings
10 // Copyright (C) 2004-2006 Novell, Inc (http://www.novell.com)
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System.Collections;
33 using System.Globalization;
34 using System.Runtime.CompilerServices;
35 using System.Runtime.InteropServices;
41 /// The DateTime structure represents dates and time ranging from
42 /// 1-1-0001 12:00:00 AM to 31-12-9999 23:59:00 Common Era.
46 [StructLayout (LayoutKind.Auto)]
47 public struct DateTime : IFormattable, IConvertible, IComparable
49 , IComparable<DateTime>, IEquatable <DateTime>
52 private TimeSpan ticks;
58 private const int dp400 = 146097;
59 private const int dp100 = 36524;
60 private const int dp4 = 1461;
62 // w32 file time starts counting from 1/1/1601 00:00 GMT
63 // which is the constant ticks from the .NET epoch
64 private const long w32file_epoch = 504911232000000000L;
66 //private const long MAX_VALUE_TICKS = 3155378975400000000L;
67 // -- Microsoft .NET has this value.
68 private const long MAX_VALUE_TICKS = 3155378975999999999L;
71 // The UnixEpoch, it begins on Jan 1, 1970 at 0:0:0, expressed
74 internal const long UnixEpoch = 621355968000000000L;
76 // for OLE Automation dates
77 private const long ticks18991230 = 599264352000000000L;
78 private const double OAMinValue = -657435.0d;
79 private const double OAMaxValue = 2958466.0d;
81 public static readonly DateTime MaxValue = new DateTime (false, new TimeSpan (MAX_VALUE_TICKS));
82 public static readonly DateTime MinValue = new DateTime (false, new TimeSpan (0));
84 // DateTime.Parse patterns
85 // Patterns are divided to date and time patterns. The algorithm will
86 // try combinations of these patterns. The algorithm also looks for
87 // day of the week, AM/PM GMT and Z independently of the patterns.
88 private static readonly string[] ParseTimeFormats = new string [] {
95 "H tt", // Specifies AM to disallow '8'.
96 "H'\u6642'm'\u5206's'\u79D2'",
99 // DateTime.Parse date patterns extend ParseExact patterns as follows:
100 // MMM - month short name or month full name
101 // MMMM - month number or short name or month full name
103 // Parse behaves differently according to the ShorDatePattern of the
104 // DateTimeFormatInfo. The following define the date patterns for
105 // different orders of day, month and year in ShorDatePattern.
106 // Note that the year cannot go between the day and the month.
107 private static readonly string[] ParseYearDayMonthFormats = new string [] {
110 "yyyy'\u5E74'M'\u6708'd'\u65E5",
127 private static readonly string[] ParseYearMonthDayFormats = new string [] {
130 "yyyy'\u5E74'M'\u6708'd'\u65E5",
144 private static readonly string[] ParseDayMonthYearFormats = new string [] {
147 "yyyy'\u5E74'M'\u6708'd'\u65E5",
164 private static readonly string[] ParseMonthDayYearFormats = new string [] {
167 "yyyy'\u5E74'M'\u6708'd'\u65E5",
184 // Patterns influenced by the MonthDayPattern in DateTimeFormatInfo.
185 // Note that these patterns cannot be followed by the time.
186 private static readonly string[] MonthDayShortFormats = new string [] {
191 private static readonly string[] DayMonthShortFormats = new string [] {
195 #else // In .Net 1.0 Feb 03 is always Feb 3rd (and not Feb 2003)
209 private static readonly int[] daysmonth = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
210 private static readonly int[] daysmonthleap = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
212 private static int AbsoluteDays (int year, int month, int day)
217 days = (IsLeapYear(year) ? daysmonthleap : daysmonth);
221 return ((day-1) + temp + (365* (year-1)) + ((year-1)/4) - ((year-1)/100) + ((year-1)/400));
224 private int FromTicks(Which what)
226 int num400, num100, num4, numyears;
229 int[] days = daysmonth;
230 int totaldays = this.ticks.Days;
232 num400 = (totaldays / dp400);
233 totaldays -= num400 * dp400;
235 num100 = (totaldays / dp100);
236 if (num100 == 4) // leap
238 totaldays -= (num100 * dp100);
240 num4 = totaldays / dp4;
241 totaldays -= (num4 * dp4);
243 numyears = totaldays / 365 ;
245 if (numyears == 4) //leap
247 if (what == Which.Year )
248 return num400*400 + num100*100 + num4*4 + numyears + 1;
250 totaldays -= (numyears * 365) ;
251 if (what == Which.DayYear )
252 return totaldays + 1;
254 if ((numyears==3) && ((num100 == 3) || !(num4 == 24)) ) //31 dec leapyear
255 days = daysmonthleap;
257 while (totaldays >= days[M])
258 totaldays -= days[M++];
260 if (what == Which.Month )
270 /// Constructs a DateTime for specified ticks
273 public DateTime (long ticks)
275 this.ticks = new TimeSpan (ticks);
276 if (ticks < MinValue.Ticks || ticks > MaxValue.Ticks) {
277 string msg = Locale.GetText ("Value {0} is outside the valid range [{1},{2}].",
278 ticks, MinValue.Ticks, MaxValue.Ticks);
279 throw new ArgumentOutOfRangeException ("ticks", msg);
282 kind = DateTimeKind.Unspecified;
286 public DateTime (int year, int month, int day)
287 : this (year, month, day,0,0,0,0) {}
289 public DateTime (int year, int month, int day, int hour, int minute, int second)
290 : this (year, month, day, hour, minute, second, 0) {}
292 public DateTime (int year, int month, int day, int hour, int minute, int second, int millisecond)
294 if ( year < 1 || year > 9999 ||
295 month < 1 || month >12 ||
296 day < 1 || day > DaysInMonth(year, month) ||
297 hour < 0 || hour > 23 ||
298 minute < 0 || minute > 59 ||
299 second < 0 || second > 59 ||
300 millisecond < 0 || millisecond > 999)
301 throw new ArgumentOutOfRangeException ("Parameters describe an " +
302 "unrepresentable DateTime.");
304 ticks = new TimeSpan (AbsoluteDays(year,month,day), hour, minute, second, millisecond);
307 kind = DateTimeKind.Unspecified;
311 public DateTime (int year, int month, int day, Calendar calendar)
312 : this (year, month, day, 0, 0, 0, 0, calendar)
316 public DateTime (int year, int month, int day, int hour, int minute, int second, Calendar calendar)
317 : this (year, month, day, hour, minute, second, 0, calendar)
321 public DateTime (int year, int month, int day, int hour, int minute, int second, int millisecond, Calendar calendar)
323 if (calendar == null)
324 throw new ArgumentNullException ("calendar");
325 ticks = calendar.ToDateTime (year, month, day, hour, minute, second, millisecond).ticks;
327 kind = DateTimeKind.Unspecified;
331 internal DateTime (bool check, TimeSpan value)
333 if (check && (value.Ticks < MinValue.Ticks || value.Ticks > MaxValue.Ticks))
334 throw new ArgumentOutOfRangeException ();
339 kind = DateTimeKind.Unspecified;
344 public DateTime (long ticks, DateTimeKind kind) : this (ticks)
346 CheckDateTimeKind (kind);
350 public DateTime (int year, int month, int day, int hour, int minute, int second, DateTimeKind kind)
351 : this (year, month, day, hour, minute, second)
353 CheckDateTimeKind (kind);
357 public DateTime (int year, int month, int day, int hour, int minute, int second, int millisecond, DateTimeKind kind)
358 : this (year, month, day, hour, minute, second, millisecond)
360 CheckDateTimeKind (kind);
364 public DateTime (int year, int month, int day, int hour, int minute, int second, int millisecond, Calendar calendar, DateTimeKind kind)
365 : this (year, month, day, hour, minute, second, millisecond, calendar)
367 CheckDateTimeKind (kind);
378 DateTime ret = new DateTime (Year, Month, Day);
390 return FromTicks(Which.Month);
398 return FromTicks(Which.Day);
402 public DayOfWeek DayOfWeek
406 return ( (DayOfWeek) ((ticks.Days+1) % 7) );
414 return FromTicks(Which.DayYear);
418 public TimeSpan TimeOfDay
422 return new TimeSpan(ticks.Ticks % TimeSpan.TicksPerDay );
439 return ticks.Minutes;
447 return ticks.Seconds;
451 public int Millisecond
455 return ticks.Milliseconds;
459 [MethodImplAttribute(MethodImplOptions.InternalCall)]
460 internal static extern long GetTimeMonotonic ();
462 [MethodImplAttribute(MethodImplOptions.InternalCall)]
463 internal static extern long GetNow ();
466 // To reduce the time consumed by DateTime.Now, we keep
467 // the difference to map the system time into a local
468 // time into `to_local_time_span', we record the timestamp
469 // for this in `last_now'
471 static object to_local_time_span_object;
472 static long last_now;
474 public static DateTime Now
478 long now = GetNow ();
479 DateTime dt = new DateTime (now);
481 if ((now - last_now) > TimeSpan.TicksPerMinute){
482 to_local_time_span_object = TimeZone.CurrentTimeZone.GetLocalTimeDiff (dt);
487 // This is boxed, so we avoid locking.
488 DateTime ret = dt + (TimeSpan) to_local_time_span_object;
490 ret.kind = DateTimeKind.Local;
504 public static DateTime Today
508 DateTime today = new DateTime (now.Year, now.Month, now.Day);
510 today.kind = now.kind;
516 public static DateTime UtcNow
520 return new DateTime (GetNow (), DateTimeKind.Utc);
522 return new DateTime (GetNow ());
531 return FromTicks(Which.Year);
536 public DateTimeKind Kind {
545 public DateTime Add (TimeSpan value)
547 DateTime ret = AddTicks (value.Ticks);
554 public DateTime AddDays (double value)
556 return AddMilliseconds (Math.Round (value * 86400000));
559 public DateTime AddTicks (long value)
561 if ((value + ticks.Ticks) > MAX_VALUE_TICKS || (value + ticks.Ticks) < 0) {
562 throw new ArgumentOutOfRangeException();
564 DateTime ret = new DateTime (value + ticks.Ticks);
571 public DateTime AddHours (double value)
573 return AddMilliseconds (value * 3600000);
576 public DateTime AddMilliseconds (double value)
578 if ((value * TimeSpan.TicksPerMillisecond) > long.MaxValue ||
579 (value * TimeSpan.TicksPerMillisecond) < long.MinValue) {
580 throw new ArgumentOutOfRangeException();
582 long msticks = (long) (value * TimeSpan.TicksPerMillisecond);
584 return AddTicks (msticks);
587 // required to match MS implementation for OADate (OLE Automation)
588 private DateTime AddRoundedMilliseconds (double ms)
590 if ((ms * TimeSpan.TicksPerMillisecond) > long.MaxValue ||
591 (ms * TimeSpan.TicksPerMillisecond) < long.MinValue) {
592 throw new ArgumentOutOfRangeException ();
594 long msticks = (long) (ms += ms > 0 ? 0.5 : -0.5) * TimeSpan.TicksPerMillisecond;
596 return AddTicks (msticks);
599 public DateTime AddMinutes (double value)
601 return AddMilliseconds (value * 60000);
604 public DateTime AddMonths (int months)
606 int day, month, year, maxday ;
610 month = this.Month + (months % 12);
611 year = this.Year + months/12 ;
623 maxday = DaysInMonth(year, month);
627 temp = new DateTime (year, month, day);
631 return temp.Add (this.TimeOfDay);
634 public DateTime AddSeconds (double value)
636 return AddMilliseconds (value * 1000);
639 public DateTime AddYears (int value)
641 return AddMonths (value * 12);
644 public static int Compare (DateTime t1, DateTime t2)
646 if (t1.ticks < t2.ticks)
648 else if (t1.ticks > t2.ticks)
654 public int CompareTo (object value)
659 if (!(value is System.DateTime))
660 throw new ArgumentException (Locale.GetText (
661 "Value is not a System.DateTime"));
663 return Compare (this, (DateTime) value);
667 public bool IsDaylightSavingTime ()
669 if (kind == DateTimeKind.Utc)
671 return TimeZone.CurrentTimeZone.IsDaylightSavingTime (this);
674 public int CompareTo (DateTime value)
676 return Compare (this, value);
679 public bool Equals (DateTime value)
681 return value.ticks == ticks;
684 public long ToBinary ()
687 case DateTimeKind.Utc:
688 return Ticks | 0x4000000000000000;
689 case DateTimeKind.Local:
690 return (long) ((ulong) ToUniversalTime ().Ticks | 0x8000000000000000);
696 public static DateTime FromBinary (long dateData)
698 switch ((ulong)dateData >> 62) {
700 return new DateTime (dateData ^ 0x4000000000000000, DateTimeKind.Utc);
702 return new DateTime (dateData, DateTimeKind.Unspecified);
704 return new DateTime (dateData & 0x3fffffffffffffff, DateTimeKind.Utc).ToLocalTime ();
708 public static DateTime SpecifyKind (DateTime value, DateTimeKind kind)
710 return new DateTime (value.Ticks, kind);
715 internal long ToBinary ()
720 internal static DateTime FromBinary (long dateData)
722 return new DateTime (dateData & 0x3fffffffffffffff);
726 public static int DaysInMonth (int year, int month)
730 if (month < 1 || month >12)
731 throw new ArgumentOutOfRangeException ();
733 if (year < 1 || year > 9999)
734 throw new ArgumentOutOfRangeException ();
736 days = (IsLeapYear(year) ? daysmonthleap : daysmonth);
740 public override bool Equals (object value)
742 if (!(value is System.DateTime))
745 return ((DateTime) value).ticks == ticks;
748 public static bool Equals (DateTime t1, DateTime t2 )
750 return (t1.ticks == t2.ticks );
753 public static DateTime FromFileTime (long fileTime)
756 throw new ArgumentOutOfRangeException ("fileTime", "< 0");
758 return new DateTime (w32file_epoch + fileTime).ToLocalTime ();
762 public static DateTime FromFileTimeUtc (long fileTime)
765 throw new ArgumentOutOfRangeException ("fileTime", "< 0");
767 return new DateTime (w32file_epoch + fileTime);
771 public static DateTime FromOADate (double d)
773 // An OLE Automation date is implemented as a floating-point number
774 // whose value is the number of days from midnight, 30 December 1899.
776 // d must be negative 657435.0 through positive 2958466.0.
777 if ((d <= OAMinValue) || (d >= OAMaxValue))
778 throw new ArgumentException ("d", "[-657435,2958466]");
780 DateTime dt = new DateTime (ticks18991230);
782 Double days = Math.Ceiling (d);
783 // integer part is the number of days (negative)
784 dt = dt.AddRoundedMilliseconds (days * 86400000);
785 // but decimals are the number of hours (in days fractions) and positive
786 Double hours = (days - d);
787 dt = dt.AddRoundedMilliseconds (hours * 86400000);
790 dt = dt.AddRoundedMilliseconds (d * 86400000);
796 public string[] GetDateTimeFormats()
798 return GetDateTimeFormats (CultureInfo.CurrentCulture);
801 public string[] GetDateTimeFormats(char format)
803 if ("dDgGfFmMrRstTuUyY".IndexOf (format) < 0)
804 throw new FormatException ("Invalid format character.");
805 string[] result = new string[1];
806 result[0] = this.ToString(format.ToString());
810 public string[] GetDateTimeFormats(IFormatProvider provider)
812 DateTimeFormatInfo info = (DateTimeFormatInfo) provider.GetFormat (typeof(DateTimeFormatInfo));
813 // return GetDateTimeFormats (info.GetAllDateTimePatterns ());
814 ArrayList al = new ArrayList ();
815 foreach (char c in "dDgGfFmMrRstTuUyY")
816 al.AddRange (GetDateTimeFormats (c, info));
817 return al.ToArray (typeof (string)) as string [];
820 public string[] GetDateTimeFormats(char format,IFormatProvider provider )
822 if ("dDgGfFmMrRstTuUyY".IndexOf (format) < 0)
823 throw new FormatException ("Invalid format character.");
825 // LAMESPEC: There is NO assurance that 'U' ALWAYS
826 // euqals to 'F', but since we have to iterate all
827 // the pattern strings, we cannot just use
828 // ToString("U", provider) here. I believe that the
829 // method's behavior cannot be formalized.
830 bool adjustutc = false;
839 DateTimeFormatInfo info = (DateTimeFormatInfo) provider.GetFormat (typeof(DateTimeFormatInfo));
840 return GetDateTimeFormats (adjustutc, info.GetAllRawDateTimePatterns (format), info);
843 private string [] GetDateTimeFormats (bool adjustutc, string [] patterns, DateTimeFormatInfo dfi)
845 string [] results = new string [patterns.Length];
846 DateTime val = adjustutc ? ToUniversalTime () : this;
847 for (int i = 0; i < results.Length; i++)
848 results [i] = DateTimeUtils.ToString (val, patterns [i], dfi);
853 private void CheckDateTimeKind (DateTimeKind kind) {
854 if ((kind != DateTimeKind.Unspecified) && (kind != DateTimeKind.Utc) && (kind != DateTimeKind.Local))
855 throw new ArgumentException ("Invalid DateTimeKind value.", "kind");
859 public override int GetHashCode ()
861 return (int) ticks.Ticks;
864 public TypeCode GetTypeCode ()
866 return TypeCode.DateTime;
869 public static bool IsLeapYear (int year)
871 if (year < 1 || year > 9999)
872 throw new ArgumentOutOfRangeException ();
873 return ( (year % 4 == 0 && year % 100 != 0) || year % 400 == 0) ;
876 public static DateTime Parse (string s)
878 return Parse (s, null);
881 public static DateTime Parse (string s, IFormatProvider provider)
883 return Parse (s, provider, DateTimeStyles.AllowWhiteSpaces);
886 public static DateTime Parse (string s, IFormatProvider provider, DateTimeStyles styles)
889 throw new ArgumentNullException ("s");
892 Exception exception = null;
893 if (!CoreParse (s, provider, styles, out res, true, ref exception))
899 const string formatExceptionMessage = "String was not recognized as a valid DateTime.";
901 internal static bool CoreParse (string s, IFormatProvider provider, DateTimeStyles styles,
902 out DateTime result, bool setExceptionOnError, ref Exception exception)
904 if (provider == null)
905 provider = CultureInfo.CurrentCulture;
906 DateTimeFormatInfo dfi = DateTimeFormatInfo.GetInstance (provider);
908 // Try first all the combinations of ParseAllDateFormats & ParseTimeFormats
909 string[] allDateFormats = YearMonthDayFormats (dfi, setExceptionOnError, ref exception);
910 if (allDateFormats == null){
915 bool longYear = false;
916 for (int i = 0; i < allDateFormats.Length; i++) {
917 string firstPart = allDateFormats [i];
918 bool incompleteFormat = false;
919 if (_DoParse (s, firstPart, "", false, out result, dfi, styles, true, ref incompleteFormat, ref longYear))
922 if (!incompleteFormat)
925 for (int j = 0; j < ParseTimeFormats.Length; j++) {
926 if (_DoParse (s, firstPart, ParseTimeFormats [j], false, out result, dfi, styles, true, ref incompleteFormat, ref longYear))
934 int dayIndex = dfi.MonthDayPattern.IndexOf('d');
935 int monthIndex = dfi.MonthDayPattern.IndexOf('M');
936 if (dayIndex == -1 || monthIndex == -1){
938 if (setExceptionOnError)
939 exception = new FormatException (Locale.GetText("Order of month and date is not defined by {0}", dfi.MonthDayPattern));
942 bool is_day_before_month = dayIndex < monthIndex;
943 string[] monthDayFormats = is_day_before_month ? DayMonthShortFormats : MonthDayShortFormats;
944 for (int i = 0; i < monthDayFormats.Length; i++) {
945 bool incompleteFormat = false;
946 if (_DoParse (s, monthDayFormats[i], "", false, out result, dfi, styles, true, ref incompleteFormat, ref longYear))
950 for (int j = 0; j < ParseTimeFormats.Length; j++) {
951 string firstPart = ParseTimeFormats [j];
952 bool incompleteFormat = false;
953 if (_DoParse (s, firstPart, "", false, out result, dfi, styles, false, ref incompleteFormat, ref longYear))
955 if (!incompleteFormat)
958 for (int i = 0; i < monthDayFormats.Length; i++) {
959 if (_DoParse (s, firstPart, monthDayFormats [i], false, out result, dfi, styles, false, ref incompleteFormat, ref longYear))
962 for (int i = 0; i < allDateFormats.Length; i++) {
963 string dateFormat = allDateFormats [i];
964 if (dateFormat[dateFormat.Length - 1] == 'T')
965 continue; // T formats must be before the time part
966 if (_DoParse (s, firstPart, dateFormat, false, out result, dfi, styles, false, ref incompleteFormat, ref longYear))
971 // Try as a last resort all the patterns
972 if (ParseExact (s, dfi.GetAllDateTimePatternsInternal (), dfi, styles, out result, false, ref longYear, setExceptionOnError, ref exception))
975 if (!setExceptionOnError)
979 // .NET 2.x does not throw an ArgumentOutOfRangeException, but .NET 1.1 does.
980 exception = new FormatException (formatExceptionMessage);
983 exception = new ArgumentOutOfRangeException ("year", "Valid values are between 1 and 9999, inclusive.");
985 exception = new FormatException (formatExceptionMessage);
990 public static DateTime ParseExact (string s, string format, IFormatProvider provider)
992 return ParseExact (s, format, provider, DateTimeStyles.None);
995 private static string[] YearMonthDayFormats (DateTimeFormatInfo dfi, bool setExceptionOnError, ref Exception exc)
997 int dayIndex = dfi.ShortDatePattern.IndexOf('d');
998 int monthIndex = dfi.ShortDatePattern.IndexOf('M');
999 int yearIndex = dfi.ShortDatePattern.IndexOf('y');
1000 if (dayIndex == -1 || monthIndex == -1 || yearIndex == -1){
1001 if (setExceptionOnError)
1002 exc = new FormatException (Locale.GetText("Order of year, month and date is not defined by {0}", dfi.ShortDatePattern));
1006 if (yearIndex < monthIndex)
1007 if (monthIndex < dayIndex)
1008 return ParseYearMonthDayFormats;
1009 else if (yearIndex < dayIndex)
1010 return ParseYearDayMonthFormats;
1012 // The year cannot be between the date and the month
1013 if (setExceptionOnError)
1014 exc = new FormatException (Locale.GetText("Order of date, year and month defined by {0} is not supported", dfi.ShortDatePattern));
1017 else if (dayIndex < monthIndex)
1018 return ParseDayMonthYearFormats;
1019 else if (dayIndex < yearIndex)
1020 return ParseMonthDayYearFormats;
1022 // The year cannot be between the month and the date
1023 if (setExceptionOnError)
1024 exc = new FormatException (Locale.GetText("Order of month, year and date defined by {0} is not supported", dfi.ShortDatePattern));
1029 private static int _ParseNumber (string s, int valuePos,
1033 bool sloppy_parsing,
1039 leadingzero = false;
1042 int real_digits = 0;
1043 for (i = valuePos; i < s.Length && i < digits + valuePos; i++) {
1044 if (!Char.IsDigit (s[i]))
1050 digits = real_digits;
1052 if (digits < min_digits) {
1057 if (s.Length - valuePos < digits) {
1062 for (i = valuePos; i < digits + valuePos; i++) {
1064 if (!Char.IsDigit (c)) {
1069 number = number * 10 + (byte) (c - '0');
1072 num_parsed = digits;
1076 private static int _ParseEnum (string s, int sPos, string[] values, string[] invValues, bool exact, out int num_parsed)
1078 // FIXME: I know this is somehow lame code. Probably
1079 // it should iterate all the enum value and return
1080 // the longest match. However right now I don't see
1081 // anything but "1" and "10" - "12" that might match
1082 // two or more values. (They are only abbrev month
1083 // names, so do reverse order search). See bug #80094.
1084 for (int i = values.Length - 1; i >= 0; i--) {
1085 if (!exact && invValues [i].Length > values[i].Length) {
1086 if (invValues [i].Length > 0 && _ParseString (s, sPos, 0, invValues [i], out num_parsed))
1088 if (values [i].Length > 0 && _ParseString (s, sPos, 0, values [i], out num_parsed))
1092 if (values [i].Length > 0 && _ParseString (s, sPos, 0, values [i], out num_parsed))
1094 if (!exact && invValues [i].Length > 0 && _ParseString (s, sPos, 0, invValues [i], out num_parsed))
1103 private static bool _ParseString (string s, int sPos, int maxlength, string value, out int num_parsed)
1106 maxlength = value.Length;
1108 if (sPos + maxlength <= s.Length && String.Compare (s, sPos, value, 0, maxlength, true, CultureInfo.InvariantCulture) == 0) {
1109 num_parsed = maxlength;
1117 // Note that in case of Parse (exact == false) we check both for AM/PM
1118 // and the culture spcific AM/PM strings.
1119 private static bool _ParseAmPm(string s,
1122 DateTimeFormatInfo dfi,
1131 if (!IsLetter (s, valuePos)) {
1132 if (dfi.AMDesignator != "")
1139 DateTimeFormatInfo invInfo = DateTimeFormatInfo.InvariantInfo;
1140 if (!exact && _ParseString (s, valuePos, num, invInfo.PMDesignator, out num_parsed) ||
1141 dfi.PMDesignator != "" && _ParseString(s, valuePos, num, dfi.PMDesignator, out num_parsed))
1143 else if (!exact && _ParseString (s, valuePos, num, invInfo.AMDesignator, out num_parsed) ||
1144 _ParseString (s, valuePos, num, dfi.AMDesignator, out num_parsed)) {
1145 if (exact || num_parsed != 0)
1153 // Note that in case of Parse (exact == false) we check both for ':'
1154 // and the culture spcific TimeSperator
1155 private static bool _ParseTimeSeparator (string s, int sPos, DateTimeFormatInfo dfi, bool exact, out int num_parsed)
1157 return _ParseString (s, sPos, 0, dfi.TimeSeparator, out num_parsed) ||
1158 !exact && _ParseString (s, sPos, 0, ":", out num_parsed);
1161 // Accept any character for DateSeparator, except TimeSeparator,
1162 // a digit or a letter.
1163 // Not documented, but seems to be MS behaviour here. See bug 54047.
1164 private static bool _ParseDateSeparator (string s, int sPos, DateTimeFormatInfo dfi, bool exact, out int num_parsed)
1167 if (exact && s [sPos] != '/')
1170 if (_ParseTimeSeparator (s, sPos, dfi, exact, out num_parsed) ||
1171 Char.IsDigit (s [sPos]) || Char.IsLetter (s [sPos]))
1178 private static bool IsLetter (string s, int pos)
1180 return pos < s.Length && Char.IsLetter (s [pos]);
1183 // To implement better DateTime.Parse we use two format strings one
1184 // for Date and one for Time. This allows us to define two different
1185 // arrays of formats for Time and Dates and to combine them more or less
1186 // efficiently. When this mode is used flexibleTwoPartsParsing is true.
1187 private static bool _DoParse (string s,
1191 out DateTime result,
1192 DateTimeFormatInfo dfi,
1193 DateTimeStyles style,
1194 bool firstPartIsDate,
1195 ref bool incompleteFormat,
1198 bool useutc = false;
1199 bool use_invariant = false;
1200 bool sloppy_parsing = false;
1202 bool afterTimePart = firstPartIsDate && secondPart == "";
1204 bool flexibleTwoPartsParsing = !exact && secondPart != null;
1205 incompleteFormat = false;
1207 string format = firstPart;
1208 bool afterTFormat = false;
1209 DateTimeFormatInfo invInfo = DateTimeFormatInfo.InvariantInfo;
1210 if (format.Length == 1)
1211 format = DateTimeUtils.GetStandardPattern (format [0], dfi, out useutc, out use_invariant);
1213 result = new DateTime (0);
1217 if ((style & DateTimeStyles.AllowLeadingWhite) != 0) {
1218 format = format.TrimStart (null);
1220 s = s.TrimStart (null); // it could be optimized, but will make little good.
1223 if ((style & DateTimeStyles.AllowTrailingWhite) != 0) {
1224 format = format.TrimEnd (null);
1225 s = s.TrimEnd (null); // it could be optimized, but will make little good.
1231 if ((style & DateTimeStyles.AllowInnerWhite) != 0)
1232 sloppy_parsing = true;
1234 string chars = format;
1235 int len = format.Length, pos = 0, num = 0;
1239 int day = -1, dayofweek = -1, month = -1, year = -1;
1240 int hour = -1, minute = -1, second = -1;
1241 double fractionalSeconds = -1;
1243 int tzsign = -1, tzoffset = -1, tzoffmin = -1;
1244 bool isFirstPart = true;
1248 if (valuePos == s.Length)
1252 if (flexibleTwoPartsParsing && pos + num == 0)
1254 bool isLetter = IsLetter(s, valuePos);
1258 if (afterTimePart && isLetter) {
1260 if (s [valuePos] == 'Z')
1263 _ParseString (s, valuePos, 0, "GMT", out num_parsed);
1264 if (num_parsed > 0 && !IsLetter (s, valuePos + num_parsed)) {
1265 valuePos += num_parsed;
1270 if (!afterTFormat && _ParseAmPm (s, valuePos, 0, dfi, exact, out num_parsed, ref ampm)) {
1271 if (IsLetter (s, valuePos + num_parsed))
1273 else if (num_parsed > 0) {
1274 valuePos += num_parsed;
1279 if (!afterTFormat && dayofweek == -1 && isLetter) {
1280 dayofweek = _ParseEnum (s, valuePos, dfi.RawDayNames, invInfo.RawDayNames, exact, out num_parsed);
1281 if (dayofweek == -1)
1282 dayofweek = _ParseEnum (s, valuePos, dfi.RawAbbreviatedDayNames, invInfo.RawAbbreviatedDayNames, exact, out num_parsed);
1283 if (dayofweek != -1 && !IsLetter (s, valuePos + num_parsed)) {
1284 valuePos += num_parsed;
1291 if (char.IsWhiteSpace (s [valuePos]) || s [valuePos] == ',') {
1298 if (pos + num >= len)
1300 if (flexibleTwoPartsParsing && num == 0) {
1301 afterTFormat = isFirstPart && firstPart [firstPart.Length - 1] == 'T';
1302 if (!isFirstPart && format == "")
1307 format = secondPart;
1312 isFirstPart = false;
1314 if (!firstPartIsDate || format == "")
1315 afterTimePart = true;
1322 bool leading_zeros = true;
1324 if (chars[pos] == '\'') {
1326 while (pos+num < len) {
1327 if (chars[pos+num] == '\'')
1330 if (valuePos == s.Length || s [valuePos] != chars [pos + num])
1340 } else if (chars[pos] == '"') {
1342 while (pos+num < len) {
1343 if (chars[pos+num] == '"')
1346 if (valuePos == s.Length || s [valuePos] != chars[pos+num])
1356 } else if (chars[pos] == '\\') {
1361 if (s [valuePos] != chars [pos])
1367 } else if (chars[pos] == '%') {
1370 } else if (char.IsWhiteSpace (s [valuePos]) ||
1371 s [valuePos] == ',' && (!exact && chars [pos] == '/' || Char.IsWhiteSpace (chars [pos]))) {
1374 if (exact && (style & DateTimeStyles.AllowInnerWhite) == 0) {
1375 if (!Char.IsWhiteSpace (chars[pos]))
1382 while (ws < s.Length) {
1383 if (Char.IsWhiteSpace (s [ws]) || s [ws] == ',')
1390 while (ws < chars.Length) {
1391 if (Char.IsWhiteSpace (chars [ws]) || chars [ws] == ',')
1397 // A whitespace may match a '/' in the pattern.
1398 if (!exact && pos < chars.Length && chars[pos] == '/')
1399 if (!_ParseDateSeparator (s, valuePos, dfi, exact, out num_parsed))
1404 if ((pos+num+1 < len) && (chars[pos+num+1] == chars[pos+num])) {
1412 if (num < 2 && day != -1 || num >= 2 && dayofweek != -1)
1415 day = _ParseNumber (s, valuePos, 1, 2, false, sloppy_parsing, out num_parsed);
1417 day = _ParseNumber (s, valuePos, 1, 2, true, sloppy_parsing, out num_parsed);
1419 dayofweek = _ParseEnum (s, valuePos, dfi.RawAbbreviatedDayNames, invInfo.RawAbbreviatedDayNames, exact, out num_parsed);
1421 dayofweek = _ParseEnum (s, valuePos, dfi.RawDayNames, invInfo.RawDayNames, exact, out num_parsed);
1427 if (flexibleTwoPartsParsing) {
1429 if (num == 0 || num == 3)
1430 month = _ParseNumber (s, valuePos, 1, 2, false, sloppy_parsing, out num_parsed);
1431 if (num > 1 && num_parsed == -1)
1432 month = _ParseEnum (s, valuePos, dfi.RawMonthNames, invInfo.RawMonthNames, exact, out num_parsed) + 1;
1433 if (num > 1 && num_parsed == -1)
1434 month = _ParseEnum (s, valuePos, dfi.RawAbbreviatedMonthNames, invInfo.RawAbbreviatedMonthNames, exact, out num_parsed) + 1;
1439 month = _ParseNumber (s, valuePos, 1, 2, false, sloppy_parsing, out num_parsed);
1441 month = _ParseNumber (s, valuePos, 1, 2, true, sloppy_parsing, out num_parsed);
1443 month = _ParseEnum (s, valuePos, dfi.RawAbbreviatedMonthNames, invInfo.RawAbbreviatedMonthNames, exact, out num_parsed) + 1;
1445 month = _ParseEnum (s, valuePos, dfi.RawMonthNames, invInfo.RawMonthNames, exact, out num_parsed) + 1;
1452 year = _ParseNumber (s, valuePos, 1, 2, false, sloppy_parsing, out num_parsed);
1453 } else if (num < 3) {
1454 year = _ParseNumber (s, valuePos, 1, 2, true, sloppy_parsing, out num_parsed);
1456 year = _ParseNumber (s, valuePos, exact ? 4 : 3, 4, false, sloppy_parsing, out num_parsed);
1457 if ((year >= 1000) && (num_parsed == 4) && (!longYear) && (s.Length > 4 + valuePos)) {
1459 int ly = _ParseNumber (s, valuePos, 5, 5, false, sloppy_parsing, out np);
1460 longYear = (ly > 9999);
1465 //FIXME: We should do use dfi.Calendat.TwoDigitYearMax
1466 if (num_parsed <= 2)
1467 year += (year < 30) ? 2000 : 1900;
1473 hour = _ParseNumber (s, valuePos, 1, 2, false, sloppy_parsing, out num_parsed);
1475 hour = _ParseNumber (s, valuePos, 1, 2, true, sloppy_parsing, out num_parsed);
1484 if (hour != -1 || !flexibleTwoPartsParsing && ampm >= 0)
1487 hour = _ParseNumber (s, valuePos, 1, 2, false, sloppy_parsing, out num_parsed);
1489 hour = _ParseNumber (s, valuePos, 1, 2, true, sloppy_parsing, out num_parsed);
1500 minute = _ParseNumber (s, valuePos, 1, 2, false, sloppy_parsing, out num_parsed);
1502 minute = _ParseNumber (s, valuePos, 1, 2, true, sloppy_parsing, out num_parsed);
1512 second = _ParseNumber (s, valuePos, 1, 2, false, sloppy_parsing, out num_parsed);
1514 second = _ParseNumber (s, valuePos, 1, 2, true, sloppy_parsing, out num_parsed);
1522 leading_zeros = false;
1526 if (num > 6 || fractionalSeconds != -1)
1528 double decimalNumber = (double) _ParseNumber (s, valuePos, 0, num+1, leading_zeros, sloppy_parsing, out num_parsed);
1529 if (num_parsed == -1)
1531 fractionalSeconds = decimalNumber / Math.Pow(10.0, num_parsed);
1534 if (!_ParseAmPm (s, valuePos, num > 0 ? 0 : 1, dfi, exact, out num_parsed, ref ampm))
1541 if (s [valuePos] == '+')
1543 else if (s [valuePos] == '-')
1550 tzoffset = _ParseNumber (s, valuePos, 1, 2, false, sloppy_parsing, out num_parsed);
1552 tzoffset = _ParseNumber (s, valuePos, 1, 2, true, sloppy_parsing, out num_parsed);
1554 tzoffset = _ParseNumber (s, valuePos, 1, 2, true, /*sloppy_parsing*/true, out num_parsed);
1555 valuePos += num_parsed;
1560 if (valuePos < s.Length && Char.IsDigit (s [valuePos]) ||
1561 _ParseTimeSeparator (s, valuePos, dfi, exact, out num_parsed)) {
1562 valuePos += num_parsed;
1563 tzoffmin = _ParseNumber (s, valuePos, 1, 2, true, sloppy_parsing, out num_parsed);
1567 else if (!flexibleTwoPartsParsing)
1575 if (s [valuePos] == 'Z') {
1579 else if (s [valuePos] == '+' || s [valuePos] == '-') {
1582 if (s [valuePos] == '+')
1584 else if (s [valuePos] == '-')
1589 tzoffset = _ParseNumber (s, valuePos, 0, 2, true, sloppy_parsing, out num_parsed);
1590 valuePos += num_parsed;
1594 if (Char.IsDigit (s [valuePos]))
1596 else if (!_ParseString (s, valuePos, 0, dfi.TimeSeparator, out num_parsed))
1598 valuePos += num_parsed;
1600 tzoffmin = _ParseNumber (s, valuePos, 0, 2, true, sloppy_parsing, out num_parsed);
1607 // LAMESPEC: This should be part of UTCpattern
1608 // string and thus should not be considered here.
1610 // Note that 'Z' is not defined as a pattern
1611 // character. Keep it for X509 certificate
1612 // verification. Also, "Z" != "'Z'" under MS.NET
1613 // ("'Z'" is just literal; handled above)
1615 if (s [valuePos] != 'Z')
1622 if (s [valuePos] != 'G')
1625 if ((pos + 2 < len) && (valuePos + 2 < s.Length) &&
1626 (chars [pos + 1] == 'M') && (s[valuePos + 1] == 'M') &&
1627 (chars [pos + 2] == 'T') && (s[valuePos + 2] == 'T'))
1639 if (!_ParseTimeSeparator (s, valuePos, dfi, exact, out num_parsed))
1643 if (!_ParseDateSeparator (s, valuePos, dfi, exact, out num_parsed))
1649 if (s [valuePos] != chars [pos])
1660 valuePos += num_parsed;
1662 if (!exact && !flexibleTwoPartsParsing) {
1663 switch (chars [pos]) {
1671 if (s.Length > valuePos && s [valuePos] == 'Z' &&
1672 (pos + 1 == chars.Length || chars [pos + 1] != 'Z')) {
1680 pos = pos + num + 1;
1685 if (pos + 1 < len && chars [pos] == '.' && chars [pos + 1] == 'F') {
1687 while (pos < len && chars [pos] == 'F') // '.FFF....' can be mapped to nothing. See bug #444103
1690 while (pos < len && chars [pos] == 'K') // 'K' can be mapped to nothing
1696 if (s.Length > valuePos) // extraneous tail.
1701 if (Char.IsDigit (s [valuePos]) && Char.IsDigit (s [valuePos - 1]))
1703 if (Char.IsLetter (s [valuePos]) && Char.IsLetter (s [valuePos - 1]))
1705 incompleteFormat = true;
1716 if (fractionalSeconds == -1)
1717 fractionalSeconds = 0;
1719 // If no date was given
1720 if ((day == -1) && (month == -1) && (year == -1)) {
1721 if ((style & DateTimeStyles.NoCurrentDateDefault) != 0) {
1726 day = DateTime.Today.Day;
1727 month = DateTime.Today.Month;
1728 year = DateTime.Today.Year;
1737 if ((style & DateTimeStyles.NoCurrentDateDefault) != 0)
1740 year = DateTime.Today.Year;
1743 if (ampm == 0 && hour == 12)
1746 if (ampm == 1 && (!flexibleTwoPartsParsing || hour < 12))
1749 // For anything out of range
1751 if (year < 1 || year > 9999 ||
1752 month < 1 || month >12 ||
1753 day < 1 || day > DateTime.DaysInMonth(year, month) ||
1754 hour < 0 || hour > 23 ||
1755 minute < 0 || minute > 59 ||
1756 second < 0 || second > 59)
1759 result = new DateTime (year, month, day, hour, minute, second, 0);
1760 result = result.AddSeconds(fractionalSeconds);
1762 if (dayofweek != -1 && dayofweek != (int) result.DayOfWeek)
1767 bool adjustToUniversal = (style & DateTimeStyles.AdjustToUniversal) != 0;
1775 tzoffset = -tzoffset;
1777 utcoffset = new TimeSpan (tzoffset, tzoffmin, 0);
1778 long newticks = (result.ticks - utcoffset).Ticks;
1780 newticks += TimeSpan.TicksPerDay;
1781 result = new DateTime (false, new TimeSpan (newticks));
1783 result.kind = DateTimeKind.Utc;
1784 if ((style & DateTimeStyles.RoundtripKind) != 0)
1785 result = result.ToLocalTime ();
1789 else if (useutc || ((style & DateTimeStyles.AssumeUniversal) != 0))
1790 result.kind = DateTimeKind.Utc;
1791 else if ((style & DateTimeStyles.AssumeLocal) != 0)
1792 result.kind = DateTimeKind.Local;
1794 bool adjustToLocal = !adjustToUniversal && (style & DateTimeStyles.RoundtripKind) == 0;
1795 if (result.kind != DateTimeKind.Unspecified)
1797 if (adjustToUniversal)
1798 result = result.ToUniversalTime ();
1799 else if (adjustToLocal)
1800 result = result.ToLocalTime ();
1803 if (!adjustToUniversal && (useutc || tzsign != -1))
1804 result = result.ToLocalTime ();
1809 public static DateTime ParseExact (string s, string format,
1810 IFormatProvider provider, DateTimeStyles style)
1813 throw new ArgumentNullException ("format");
1815 string [] formats = new string [1];
1816 formats[0] = format;
1818 return ParseExact (s, formats, provider, style);
1821 public static DateTime ParseExact (string s, string[] formats,
1822 IFormatProvider provider,
1823 DateTimeStyles style)
1825 DateTimeFormatInfo dfi = DateTimeFormatInfo.GetInstance (provider);
1830 throw new ArgumentNullException ("s");
1831 if (formats == null)
1832 throw new ArgumentNullException ("formats");
1833 if (formats.Length == 0)
1834 throw new FormatException ("Format specifier was invalid.");
1837 bool longYear = false;
1839 if (!ParseExact (s, formats, dfi, style, out result, true, ref longYear, true, ref e))
1845 private static void CheckStyle (DateTimeStyles style)
1847 if ( (style & DateTimeStyles.RoundtripKind) != 0)
1849 if ((style & DateTimeStyles.AdjustToUniversal) != 0 || (style & DateTimeStyles.AssumeLocal) != 0 ||
1850 (style & DateTimeStyles.AssumeUniversal) != 0)
1851 throw new ArgumentException ("The DateTimeStyles value RoundtripKind cannot be used with the values AssumeLocal, Asersal or AdjustToUniversal.", "style");
1853 if ((style & DateTimeStyles.AssumeUniversal) != 0 && (style & DateTimeStyles.AssumeLocal) != 0)
1854 throw new ArgumentException ("The DateTimeStyles values AssumeLocal and AssumeUniversal cannot be used together.", "style");
1857 public static bool TryParse (string s, out DateTime result)
1861 Exception exception = null;
1863 return CoreParse (s, null, DateTimeStyles.AllowWhiteSpaces, out result, false, ref exception);
1870 public static bool TryParse (string s, IFormatProvider provider, DateTimeStyles styles, out DateTime result)
1874 Exception exception = null;
1876 return CoreParse (s, provider, styles, out result, false, ref exception);
1883 public static bool TryParseExact (string s, string format,
1884 IFormatProvider provider,
1885 DateTimeStyles style,
1886 out DateTime result)
1889 formats = new string [1];
1890 formats[0] = format;
1892 return TryParseExact (s, formats, provider, style, out result);
1895 public static bool TryParseExact (string s, string[] formats,
1896 IFormatProvider provider,
1897 DateTimeStyles style,
1898 out DateTime result)
1900 DateTimeFormatInfo dfi = DateTimeFormatInfo.GetInstance (provider);
1902 bool longYear = false;
1904 return ParseExact (s, formats, dfi, style, out result, true, ref longYear, false, ref e);
1908 private static bool ParseExact (string s, string [] formats,
1909 DateTimeFormatInfo dfi, DateTimeStyles style, out DateTime ret,
1910 bool exact, ref bool longYear,
1911 bool setExceptionOnError, ref Exception exception)
1914 bool incompleteFormat = false;
1915 for (i = 0; i < formats.Length; i++)
1918 string format = formats[i];
1919 if (format == null || format == String.Empty)
1922 if (_DoParse (s, formats[i], null, exact, out result, dfi, style, false, ref incompleteFormat, ref longYear)) {
1928 if (setExceptionOnError)
1929 exception = new FormatException ("Invalid format string");
1930 ret = DateTime.MinValue;
1934 public TimeSpan Subtract (DateTime value)
1936 return new TimeSpan (ticks.Ticks) - value.ticks;
1939 public DateTime Subtract(TimeSpan value)
1943 newticks = (new TimeSpan (ticks.Ticks)) - value;
1944 DateTime ret = new DateTime (true,newticks);
1951 public long ToFileTime()
1953 DateTime universalTime = ToUniversalTime();
1955 if (universalTime.Ticks < w32file_epoch) {
1956 throw new ArgumentOutOfRangeException("file time is not valid");
1959 return(universalTime.Ticks - w32file_epoch);
1963 public long ToFileTimeUtc()
1965 if (Ticks < w32file_epoch) {
1966 throw new ArgumentOutOfRangeException("file time is not valid");
1969 return (Ticks - w32file_epoch);
1973 public string ToLongDateString()
1975 return ToString ("D");
1978 public string ToLongTimeString()
1980 return ToString ("T");
1983 public double ToOADate ()
1985 long t = this.Ticks;
1986 // uninitialized DateTime case
1989 // we can't reach minimum value
1990 if (t < 31242239136000000)
1991 return OAMinValue + 0.001;
1993 TimeSpan ts = new TimeSpan (this.Ticks - ticks18991230);
1994 double result = ts.TotalDays;
1995 // t < 0 (where 599264352000000000 == 0.0d for OA)
1996 if (t < 599264352000000000) {
1997 // negative days (int) but decimals are positive
1998 double d = Math.Ceiling (result);
1999 result = d - 2 - (result - d);
2002 // we can't reach maximum value
2003 if (result >= OAMaxValue)
2004 result = OAMaxValue - 0.00000001d;
2009 public string ToShortDateString()
2011 return ToString ("d");
2014 public string ToShortTimeString()
2016 return ToString ("t");
2019 public override string ToString ()
2021 return ToString ("G", null);
2024 public string ToString (IFormatProvider provider)
2026 return ToString (null, provider);
2029 public string ToString (string format)
2031 return ToString (format, null);
2034 public string ToString (string format, IFormatProvider provider)
2036 DateTimeFormatInfo dfi = DateTimeFormatInfo.GetInstance (provider);
2038 if (format == null || format == String.Empty)
2041 bool useutc = false, use_invariant = false;
2043 if (format.Length == 1) {
2044 char fchar = format [0];
2045 format = DateTimeUtils.GetStandardPattern (fchar, dfi, out useutc, out use_invariant);
2047 return DateTimeUtils.ToString (ToUniversalTime (), format, dfi);
2048 // return ToUniversalTime()._ToString (format, dfi);
2051 throw new FormatException ("format is not one of the format specifier characters defined for DateTimeFormatInfo");
2054 // Don't convert UTC value. It just adds 'Z' for
2055 // 'u' format, for the same ticks.
2056 return DateTimeUtils.ToString (this, format, dfi);
2059 public DateTime ToLocalTime ()
2061 return TimeZone.CurrentTimeZone.ToLocalTime (this);
2064 public DateTime ToUniversalTime()
2066 return TimeZone.CurrentTimeZone.ToUniversalTime (this);
2071 public static DateTime operator +(DateTime d, TimeSpan t)
2073 DateTime ret = new DateTime (true, d.ticks + t);
2080 public static bool operator ==(DateTime d1, DateTime d2)
2082 return (d1.ticks == d2.ticks);
2085 public static bool operator >(DateTime t1,DateTime t2)
2087 return (t1.ticks > t2.ticks);
2090 public static bool operator >=(DateTime t1,DateTime t2)
2092 return (t1.ticks >= t2.ticks);
2095 public static bool operator !=(DateTime d1, DateTime d2)
2097 return (d1.ticks != d2.ticks);
2100 public static bool operator <(DateTime t1, DateTime t2)
2102 return (t1.ticks < t2.ticks );
2105 public static bool operator <=(DateTime t1,DateTime t2)
2107 return (t1.ticks <= t2.ticks);
2110 public static TimeSpan operator -(DateTime d1,DateTime d2)
2112 return new TimeSpan((d1.ticks - d2.ticks).Ticks);
2115 public static DateTime operator -(DateTime d,TimeSpan t)
2117 DateTime ret = new DateTime (true, d.ticks - t);
2124 bool IConvertible.ToBoolean(IFormatProvider provider)
2126 throw new InvalidCastException();
2129 byte IConvertible.ToByte(IFormatProvider provider)
2131 throw new InvalidCastException();
2135 char IConvertible.ToChar(IFormatProvider provider)
2137 throw new InvalidCastException();
2140 System.DateTime IConvertible.ToDateTime(IFormatProvider provider)
2145 decimal IConvertible.ToDecimal(IFormatProvider provider)
2147 throw new InvalidCastException();
2150 double IConvertible.ToDouble(IFormatProvider provider)
2152 throw new InvalidCastException();
2155 Int16 IConvertible.ToInt16(IFormatProvider provider)
2157 throw new InvalidCastException();
2160 Int32 IConvertible.ToInt32(IFormatProvider provider)
2162 throw new InvalidCastException();
2165 Int64 IConvertible.ToInt64(IFormatProvider provider)
2167 throw new InvalidCastException();
2171 #pragma warning disable 3019
2172 [CLSCompliant (false)]
2174 SByte IConvertible.ToSByte(IFormatProvider provider)
2176 throw new InvalidCastException();
2179 #pragma warning restore 3019
2182 Single IConvertible.ToSingle(IFormatProvider provider)
2184 throw new InvalidCastException();
2187 object IConvertible.ToType (Type type, IFormatProvider provider)
2190 throw new ArgumentNullException ("type");
2192 if (type == typeof (DateTime))
2194 else if (type == typeof (String))
2195 return this.ToString (provider);
2196 else if (type == typeof (Object))
2199 throw new InvalidCastException();
2203 #pragma warning disable 3019
2204 [CLSCompliant (false)]
2206 UInt16 IConvertible.ToUInt16(IFormatProvider provider)
2208 throw new InvalidCastException();
2211 #pragma warning restore 3019
2215 #pragma warning disable 3019
2216 [CLSCompliant (false)]
2218 UInt32 IConvertible.ToUInt32(IFormatProvider provider)
2220 throw new InvalidCastException();
2223 #pragma warning restore 3019
2227 #pragma warning disable 3019
2228 [CLSCompliant (false)]
2230 UInt64 IConvertible.ToUInt64(IFormatProvider provider)
2232 throw new InvalidCastException();
2235 #pragma warning restore 3019