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 GetNow ();
463 // To reduce the time consumed by DateTime.Now, we keep
464 // the difference to map the system time into a local
465 // time into `to_local_time_span', we record the timestamp
466 // for this in `last_now'
468 static object to_local_time_span_object;
469 static long last_now;
471 public static DateTime Now
475 long now = GetNow ();
476 DateTime dt = new DateTime (now);
478 if ((now - last_now) > TimeSpan.TicksPerMinute){
479 to_local_time_span_object = TimeZone.CurrentTimeZone.GetLocalTimeDiff (dt);
484 // This is boxed, so we avoid locking.
485 DateTime ret = dt + (TimeSpan) to_local_time_span_object;
487 ret.kind = DateTimeKind.Local;
501 public static DateTime Today
505 DateTime today = new DateTime (now.Year, now.Month, now.Day);
507 today.kind = now.kind;
513 public static DateTime UtcNow
517 return new DateTime (GetNow (), DateTimeKind.Utc);
519 return new DateTime (GetNow ());
528 return FromTicks(Which.Year);
533 public DateTimeKind Kind {
542 public DateTime Add (TimeSpan ts)
544 DateTime ret = AddTicks (ts.Ticks);
551 public DateTime AddDays (double days)
553 return AddMilliseconds (Math.Round (days * 86400000));
556 public DateTime AddTicks (long t)
558 if ((t + ticks.Ticks) > MAX_VALUE_TICKS || (t + ticks.Ticks) < 0) {
559 throw new ArgumentOutOfRangeException();
561 DateTime ret = new DateTime (t + ticks.Ticks);
568 public DateTime AddHours (double hours)
570 return AddMilliseconds (hours * 3600000);
573 public DateTime AddMilliseconds (double ms)
575 if ((ms * TimeSpan.TicksPerMillisecond) > long.MaxValue ||
576 (ms * TimeSpan.TicksPerMillisecond) < long.MinValue) {
577 throw new ArgumentOutOfRangeException();
579 long msticks = (long) (ms * TimeSpan.TicksPerMillisecond);
581 return AddTicks (msticks);
584 // required to match MS implementation for OADate (OLE Automation)
585 private DateTime AddRoundedMilliseconds (double ms)
587 if ((ms * TimeSpan.TicksPerMillisecond) > long.MaxValue ||
588 (ms * TimeSpan.TicksPerMillisecond) < long.MinValue) {
589 throw new ArgumentOutOfRangeException ();
591 long msticks = (long) (ms += ms > 0 ? 0.5 : -0.5) * TimeSpan.TicksPerMillisecond;
593 return AddTicks (msticks);
596 public DateTime AddMinutes (double minutes)
598 return AddMilliseconds (minutes * 60000);
601 public DateTime AddMonths (int months)
603 int day, month, year, maxday ;
607 month = this.Month + (months % 12);
608 year = this.Year + months/12 ;
620 maxday = DaysInMonth(year, month);
624 temp = new DateTime (year, month, day);
628 return temp.Add (this.TimeOfDay);
631 public DateTime AddSeconds (double seconds)
633 return AddMilliseconds (seconds*1000);
636 public DateTime AddYears (int years )
638 return AddMonths(years * 12);
641 public static int Compare (DateTime t1, DateTime t2)
643 if (t1.ticks < t2.ticks)
645 else if (t1.ticks > t2.ticks)
651 public int CompareTo (object v)
656 if (!(v is System.DateTime))
657 throw new ArgumentException (Locale.GetText (
658 "Value is not a System.DateTime"));
660 return Compare (this, (DateTime) v);
664 public bool IsDaylightSavingTime ()
666 if (kind == DateTimeKind.Utc)
668 return TimeZone.CurrentTimeZone.IsDaylightSavingTime (this);
671 public int CompareTo (DateTime value)
673 return Compare (this, value);
676 public bool Equals (DateTime value)
678 return value.ticks == ticks;
681 public long ToBinary ()
684 case DateTimeKind.Utc:
685 return Ticks | 0x4000000000000000;
686 case DateTimeKind.Local:
687 return (long) ((ulong) ToUniversalTime ().Ticks | 0x8000000000000000);
693 public static DateTime FromBinary (long dateData)
695 switch ((ulong)dateData >> 62) {
697 return new DateTime (dateData ^ 0x4000000000000000, DateTimeKind.Utc);
699 return new DateTime (dateData, DateTimeKind.Unspecified);
701 return new DateTime (dateData & 0x3fffffffffffffff, DateTimeKind.Utc).ToLocalTime ();
705 public static DateTime SpecifyKind (DateTime value, DateTimeKind kind)
707 return new DateTime (value.Ticks, kind);
712 internal long ToBinary ()
717 internal static DateTime FromBinary (long dateData)
719 return new DateTime (dateData & 0x3fffffffffffffff);
723 public static int DaysInMonth (int year, int month)
727 if (month < 1 || month >12)
728 throw new ArgumentOutOfRangeException ();
730 if (year < 1 || year > 9999)
731 throw new ArgumentOutOfRangeException ();
733 days = (IsLeapYear(year) ? daysmonthleap : daysmonth);
737 public override bool Equals (object o)
739 if (!(o is System.DateTime))
742 return ((DateTime) o).ticks == ticks;
745 public static bool Equals (DateTime t1, DateTime t2 )
747 return (t1.ticks == t2.ticks );
750 public static DateTime FromFileTime (long fileTime)
753 throw new ArgumentOutOfRangeException ("fileTime", "< 0");
755 return new DateTime (w32file_epoch + fileTime).ToLocalTime ();
759 public static DateTime FromFileTimeUtc (long fileTime)
762 throw new ArgumentOutOfRangeException ("fileTime", "< 0");
764 return new DateTime (w32file_epoch + fileTime);
768 public static DateTime FromOADate (double d)
770 // An OLE Automation date is implemented as a floating-point number
771 // whose value is the number of days from midnight, 30 December 1899.
773 // d must be negative 657435.0 through positive 2958466.0.
774 if ((d <= OAMinValue) || (d >= OAMaxValue))
775 throw new ArgumentException ("d", "[-657435,2958466]");
777 DateTime dt = new DateTime (ticks18991230);
779 Double days = Math.Ceiling (d);
780 // integer part is the number of days (negative)
781 dt = dt.AddRoundedMilliseconds (days * 86400000);
782 // but decimals are the number of hours (in days fractions) and positive
783 Double hours = (days - d);
784 dt = dt.AddRoundedMilliseconds (hours * 86400000);
787 dt = dt.AddRoundedMilliseconds (d * 86400000);
793 public string[] GetDateTimeFormats()
795 return GetDateTimeFormats (CultureInfo.CurrentCulture);
798 public string[] GetDateTimeFormats(char format)
800 if ("dDgGfFmMrRstTuUyY".IndexOf (format) < 0)
801 throw new FormatException ("Invalid format character.");
802 string[] result = new string[1];
803 result[0] = this.ToString(format.ToString());
807 public string[] GetDateTimeFormats(IFormatProvider provider)
809 DateTimeFormatInfo info = (DateTimeFormatInfo) provider.GetFormat (typeof(DateTimeFormatInfo));
810 // return GetDateTimeFormats (info.GetAllDateTimePatterns ());
811 ArrayList al = new ArrayList ();
812 foreach (char c in "dDgGfFmMrRstTuUyY")
813 al.AddRange (GetDateTimeFormats (c, info));
814 return al.ToArray (typeof (string)) as string [];
817 public string[] GetDateTimeFormats(char format,IFormatProvider provider )
819 if ("dDgGfFmMrRstTuUyY".IndexOf (format) < 0)
820 throw new FormatException ("Invalid format character.");
822 // LAMESPEC: There is NO assurance that 'U' ALWAYS
823 // euqals to 'F', but since we have to iterate all
824 // the pattern strings, we cannot just use
825 // ToString("U", provider) here. I believe that the
826 // method's behavior cannot be formalized.
827 bool adjustutc = false;
836 DateTimeFormatInfo info = (DateTimeFormatInfo) provider.GetFormat (typeof(DateTimeFormatInfo));
837 return GetDateTimeFormats (adjustutc, info.GetAllRawDateTimePatterns (format), info);
840 private string [] GetDateTimeFormats (bool adjustutc, string [] patterns, DateTimeFormatInfo dfi)
842 string [] results = new string [patterns.Length];
843 DateTime val = adjustutc ? ToUniversalTime () : this;
844 for (int i = 0; i < results.Length; i++)
845 results [i] = DateTimeUtils.ToString (val, patterns [i], dfi);
850 private void CheckDateTimeKind (DateTimeKind kind) {
851 if ((kind != DateTimeKind.Unspecified) && (kind != DateTimeKind.Utc) && (kind != DateTimeKind.Local))
852 throw new ArgumentException ("Invalid DateTimeKind value.", "kind");
856 public override int GetHashCode ()
858 return (int) ticks.Ticks;
861 public TypeCode GetTypeCode ()
863 return TypeCode.DateTime;
866 public static bool IsLeapYear (int year)
868 if (year < 1 || year > 9999)
869 throw new ArgumentOutOfRangeException ();
870 return ( (year % 4 == 0 && year % 100 != 0) || year % 400 == 0) ;
873 public static DateTime Parse (string s)
875 return Parse (s, null);
878 public static DateTime Parse (string s, IFormatProvider fp)
880 return Parse (s, fp, DateTimeStyles.AllowWhiteSpaces);
883 public static DateTime Parse (string s, IFormatProvider fp, DateTimeStyles styles)
886 const string formatExceptionMessage = "String was not recognized as a valid DateTime.";
888 const string argumentYearRangeExceptionMessage = "Valid values are between 1 and 9999, inclusive.";
892 throw new ArgumentNullException (Locale.GetText ("s is null"));
894 fp = CultureInfo.CurrentCulture;
895 DateTimeFormatInfo dfi = DateTimeFormatInfo.GetInstance (fp);
897 bool longYear = false;
899 // Try first all the combinations of ParseAllDateFormats & ParseTimeFormats
900 string[] allDateFormats = YearMonthDayFormats (dfi);
901 for (int i = 0; i < allDateFormats.Length; i++) {
902 string firstPart = allDateFormats [i];
903 bool incompleteFormat = false;
904 if (_DoParse (s, firstPart, "", false, out result, dfi, styles, true, ref incompleteFormat, ref longYear))
906 if (!incompleteFormat)
909 for (int j = 0; j < ParseTimeFormats.Length; j++) {
910 if (_DoParse (s, firstPart, ParseTimeFormats [j], false, out result, dfi, styles, true, ref incompleteFormat, ref longYear))
914 string[] monthDayFormats = IsDayBeforeMonth (dfi) ? DayMonthShortFormats : MonthDayShortFormats;
915 for (int i = 0; i < monthDayFormats.Length; i++) {
916 bool incompleteFormat = false;
917 if (_DoParse (s, monthDayFormats[i], "", false, out result, dfi, styles, true, ref incompleteFormat, ref longYear))
920 for (int j = 0; j < ParseTimeFormats.Length; j++) {
921 string firstPart = ParseTimeFormats [j];
922 bool incompleteFormat = false;
923 if (_DoParse (s, firstPart, "", false, out result, dfi, styles, false, ref incompleteFormat, ref longYear))
925 if (!incompleteFormat)
928 for (int i = 0; i < monthDayFormats.Length; i++) {
929 if (_DoParse (s, firstPart, monthDayFormats [i], false, out result, dfi, styles, false, ref incompleteFormat, ref longYear))
932 for (int i = 0; i < allDateFormats.Length; i++) {
933 string dateFormat = allDateFormats [i];
934 if (dateFormat[dateFormat.Length - 1] == 'T')
935 continue; // T formats must be before the time part
936 if (_DoParse (s, firstPart, dateFormat, false, out result, dfi, styles, false, ref incompleteFormat, ref longYear))
941 // Try as a last resort all the patterns
942 if (ParseExact (s, dfi.GetAllDateTimePatternsInternal (), dfi, styles, out result, false, ref longYear))
946 // .NET does not throw an ArgumentOutOfRangeException, but .NET 1.1 does.
947 throw new FormatException (formatExceptionMessage);
950 throw new ArgumentOutOfRangeException ("year",
951 argumentYearRangeExceptionMessage);
954 throw new FormatException (formatExceptionMessage);
958 public static DateTime ParseExact (string s, string format, IFormatProvider fp)
960 return ParseExact (s, format, fp, DateTimeStyles.None);
963 private static bool IsDayBeforeMonth (DateTimeFormatInfo dfi)
965 int dayIndex = dfi.MonthDayPattern.IndexOf('d');
966 int monthIndex = dfi.MonthDayPattern.IndexOf('M');
967 if (dayIndex == -1 || monthIndex == -1)
968 throw new FormatException (Locale.GetText("Order of month and date is not defined by {0}", dfi.MonthDayPattern));
970 return dayIndex < monthIndex;
973 private static string[] YearMonthDayFormats (DateTimeFormatInfo dfi)
975 int dayIndex = dfi.ShortDatePattern.IndexOf('d');
976 int monthIndex = dfi.ShortDatePattern.IndexOf('M');
977 int yearIndex = dfi.ShortDatePattern.IndexOf('y');
978 if (dayIndex == -1 || monthIndex == -1 || yearIndex == -1)
979 throw new FormatException (Locale.GetText("Order of year, month and date is not defined by {0}", dfi.ShortDatePattern));
981 if (yearIndex < monthIndex)
982 if (monthIndex < dayIndex)
983 return ParseYearMonthDayFormats;
984 else if (yearIndex < dayIndex)
985 return ParseYearDayMonthFormats;
987 // The year cannot be between the date and the month
988 throw new FormatException (Locale.GetText("Order of date, year and month defined by {0} is not supported", dfi.ShortDatePattern));
989 else if (dayIndex < monthIndex)
990 return ParseDayMonthYearFormats;
991 else if (dayIndex < yearIndex)
992 return ParseMonthDayYearFormats;
994 // The year cannot be between the month and the date
995 throw new FormatException (Locale.GetText("Order of month, year and date defined by {0} is not supported", dfi.ShortDatePattern));
998 private static int _ParseNumber (string s, int valuePos,
1002 bool sloppy_parsing,
1008 leadingzero = false;
1011 int real_digits = 0;
1012 for (i = valuePos; i < s.Length && i < digits + valuePos; i++) {
1013 if (!Char.IsDigit (s[i]))
1019 digits = real_digits;
1021 if (digits < min_digits) {
1026 if (s.Length - valuePos < digits) {
1031 for (i = valuePos; i < digits + valuePos; i++) {
1033 if (!Char.IsDigit (c)) {
1038 number = number * 10 + (byte) (c - '0');
1041 num_parsed = digits;
1045 private static int _ParseEnum (string s, int sPos, string[] values, string[] invValues, bool exact, out int num_parsed)
1047 // FIXME: I know this is somehow lame code. Probably
1048 // it should iterate all the enum value and return
1049 // the longest match. However right now I don't see
1050 // anything but "1" and "10" - "12" that might match
1051 // two or more values. (They are only abbrev month
1052 // names, so do reverse order search). See bug #80094.
1053 for (int i = values.Length - 1; i >= 0; i--) {
1054 if (!exact && invValues [i].Length > values[i].Length) {
1055 if (invValues [i].Length > 0 && _ParseString (s, sPos, 0, invValues [i], out num_parsed))
1057 if (values [i].Length > 0 && _ParseString (s, sPos, 0, values [i], out num_parsed))
1061 if (values [i].Length > 0 && _ParseString (s, sPos, 0, values [i], out num_parsed))
1063 if (!exact && invValues [i].Length > 0 && _ParseString (s, sPos, 0, invValues [i], out num_parsed))
1072 private static bool _ParseString (string s, int sPos, int maxlength, string value, out int num_parsed)
1075 maxlength = value.Length;
1077 if (sPos + maxlength <= s.Length && String.Compare (s, sPos, value, 0, maxlength, true, CultureInfo.InvariantCulture) == 0) {
1078 num_parsed = maxlength;
1086 // Note that in case of Parse (exact == false) we check both for AM/PM
1087 // and the culture spcific AM/PM strings.
1088 private static bool _ParseAmPm(string s,
1091 DateTimeFormatInfo dfi,
1100 if (!IsLetter (s, valuePos)) {
1101 if (dfi.AMDesignator != "")
1108 DateTimeFormatInfo invInfo = DateTimeFormatInfo.InvariantInfo;
1109 if (!exact && _ParseString (s, valuePos, num, invInfo.PMDesignator, out num_parsed) ||
1110 dfi.PMDesignator != "" && _ParseString(s, valuePos, num, dfi.PMDesignator, out num_parsed))
1112 else if (!exact && _ParseString (s, valuePos, num, invInfo.AMDesignator, out num_parsed) ||
1113 _ParseString (s, valuePos, num, dfi.AMDesignator, out num_parsed)) {
1114 if (exact || num_parsed != 0)
1122 // Note that in case of Parse (exact == false) we check both for ':'
1123 // and the culture spcific TimeSperator
1124 private static bool _ParseTimeSeparator (string s, int sPos, DateTimeFormatInfo dfi, bool exact, out int num_parsed)
1126 return _ParseString (s, sPos, 0, dfi.TimeSeparator, out num_parsed) ||
1127 !exact && _ParseString (s, sPos, 0, ":", out num_parsed);
1130 // Accept any character for DateSeparator, except TimeSeparator,
1131 // a digit or a letter.
1132 // Not documented, but seems to be MS behaviour here. See bug 54047.
1133 private static bool _ParseDateSeparator (string s, int sPos, DateTimeFormatInfo dfi, bool exact, out int num_parsed)
1136 if (exact && s [sPos] != '/')
1139 if (_ParseTimeSeparator (s, sPos, dfi, exact, out num_parsed) ||
1140 Char.IsDigit (s [sPos]) || Char.IsLetter (s [sPos]))
1147 private static bool IsLetter (string s, int pos)
1149 return pos < s.Length && Char.IsLetter (s [pos]);
1152 // To implement better DateTime.Parse we use two format strings one
1153 // for Date and one for Time. This allows us to define two different
1154 // arrays of formats for Time and Dates and to combine them more or less
1155 // efficiently. When this mode is used flexibleTwoPartsParsing is true.
1156 private static bool _DoParse (string s,
1160 out DateTime result,
1161 DateTimeFormatInfo dfi,
1162 DateTimeStyles style,
1163 bool firstPartIsDate,
1164 ref bool incompleteFormat,
1167 bool useutc = false;
1168 bool use_invariant = false;
1169 bool sloppy_parsing = false;
1171 bool afterTimePart = firstPartIsDate && secondPart == "";
1173 bool flexibleTwoPartsParsing = !exact && secondPart != null;
1174 incompleteFormat = false;
1176 string format = firstPart;
1177 bool afterTFormat = false;
1178 DateTimeFormatInfo invInfo = DateTimeFormatInfo.InvariantInfo;
1179 if (format.Length == 1)
1180 format = DateTimeUtils.GetStandardPattern (format [0], dfi, out useutc, out use_invariant);
1182 result = new DateTime (0);
1186 if ((style & DateTimeStyles.AllowLeadingWhite) != 0) {
1187 format = format.TrimStart (null);
1189 s = s.TrimStart (null); // it could be optimized, but will make little good.
1192 if ((style & DateTimeStyles.AllowTrailingWhite) != 0) {
1193 format = format.TrimEnd (null);
1194 s = s.TrimEnd (null); // it could be optimized, but will make little good.
1200 if ((style & DateTimeStyles.AllowInnerWhite) != 0)
1201 sloppy_parsing = true;
1203 string chars = format;
1204 int len = format.Length, pos = 0, num = 0;
1208 int day = -1, dayofweek = -1, month = -1, year = -1;
1209 int hour = -1, minute = -1, second = -1;
1210 double fractionalSeconds = -1;
1212 int tzsign = -1, tzoffset = -1, tzoffmin = -1;
1213 bool isFirstPart = true;
1217 if (valuePos == s.Length)
1221 if (flexibleTwoPartsParsing && pos + num == 0)
1223 bool isLetter = IsLetter(s, valuePos);
1227 if (afterTimePart && isLetter) {
1229 if (s [valuePos] == 'Z')
1232 _ParseString (s, valuePos, 0, "GMT", out num_parsed);
1233 if (num_parsed > 0 && !IsLetter (s, valuePos + num_parsed)) {
1234 valuePos += num_parsed;
1239 if (!afterTFormat && _ParseAmPm (s, valuePos, 0, dfi, exact, out num_parsed, ref ampm)) {
1240 if (IsLetter (s, valuePos + num_parsed))
1242 else if (num_parsed > 0) {
1243 valuePos += num_parsed;
1248 if (!afterTFormat && dayofweek == -1 && isLetter) {
1249 dayofweek = _ParseEnum (s, valuePos, dfi.RawDayNames, invInfo.RawDayNames, exact, out num_parsed);
1250 if (dayofweek == -1)
1251 dayofweek = _ParseEnum (s, valuePos, dfi.RawAbbreviatedDayNames, invInfo.RawAbbreviatedDayNames, exact, out num_parsed);
1252 if (dayofweek != -1 && !IsLetter (s, valuePos + num_parsed)) {
1253 valuePos += num_parsed;
1260 if (char.IsWhiteSpace (s [valuePos]) || s [valuePos] == ',') {
1267 if (pos + num >= len)
1269 if (flexibleTwoPartsParsing && num == 0) {
1270 afterTFormat = isFirstPart && firstPart [firstPart.Length - 1] == 'T';
1271 if (!isFirstPart && format == "")
1276 format = secondPart;
1281 isFirstPart = false;
1283 if (!firstPartIsDate || format == "")
1284 afterTimePart = true;
1291 bool leading_zeros = true;
1293 if (chars[pos] == '\'') {
1295 while (pos+num < len) {
1296 if (chars[pos+num] == '\'')
1299 if (valuePos == s.Length || s [valuePos] != chars [pos + num])
1309 } else if (chars[pos] == '"') {
1311 while (pos+num < len) {
1312 if (chars[pos+num] == '"')
1315 if (valuePos == s.Length || s [valuePos] != chars[pos+num])
1325 } else if (chars[pos] == '\\') {
1330 if (s [valuePos] != chars [pos])
1336 } else if (chars[pos] == '%') {
1339 } else if (char.IsWhiteSpace (s [valuePos]) ||
1340 s [valuePos] == ',' && (!exact && chars [pos] == '/' || Char.IsWhiteSpace (chars [pos]))) {
1343 if (exact && (style & DateTimeStyles.AllowInnerWhite) == 0) {
1344 if (!Char.IsWhiteSpace (chars[pos]))
1351 while (ws < s.Length) {
1352 if (Char.IsWhiteSpace (s [ws]) || s [ws] == ',')
1359 while (ws < chars.Length) {
1360 if (Char.IsWhiteSpace (chars [ws]) || chars [ws] == ',')
1366 // A whitespace may match a '/' in the pattern.
1367 if (!exact && pos < chars.Length && chars[pos] == '/')
1368 if (!_ParseDateSeparator (s, valuePos, dfi, exact, out num_parsed))
1373 if ((pos+num+1 < len) && (chars[pos+num+1] == chars[pos+num])) {
1381 if (num < 2 && day != -1 || num >= 2 && dayofweek != -1)
1384 day = _ParseNumber (s, valuePos, 1, 2, false, sloppy_parsing, out num_parsed);
1386 day = _ParseNumber (s, valuePos, 1, 2, true, sloppy_parsing, out num_parsed);
1388 dayofweek = _ParseEnum (s, valuePos, dfi.RawAbbreviatedDayNames, invInfo.RawAbbreviatedDayNames, exact, out num_parsed);
1390 dayofweek = _ParseEnum (s, valuePos, dfi.RawDayNames, invInfo.RawDayNames, exact, out num_parsed);
1396 if (flexibleTwoPartsParsing) {
1398 if (num == 0 || num == 3)
1399 month = _ParseNumber (s, valuePos, 1, 2, false, sloppy_parsing, out num_parsed);
1400 if (num > 1 && num_parsed == -1)
1401 month = _ParseEnum (s, valuePos, dfi.RawMonthNames, invInfo.RawMonthNames, exact, out num_parsed) + 1;
1402 if (num > 1 && num_parsed == -1)
1403 month = _ParseEnum (s, valuePos, dfi.RawAbbreviatedMonthNames, invInfo.RawAbbreviatedMonthNames, exact, out num_parsed) + 1;
1408 month = _ParseNumber (s, valuePos, 1, 2, false, sloppy_parsing, out num_parsed);
1410 month = _ParseNumber (s, valuePos, 1, 2, true, sloppy_parsing, out num_parsed);
1412 month = _ParseEnum (s, valuePos, dfi.RawAbbreviatedMonthNames, invInfo.RawAbbreviatedMonthNames, exact, out num_parsed) + 1;
1414 month = _ParseEnum (s, valuePos, dfi.RawMonthNames, invInfo.RawMonthNames, exact, out num_parsed) + 1;
1421 year = _ParseNumber (s, valuePos, 1, 2, false, sloppy_parsing, out num_parsed);
1422 } else if (num < 3) {
1423 year = _ParseNumber (s, valuePos, 1, 2, true, sloppy_parsing, out num_parsed);
1425 year = _ParseNumber (s, valuePos, exact ? 4 : 3, 4, false, sloppy_parsing, out num_parsed);
1426 if ((year >= 1000) && (num_parsed == 4) && (!longYear) && (s.Length > 4 + valuePos)) {
1428 int ly = _ParseNumber (s, valuePos, 5, 5, false, sloppy_parsing, out np);
1429 longYear = (ly > 9999);
1434 //FIXME: We should do use dfi.Calendat.TwoDigitYearMax
1435 if (num_parsed <= 2)
1436 year += (year < 30) ? 2000 : 1900;
1442 hour = _ParseNumber (s, valuePos, 1, 2, false, sloppy_parsing, out num_parsed);
1444 hour = _ParseNumber (s, valuePos, 1, 2, true, sloppy_parsing, out num_parsed);
1453 if (hour != -1 || !flexibleTwoPartsParsing && ampm >= 0)
1456 hour = _ParseNumber (s, valuePos, 1, 2, false, sloppy_parsing, out num_parsed);
1458 hour = _ParseNumber (s, valuePos, 1, 2, true, sloppy_parsing, out num_parsed);
1469 minute = _ParseNumber (s, valuePos, 1, 2, false, sloppy_parsing, out num_parsed);
1471 minute = _ParseNumber (s, valuePos, 1, 2, true, sloppy_parsing, out num_parsed);
1481 second = _ParseNumber (s, valuePos, 1, 2, false, sloppy_parsing, out num_parsed);
1483 second = _ParseNumber (s, valuePos, 1, 2, true, sloppy_parsing, out num_parsed);
1491 leading_zeros = false;
1495 if (num > 6 || fractionalSeconds != -1)
1497 double decimalNumber = (double) _ParseNumber (s, valuePos, 0, num+1, leading_zeros, sloppy_parsing, out num_parsed);
1498 if (num_parsed == -1)
1500 fractionalSeconds = decimalNumber / Math.Pow(10.0, num_parsed);
1503 if (!_ParseAmPm (s, valuePos, num > 0 ? 0 : 1, dfi, exact, out num_parsed, ref ampm))
1510 if (s [valuePos] == '+')
1512 else if (s [valuePos] == '-')
1519 tzoffset = _ParseNumber (s, valuePos, 1, 2, false, sloppy_parsing, out num_parsed);
1521 tzoffset = _ParseNumber (s, valuePos, 1, 2, true, sloppy_parsing, out num_parsed);
1523 tzoffset = _ParseNumber (s, valuePos, 1, 2, true, sloppy_parsing, out num_parsed);
1524 valuePos += num_parsed;
1529 if (valuePos < s.Length && Char.IsDigit (s [valuePos]) ||
1530 _ParseTimeSeparator (s, valuePos, dfi, exact, out num_parsed)) {
1531 valuePos += num_parsed;
1532 tzoffmin = _ParseNumber (s, valuePos, 1, 2, true, sloppy_parsing, out num_parsed);
1536 else if (!flexibleTwoPartsParsing)
1544 if (s [valuePos] == 'Z') {
1547 style |= DateTimeStyles.AdjustToUniversal;
1549 else if (s [valuePos] == '+' || s [valuePos] == '-') {
1552 if (s [valuePos] == '+')
1554 else if (s [valuePos] == '-')
1559 tzoffset = _ParseNumber (s, valuePos, 0, 2, true, sloppy_parsing, out num_parsed);
1560 valuePos += num_parsed;
1564 if (Char.IsDigit (s [valuePos]))
1566 else if (!_ParseString (s, valuePos, 0, dfi.TimeSeparator, out num_parsed))
1568 valuePos += num_parsed;
1570 tzoffmin = _ParseNumber (s, valuePos, 0, 2, true, sloppy_parsing, out num_parsed);
1577 // LAMESPEC: This should be part of UTCpattern
1578 // string and thus should not be considered here.
1580 // Note that 'Z' is not defined as a pattern
1581 // character. Keep it for X509 certificate
1582 // verification. Also, "Z" != "'Z'" under MS.NET
1583 // ("'Z'" is just literal; handled above)
1585 if (s [valuePos] != 'Z')
1592 if (s [valuePos] != 'G')
1595 if ((pos + 2 < len) && (valuePos + 2 < s.Length) &&
1596 (chars [pos + 1] == 'M') && (s[valuePos + 1] == 'M') &&
1597 (chars [pos + 2] == 'T') && (s[valuePos + 2] == 'T'))
1609 if (!_ParseTimeSeparator (s, valuePos, dfi, exact, out num_parsed))
1613 if (!_ParseDateSeparator (s, valuePos, dfi, exact, out num_parsed))
1619 if (s [valuePos] != chars [pos])
1630 valuePos += num_parsed;
1632 if (!exact && !flexibleTwoPartsParsing) {
1633 switch (chars [pos]) {
1641 if (s.Length > valuePos && s [valuePos] == 'Z' &&
1642 (pos + 1 == chars.Length || chars [pos + 1] != 'Z')) {
1650 pos = pos + num + 1;
1655 while (pos < len && chars [pos] == 'K') // 'K' can be mapped to nothing
1661 if (s.Length > valuePos) // extraneous tail.
1666 if (Char.IsDigit (s [valuePos]) && Char.IsDigit (s [valuePos - 1]))
1668 if (Char.IsLetter (s [valuePos]) && Char.IsLetter (s [valuePos - 1]))
1670 incompleteFormat = true;
1681 if (fractionalSeconds == -1)
1682 fractionalSeconds = 0;
1684 // If no date was given
1685 if ((day == -1) && (month == -1) && (year == -1)) {
1686 if ((style & DateTimeStyles.NoCurrentDateDefault) != 0) {
1691 day = DateTime.Today.Day;
1692 month = DateTime.Today.Month;
1693 year = DateTime.Today.Year;
1702 if ((style & DateTimeStyles.NoCurrentDateDefault) != 0)
1705 year = DateTime.Today.Year;
1708 if (ampm == 0 && hour == 12)
1711 if (ampm == 1 && (!flexibleTwoPartsParsing || hour < 12))
1714 // For anything out of range
1716 if (year < 1 || year > 9999 ||
1717 month < 1 || month >12 ||
1718 day < 1 || day > DateTime.DaysInMonth(year, month) ||
1719 hour < 0 || hour > 23 ||
1720 minute < 0 || minute > 59 ||
1721 second < 0 || second > 59)
1724 result = new DateTime (year, month, day, hour, minute, second, 0);
1725 result = result.AddSeconds(fractionalSeconds);
1727 if (dayofweek != -1 && dayofweek != (int) result.DayOfWeek)
1730 bool kind_specified = true;
1739 tzoffset = -tzoffset;
1741 utcoffset = new TimeSpan (tzoffset, tzoffmin, 0);
1744 else if (useutc || ((style & DateTimeStyles.AssumeUniversal) != 0))
1748 utcoffset = new TimeSpan (0, 0, 0);
1750 // If no timezone was specified, default to the local timezone.
1751 TimeZone tz = TimeZone.CurrentTimeZone;
1752 utcoffset = tz.GetUtcOffset (result);
1755 if ((style & DateTimeStyles.AssumeLocal) == 0)
1757 kind_specified = false;
1760 long newticks = (result.ticks - utcoffset).Ticks;
1762 result = new DateTime (false, new TimeSpan (newticks));
1764 if (kind_specified && ((style & DateTimeStyles.AdjustToUniversal) != 0)) {
1766 result.kind = DateTimeKind.Utc;
1770 result = result.ToLocalTime ();
1772 if (!kind_specified)
1773 result.kind = DateTimeKind.Unspecified;
1780 public static DateTime ParseExact (string s, string format,
1781 IFormatProvider fp, DateTimeStyles style)
1784 throw new ArgumentNullException ("format");
1786 string [] formats = new string [1];
1787 formats[0] = format;
1789 return ParseExact (s, formats, fp, style);
1792 public static DateTime ParseExact (string s, string[] formats,
1794 DateTimeStyles style)
1796 DateTimeFormatInfo dfi = DateTimeFormatInfo.GetInstance (fp);
1799 throw new ArgumentNullException ("s");
1800 if (formats == null)
1801 throw new ArgumentNullException ("formats");
1802 if (formats.Length == 0)
1803 throw new FormatException ("Format specifier was invalid.");
1806 bool longYear = false;
1807 if (!ParseExact (s, formats, dfi, style, out result, true, ref longYear))
1808 throw new FormatException ();
1813 public static bool TryParse (string s, out DateTime result)
1824 public static bool TryParse (string s, IFormatProvider provider, DateTimeStyles styles, out DateTime result)
1827 result = Parse (s, provider, styles);
1835 public static bool TryParseExact (string s, string format,
1837 DateTimeStyles style,
1838 out DateTime result)
1842 formats = new string [1];
1843 formats[0] = format;
1845 return TryParseExact (s, formats, fp, style, out result);
1848 public static bool TryParseExact (string s, string[] formats,
1850 DateTimeStyles style,
1851 out DateTime result)
1853 DateTimeFormatInfo dfi = DateTimeFormatInfo.GetInstance (fp);
1855 bool longYear = false;
1856 return ParseExact (s, formats, dfi, style, out result, true, ref longYear);
1860 private static bool ParseExact (string s, string [] formats,
1861 DateTimeFormatInfo dfi, DateTimeStyles style, out DateTime ret,
1862 bool exact, ref bool longYear)
1865 bool incompleteFormat = false;
1866 for (i = 0; i < formats.Length; i++)
1869 string format = formats[i];
1870 if (format == null || format == String.Empty)
1871 throw new FormatException ("Invalid Format String");
1873 if (_DoParse (s, formats[i], null, exact, out result, dfi, style, false, ref incompleteFormat, ref longYear)) {
1878 ret = DateTime.MinValue;
1882 public TimeSpan Subtract(DateTime dt)
1884 return new TimeSpan(ticks.Ticks) - dt.ticks;
1887 public DateTime Subtract(TimeSpan ts)
1891 newticks = (new TimeSpan (ticks.Ticks)) - ts;
1892 DateTime ret = new DateTime(true,newticks);
1899 public long ToFileTime()
1901 DateTime universalTime = ToUniversalTime();
1903 if (universalTime.Ticks < w32file_epoch) {
1904 throw new ArgumentOutOfRangeException("file time is not valid");
1907 return(universalTime.Ticks - w32file_epoch);
1911 public long ToFileTimeUtc()
1913 if (Ticks < w32file_epoch) {
1914 throw new ArgumentOutOfRangeException("file time is not valid");
1917 return (Ticks - w32file_epoch);
1921 public string ToLongDateString()
1923 return ToString ("D");
1926 public string ToLongTimeString()
1928 return ToString ("T");
1931 public double ToOADate ()
1933 long t = this.Ticks;
1934 // uninitialized DateTime case
1937 // we can't reach minimum value
1938 if (t < 31242239136000000)
1939 return OAMinValue + 0.001;
1941 TimeSpan ts = new TimeSpan (this.Ticks - ticks18991230);
1942 double result = ts.TotalDays;
1943 // t < 0 (where 599264352000000000 == 0.0d for OA)
1944 if (t < 599264352000000000) {
1945 // negative days (int) but decimals are positive
1946 double d = Math.Ceiling (result);
1947 result = d - 2 - (result - d);
1950 // we can't reach maximum value
1951 if (result >= OAMaxValue)
1952 result = OAMaxValue - 0.00000001d;
1957 public string ToShortDateString()
1959 return ToString ("d");
1962 public string ToShortTimeString()
1964 return ToString ("t");
1967 public override string ToString ()
1969 return ToString ("G", null);
1972 public string ToString (IFormatProvider fp)
1974 return ToString (null, fp);
1977 public string ToString (string format)
1979 return ToString (format, null);
1982 public string ToString (string format, IFormatProvider fp)
1984 DateTimeFormatInfo dfi = DateTimeFormatInfo.GetInstance(fp);
1986 if (format == null || format == String.Empty)
1989 bool useutc = false, use_invariant = false;
1991 if (format.Length == 1) {
1992 char fchar = format [0];
1993 format = DateTimeUtils.GetStandardPattern (fchar, dfi, out useutc, out use_invariant);
1995 return DateTimeUtils.ToString (ToUniversalTime (), format, dfi);
1996 // return ToUniversalTime()._ToString (format, dfi);
1999 throw new FormatException ("format is not one of the format specifier characters defined for DateTimeFormatInfo");
2002 // Don't convert UTC value. It just adds 'Z' for
2003 // 'u' format, for the same ticks.
2004 return DateTimeUtils.ToString (this, format, dfi);
2007 public DateTime ToLocalTime ()
2009 return TimeZone.CurrentTimeZone.ToLocalTime (this);
2012 public DateTime ToUniversalTime()
2014 return TimeZone.CurrentTimeZone.ToUniversalTime (this);
2019 public static DateTime operator +(DateTime d, TimeSpan t)
2021 DateTime ret = new DateTime (true, d.ticks + t);
2028 public static bool operator ==(DateTime d1, DateTime d2)
2030 return (d1.ticks == d2.ticks);
2033 public static bool operator >(DateTime t1,DateTime t2)
2035 return (t1.ticks > t2.ticks);
2038 public static bool operator >=(DateTime t1,DateTime t2)
2040 return (t1.ticks >= t2.ticks);
2043 public static bool operator !=(DateTime d1, DateTime d2)
2045 return (d1.ticks != d2.ticks);
2048 public static bool operator <(DateTime t1, DateTime t2)
2050 return (t1.ticks < t2.ticks );
2053 public static bool operator <=(DateTime t1,DateTime t2)
2055 return (t1.ticks <= t2.ticks);
2058 public static TimeSpan operator -(DateTime d1,DateTime d2)
2060 return new TimeSpan((d1.ticks - d2.ticks).Ticks);
2063 public static DateTime operator -(DateTime d,TimeSpan t)
2065 DateTime ret = new DateTime (true, d.ticks - t);
2072 bool IConvertible.ToBoolean(IFormatProvider provider)
2074 throw new InvalidCastException();
2077 byte IConvertible.ToByte(IFormatProvider provider)
2079 throw new InvalidCastException();
2083 char IConvertible.ToChar(IFormatProvider provider)
2085 throw new InvalidCastException();
2088 System.DateTime IConvertible.ToDateTime(IFormatProvider provider)
2093 decimal IConvertible.ToDecimal(IFormatProvider provider)
2095 throw new InvalidCastException();
2098 double IConvertible.ToDouble(IFormatProvider provider)
2100 throw new InvalidCastException();
2103 Int16 IConvertible.ToInt16(IFormatProvider provider)
2105 throw new InvalidCastException();
2108 Int32 IConvertible.ToInt32(IFormatProvider provider)
2110 throw new InvalidCastException();
2113 Int64 IConvertible.ToInt64(IFormatProvider provider)
2115 throw new InvalidCastException();
2118 SByte IConvertible.ToSByte(IFormatProvider provider)
2120 throw new InvalidCastException();
2123 Single IConvertible.ToSingle(IFormatProvider provider)
2125 throw new InvalidCastException();
2128 object IConvertible.ToType (Type conversionType, IFormatProvider provider)
2130 if (conversionType == null)
2131 throw new ArgumentNullException ("conversionType");
2133 if (conversionType == typeof (DateTime))
2135 else if (conversionType == typeof (String))
2136 return this.ToString (provider);
2137 else if (conversionType == typeof (Object))
2140 throw new InvalidCastException();
2143 UInt16 IConvertible.ToUInt16(IFormatProvider provider)
2145 throw new InvalidCastException();
2148 UInt32 IConvertible.ToUInt32(IFormatProvider provider)
2150 throw new InvalidCastException();
2153 UInt64 IConvertible.ToUInt64(IFormatProvider provider)
2155 throw new InvalidCastException();