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') {
1548 else if (s [valuePos] == '+' || s [valuePos] == '-') {
1551 if (s [valuePos] == '+')
1553 else if (s [valuePos] == '-')
1558 tzoffset = _ParseNumber (s, valuePos, 0, 2, true, sloppy_parsing, out num_parsed);
1559 valuePos += num_parsed;
1563 if (Char.IsDigit (s [valuePos]))
1565 else if (!_ParseString (s, valuePos, 0, dfi.TimeSeparator, out num_parsed))
1567 valuePos += num_parsed;
1569 tzoffmin = _ParseNumber (s, valuePos, 0, 2, true, sloppy_parsing, out num_parsed);
1576 // LAMESPEC: This should be part of UTCpattern
1577 // string and thus should not be considered here.
1579 // Note that 'Z' is not defined as a pattern
1580 // character. Keep it for X509 certificate
1581 // verification. Also, "Z" != "'Z'" under MS.NET
1582 // ("'Z'" is just literal; handled above)
1584 if (s [valuePos] != 'Z')
1591 if (s [valuePos] != 'G')
1594 if ((pos + 2 < len) && (valuePos + 2 < s.Length) &&
1595 (chars [pos + 1] == 'M') && (s[valuePos + 1] == 'M') &&
1596 (chars [pos + 2] == 'T') && (s[valuePos + 2] == 'T'))
1608 if (!_ParseTimeSeparator (s, valuePos, dfi, exact, out num_parsed))
1612 if (!_ParseDateSeparator (s, valuePos, dfi, exact, out num_parsed))
1618 if (s [valuePos] != chars [pos])
1629 valuePos += num_parsed;
1631 if (!exact && !flexibleTwoPartsParsing) {
1632 switch (chars [pos]) {
1640 if (s.Length > valuePos && s [valuePos] == 'Z' &&
1641 (pos + 1 == chars.Length || chars [pos + 1] != 'Z')) {
1649 pos = pos + num + 1;
1654 while (pos < len && chars [pos] == 'K') // 'K' can be mapped to nothing
1660 if (s.Length > valuePos) // extraneous tail.
1665 if (Char.IsDigit (s [valuePos]) && Char.IsDigit (s [valuePos - 1]))
1667 if (Char.IsLetter (s [valuePos]) && Char.IsLetter (s [valuePos - 1]))
1669 incompleteFormat = true;
1680 if (fractionalSeconds == -1)
1681 fractionalSeconds = 0;
1683 // If no date was given
1684 if ((day == -1) && (month == -1) && (year == -1)) {
1685 if ((style & DateTimeStyles.NoCurrentDateDefault) != 0) {
1690 day = DateTime.Today.Day;
1691 month = DateTime.Today.Month;
1692 year = DateTime.Today.Year;
1701 if ((style & DateTimeStyles.NoCurrentDateDefault) != 0)
1704 year = DateTime.Today.Year;
1707 if (ampm == 0 && hour == 12)
1710 if (ampm == 1 && (!flexibleTwoPartsParsing || hour < 12))
1713 // For anything out of range
1715 if (year < 1 || year > 9999 ||
1716 month < 1 || month >12 ||
1717 day < 1 || day > DateTime.DaysInMonth(year, month) ||
1718 hour < 0 || hour > 23 ||
1719 minute < 0 || minute > 59 ||
1720 second < 0 || second > 59)
1723 result = new DateTime (year, month, day, hour, minute, second, 0);
1724 result = result.AddSeconds(fractionalSeconds);
1726 if (dayofweek != -1 && dayofweek != (int) result.DayOfWeek)
1729 bool kind_specified = true;
1738 tzoffset = -tzoffset;
1740 utcoffset = new TimeSpan (tzoffset, tzoffmin, 0);
1743 else if (useutc || ((style & DateTimeStyles.AssumeUniversal) != 0))
1747 utcoffset = new TimeSpan (0, 0, 0);
1749 // If no timezone was specified, default to the local timezone.
1750 TimeZone tz = TimeZone.CurrentTimeZone;
1751 utcoffset = tz.GetUtcOffset (result);
1754 if ((style & DateTimeStyles.AssumeLocal) == 0)
1756 kind_specified = false;
1759 long newticks = (result.ticks - utcoffset).Ticks;
1761 result = new DateTime (false, new TimeSpan (newticks));
1763 if (kind_specified && ((style & DateTimeStyles.AdjustToUniversal) != 0)) {
1765 result.kind = DateTimeKind.Utc;
1769 result = result.ToLocalTime ();
1771 if (!kind_specified)
1772 result.kind = DateTimeKind.Unspecified;
1779 public static DateTime ParseExact (string s, string format,
1780 IFormatProvider fp, DateTimeStyles style)
1783 throw new ArgumentNullException ("format");
1785 string [] formats = new string [1];
1786 formats[0] = format;
1788 return ParseExact (s, formats, fp, style);
1791 public static DateTime ParseExact (string s, string[] formats,
1793 DateTimeStyles style)
1795 DateTimeFormatInfo dfi = DateTimeFormatInfo.GetInstance (fp);
1798 throw new ArgumentNullException ("s");
1799 if (formats == null)
1800 throw new ArgumentNullException ("formats");
1801 if (formats.Length == 0)
1802 throw new FormatException ("Format specifier was invalid.");
1805 bool longYear = false;
1806 if (!ParseExact (s, formats, dfi, style, out result, true, ref longYear))
1807 throw new FormatException ();
1812 public static bool TryParse (string s, out DateTime result)
1823 public static bool TryParse (string s, IFormatProvider provider, DateTimeStyles styles, out DateTime result)
1826 result = Parse (s, provider, styles);
1834 public static bool TryParseExact (string s, string format,
1836 DateTimeStyles style,
1837 out DateTime result)
1841 formats = new string [1];
1842 formats[0] = format;
1844 return TryParseExact (s, formats, fp, style, out result);
1847 public static bool TryParseExact (string s, string[] formats,
1849 DateTimeStyles style,
1850 out DateTime result)
1852 DateTimeFormatInfo dfi = DateTimeFormatInfo.GetInstance (fp);
1854 bool longYear = false;
1855 return ParseExact (s, formats, dfi, style, out result, true, ref longYear);
1859 private static bool ParseExact (string s, string [] formats,
1860 DateTimeFormatInfo dfi, DateTimeStyles style, out DateTime ret,
1861 bool exact, ref bool longYear)
1864 bool incompleteFormat = false;
1865 for (i = 0; i < formats.Length; i++)
1868 string format = formats[i];
1869 if (format == null || format == String.Empty)
1870 throw new FormatException ("Invalid Format String");
1872 if (_DoParse (s, formats[i], null, exact, out result, dfi, style, false, ref incompleteFormat, ref longYear)) {
1877 ret = DateTime.MinValue;
1881 public TimeSpan Subtract(DateTime dt)
1883 return new TimeSpan(ticks.Ticks) - dt.ticks;
1886 public DateTime Subtract(TimeSpan ts)
1890 newticks = (new TimeSpan (ticks.Ticks)) - ts;
1891 DateTime ret = new DateTime(true,newticks);
1898 public long ToFileTime()
1900 DateTime universalTime = ToUniversalTime();
1902 if (universalTime.Ticks < w32file_epoch) {
1903 throw new ArgumentOutOfRangeException("file time is not valid");
1906 return(universalTime.Ticks - w32file_epoch);
1910 public long ToFileTimeUtc()
1912 if (Ticks < w32file_epoch) {
1913 throw new ArgumentOutOfRangeException("file time is not valid");
1916 return (Ticks - w32file_epoch);
1920 public string ToLongDateString()
1922 return ToString ("D");
1925 public string ToLongTimeString()
1927 return ToString ("T");
1930 public double ToOADate ()
1932 long t = this.Ticks;
1933 // uninitialized DateTime case
1936 // we can't reach minimum value
1937 if (t < 31242239136000000)
1938 return OAMinValue + 0.001;
1940 TimeSpan ts = new TimeSpan (this.Ticks - ticks18991230);
1941 double result = ts.TotalDays;
1942 // t < 0 (where 599264352000000000 == 0.0d for OA)
1943 if (t < 599264352000000000) {
1944 // negative days (int) but decimals are positive
1945 double d = Math.Ceiling (result);
1946 result = d - 2 - (result - d);
1949 // we can't reach maximum value
1950 if (result >= OAMaxValue)
1951 result = OAMaxValue - 0.00000001d;
1956 public string ToShortDateString()
1958 return ToString ("d");
1961 public string ToShortTimeString()
1963 return ToString ("t");
1966 public override string ToString ()
1968 return ToString ("G", null);
1971 public string ToString (IFormatProvider fp)
1973 return ToString (null, fp);
1976 public string ToString (string format)
1978 return ToString (format, null);
1981 public string ToString (string format, IFormatProvider fp)
1983 DateTimeFormatInfo dfi = DateTimeFormatInfo.GetInstance(fp);
1985 if (format == null || format == String.Empty)
1988 bool useutc = false, use_invariant = false;
1990 if (format.Length == 1) {
1991 char fchar = format [0];
1992 format = DateTimeUtils.GetStandardPattern (fchar, dfi, out useutc, out use_invariant);
1994 return DateTimeUtils.ToString (ToUniversalTime (), format, dfi);
1995 // return ToUniversalTime()._ToString (format, dfi);
1998 throw new FormatException ("format is not one of the format specifier characters defined for DateTimeFormatInfo");
2001 // Don't convert UTC value. It just adds 'Z' for
2002 // 'u' format, for the same ticks.
2003 return DateTimeUtils.ToString (this, format, dfi);
2006 public DateTime ToLocalTime ()
2008 return TimeZone.CurrentTimeZone.ToLocalTime (this);
2011 public DateTime ToUniversalTime()
2013 return TimeZone.CurrentTimeZone.ToUniversalTime (this);
2018 public static DateTime operator +(DateTime d, TimeSpan t)
2020 DateTime ret = new DateTime (true, d.ticks + t);
2027 public static bool operator ==(DateTime d1, DateTime d2)
2029 return (d1.ticks == d2.ticks);
2032 public static bool operator >(DateTime t1,DateTime t2)
2034 return (t1.ticks > t2.ticks);
2037 public static bool operator >=(DateTime t1,DateTime t2)
2039 return (t1.ticks >= t2.ticks);
2042 public static bool operator !=(DateTime d1, DateTime d2)
2044 return (d1.ticks != d2.ticks);
2047 public static bool operator <(DateTime t1, DateTime t2)
2049 return (t1.ticks < t2.ticks );
2052 public static bool operator <=(DateTime t1,DateTime t2)
2054 return (t1.ticks <= t2.ticks);
2057 public static TimeSpan operator -(DateTime d1,DateTime d2)
2059 return new TimeSpan((d1.ticks - d2.ticks).Ticks);
2062 public static DateTime operator -(DateTime d,TimeSpan t)
2064 DateTime ret = new DateTime (true, d.ticks - t);
2071 bool IConvertible.ToBoolean(IFormatProvider provider)
2073 throw new InvalidCastException();
2076 byte IConvertible.ToByte(IFormatProvider provider)
2078 throw new InvalidCastException();
2082 char IConvertible.ToChar(IFormatProvider provider)
2084 throw new InvalidCastException();
2087 System.DateTime IConvertible.ToDateTime(IFormatProvider provider)
2092 decimal IConvertible.ToDecimal(IFormatProvider provider)
2094 throw new InvalidCastException();
2097 double IConvertible.ToDouble(IFormatProvider provider)
2099 throw new InvalidCastException();
2102 Int16 IConvertible.ToInt16(IFormatProvider provider)
2104 throw new InvalidCastException();
2107 Int32 IConvertible.ToInt32(IFormatProvider provider)
2109 throw new InvalidCastException();
2112 Int64 IConvertible.ToInt64(IFormatProvider provider)
2114 throw new InvalidCastException();
2117 SByte IConvertible.ToSByte(IFormatProvider provider)
2119 throw new InvalidCastException();
2122 Single IConvertible.ToSingle(IFormatProvider provider)
2124 throw new InvalidCastException();
2127 object IConvertible.ToType (Type conversionType, IFormatProvider provider)
2129 if (conversionType == null)
2130 throw new ArgumentNullException ("conversionType");
2132 if (conversionType == typeof (DateTime))
2134 else if (conversionType == typeof (String))
2135 return this.ToString (provider);
2136 else if (conversionType == typeof (Object))
2139 throw new InvalidCastException();
2142 UInt16 IConvertible.ToUInt16(IFormatProvider provider)
2144 throw new InvalidCastException();
2147 UInt32 IConvertible.ToUInt32(IFormatProvider provider)
2149 throw new InvalidCastException();
2152 UInt64 IConvertible.ToUInt64(IFormatProvider provider)
2154 throw new InvalidCastException();