-//\r
-// System.DateTime.cs\r
-//\r
-// author:\r
-// Marcel Narings (marcel@narings.nl)\r
-// Martin Baulig (martin@gnome.org)\r
-//\r
-// (C) 2001 Marcel Narings\r
-\r
-using System;\r
-using System.Globalization;\r
-using System.Runtime.CompilerServices;\r
-\r
-\r
-namespace System\r
-{\r
- /// <summary>\r
- /// The DateTime structure represents dates and time ranging from\r
- /// 1-1-0001 12:00:00 AM to 31-12-9999 23:59:00 Common Era.\r
- /// </summary>\r
- /// \r
- [Serializable]\r
- public struct DateTime : IComparable , IFormattable , IConvertible\r
- {\r
- private TimeSpan ticks;\r
-\r
- private const int dp400 = 146097;\r
- private const int dp100 = 36524;\r
- private const int dp4 = 1461;\r
-\r
- // w32 file time starts counting from 1/1/1601 00:00 GMT\r
- // which is the constant ticks from the .NET epoch\r
- private const long w32file_epoch = 504911232000000000L;\r
-\r
- //\r
- // The UnixEpoch, it begins on Jan 1, 1970 at 0:0:0, expressed\r
- // in Ticks\r
- //\r
- internal const long UnixEpoch = 621355968000000000L;\r
- \r
- public static readonly DateTime MaxValue = new DateTime (false,TimeSpan.MaxValue);\r
- public static readonly DateTime MinValue = new DateTime (false,TimeSpan.MinValue);\r
- \r
- private enum Which \r
- {\r
- Day,\r
- DayYear,\r
- Month,\r
- Year\r
- };\r
- \r
- private static int[] daysmonth = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; \r
- private static int[] daysmonthleap = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; \r
-\r
- private static int AbsoluteDays (int year, int month, int day)\r
- {\r
- int[] days;\r
- int temp = 0, m=1 ;\r
- \r
- days = (IsLeapYear(year) ? daysmonthleap : daysmonth);\r
- \r
- while (m < month)\r
- temp += days[m++];\r
- return ((day-1) + temp + (365* (year-1)) + ((year-1)/4) - ((year-1)/100) + ((year-1)/400));\r
- }\r
-\r
- private int FromTicks(Which what)\r
- {\r
- int num400, num100, num4, numyears; \r
- int M =1;\r
-\r
- int[] days = daysmonth;\r
- int totaldays = this.ticks.Days;\r
-\r
- num400 = (totaldays / dp400);\r
- totaldays -= num400 * dp400;\r
- \r
- num100 = (totaldays / dp100);\r
- if (num100 == 4) // leap\r
- num100 = 3;\r
- totaldays -= (num100 * dp100);\r
-\r
- num4 = totaldays / dp4;\r
- totaldays -= (num4 * dp4);\r
-\r
- numyears = totaldays / 365 ;\r
-\r
- if (numyears == 4) //leap\r
- numyears =3 ;\r
- if (what == Which.Year )\r
- return num400*400 + num100*100 + num4*4 + numyears + 1;\r
-\r
- totaldays -= (numyears * 365) ;\r
- if (what == Which.DayYear )\r
- return totaldays + 1;\r
- \r
- if ((numyears==3) && ((num100 == 3) || !(num4 == 24)) ) //31 dec leapyear\r
- days = daysmonthleap;\r
- \r
- while (totaldays >= days[M])\r
- totaldays -= days[M++];\r
-\r
- if (what == Which.Month )\r
- return M;\r
-\r
- return totaldays +1; \r
- }\r
-\r
-\r
- // Constructors\r
- \r
- /// <summary>\r
- /// Constructs a DateTime for specified ticks\r
- /// </summary>\r
- /// \r
- public DateTime (long newticks)\r
- // `local' must default to false here to avoid\r
- // a recursion loop.\r
- : this (false, newticks) {}\r
-\r
- internal DateTime (bool local, long newticks)\r
- : this (true, new TimeSpan (newticks))\r
- {\r
- if (local) {\r
- TimeZone tz = TimeZone.CurrentTimeZone;\r
-\r
- TimeSpan utcoffset = tz.GetUtcOffset (this);\r
-\r
- ticks = ticks + utcoffset;\r
- }\r
- }\r
-\r
- public DateTime (int year, int month, int day)\r
- : this (year, month, day,0,0,0,0) {}\r
-\r
- public DateTime (int year, int month, int day, int hour, int minute, int second)\r
- : this (year, month, day, hour, minute, second, 0) {}\r
-\r
- public DateTime (int year, int month, int day, int hour, int minute, int second, int millisecond)\r
- {\r
- if ( year < 1 || year > 9999 || \r
- month < 1 || month >12 ||\r
- day < 1 || day > DaysInMonth(year, month) ||\r
- hour < 0 || hour > 23 ||\r
- minute < 0 || minute > 59 ||\r
- second < 0 || second > 59 )\r
- throw new ArgumentOutOfRangeException ("Parameters describe an " +\r
- "unrepresentable DateTime.");\r
-\r
- ticks = new TimeSpan (AbsoluteDays(year,month,day), hour, minute, second, millisecond);\r
- }\r
-\r
- public DateTime (int year, int month, int day, Calendar calendar)\r
- : this (year, month, day, 0, 0, 0, 0, calendar) {}\r
-\r
- \r
- public DateTime (int year, int month, int day, int hour, int minute, int second, Calendar calendar)\r
- : this (year, month, day, hour, minute, second, 0, calendar) {}\r
-\r
-\r
- public DateTime (int year, int month, int day, int hour, int minute, int second, int millisecond, Calendar calendar)\r
- : this (year, month, day, hour, minute, second, millisecond) \r
- {\r
- if (calendar == null)\r
- throw new ArgumentNullException();\r
- }\r
-\r
- internal DateTime (bool check, TimeSpan value)\r
- {\r
- if (check && (value.Ticks < MinValue.Ticks || value.Ticks > MaxValue.Ticks))\r
- throw new ArgumentOutOfRangeException ();\r
-\r
- ticks = value;\r
- }\r
-\r
- /* Properties */\r
- \r
- public DateTime Date \r
- {\r
- get \r
- { \r
- return new DateTime (Year, Month, Day);\r
- }\r
- }\r
- \r
- public int Month \r
- {\r
- get \r
- { \r
- return FromTicks(Which.Month); \r
- }\r
- }\r
-\r
- \r
- public int Day\r
- {\r
- get \r
- { \r
- return FromTicks(Which.Day); \r
- }\r
- }\r
-\r
- public DayOfWeek DayOfWeek \r
- {\r
- get \r
- { \r
- return ( (DayOfWeek) ((ticks.Days+1) % 7) ); \r
- }\r
- }\r
-\r
- public int DayOfYear \r
- {\r
- get \r
- { \r
- return FromTicks(Which.DayYear); \r
- }\r
- }\r
-\r
- public TimeSpan TimeOfDay \r
- {\r
- get \r
- { \r
- return new TimeSpan(ticks.Ticks % TimeSpan.TicksPerDay );\r
- }\r
- \r
- }\r
-\r
- public int Hour \r
- {\r
- get \r
- { \r
- return ticks.Hours;\r
- }\r
- }\r
-\r
- public int Minute \r
- {\r
- get \r
- { \r
- return ticks.Minutes;\r
- }\r
- }\r
-\r
- public int Second \r
- {\r
- get \r
- { \r
- return ticks.Seconds;\r
- }\r
- }\r
-\r
- public int Millisecond \r
- {\r
- get \r
- { \r
- return ticks.Milliseconds;\r
- }\r
- }\r
- \r
- [MethodImplAttribute(MethodImplOptions.InternalCall)]\r
- internal static extern long GetNow ();\r
-\r
- public static DateTime Now \r
- {\r
- get \r
- {\r
- return new DateTime (true, GetNow ());\r
- }\r
- }\r
-\r
- public long Ticks\r
- { \r
- get \r
- { \r
- return ticks.Ticks;\r
- }\r
- }\r
- \r
- public static DateTime Today \r
- {\r
- get \r
- {\r
- return new DateTime (false, (GetNow () / TimeSpan.TicksPerDay) * TimeSpan.TicksPerDay);\r
- }\r
- }\r
-\r
- public static DateTime UtcNow \r
- {\r
- get {\r
- return new DateTime (GetNow ());\r
- }\r
- }\r
-\r
- public int Year \r
- {\r
- get \r
- { \r
- return FromTicks(Which.Year); \r
- }\r
- }\r
-\r
- /* methods */\r
-\r
- public DateTime Add (TimeSpan ts)\r
- {\r
- return new DateTime (true, ticks) + ts;\r
- }\r
-\r
- public DateTime AddDays (double days)\r
- {\r
- return AddMilliseconds (days * 86400000);\r
- }\r
- \r
- public DateTime AddTicks (long t)\r
- {\r
- return Add (new TimeSpan (t));\r
- }\r
-\r
- public DateTime AddHours (double hours)\r
- {\r
- return AddMilliseconds (hours * 3600000);\r
- }\r
-\r
- public DateTime AddMilliseconds (double ms)\r
- {\r
- long msticks;\r
- \r
- msticks = (long) (ms += ms > 0 ? 0.5 : -0.5) * TimeSpan.TicksPerMillisecond ; \r
-\r
- return AddTicks (msticks);\r
- }\r
-\r
- public DateTime AddMinutes (double minutes)\r
- {\r
- return AddMilliseconds (minutes * 60000);\r
- }\r
- \r
- public DateTime AddMonths (int months)\r
- {\r
- int day, month, year, maxday ;\r
- DateTime temp ;\r
-\r
- day = this.Day;\r
- month = this.Month + (months % 12);\r
- year = this.Year + months/12 ;\r
- \r
- if (month < 1)\r
- {\r
- month = 12 + month ;\r
- year -- ;\r
- }\r
- else if (month>12) \r
- {\r
- month = month -12;\r
- year ++;\r
- }\r
- maxday = DaysInMonth(year, month);\r
- if (day > maxday)\r
- day = maxday;\r
-\r
- temp = new DateTime (year, month, day);\r
- return temp.Add (this.TimeOfDay);\r
- }\r
-\r
- public DateTime AddSeconds (double seconds)\r
- {\r
- return AddMilliseconds (seconds*1000);\r
- }\r
-\r
- public DateTime AddYears (int years )\r
- {\r
- return AddMonths(years * 12);\r
- }\r
-\r
- public static int Compare (DateTime t1, DateTime t2)\r
- {\r
- if (t1.ticks < t2.ticks) \r
- return -1;\r
- else if (t1.ticks > t2.ticks) \r
- return 1;\r
- else\r
- return 0;\r
- }\r
-\r
- public int CompareTo (object v)\r
- {\r
- if ( v == null)\r
- return 1;\r
-\r
- if (!(v is System.DateTime))\r
- throw new ArgumentException (Locale.GetText (\r
- "Value is not a System.DateTime"));\r
-\r
- return Compare (this, (DateTime) v);\r
- }\r
-\r
- public static int DaysInMonth (int year, int month)\r
- {\r
- int[] days ;\r
-\r
- if (month < 1 || month >12)\r
- throw new ArgumentOutOfRangeException ();\r
-\r
- days = (IsLeapYear(year) ? daysmonthleap : daysmonth);\r
- return days[month]; \r
- }\r
- \r
- public override bool Equals (object o)\r
- {\r
- if (!(o is System.DateTime))\r
- return false;\r
-\r
- return ((DateTime) o).ticks == ticks;\r
- }\r
-\r
- public static bool Equals (DateTime t1, DateTime t2 )\r
- {\r
- return (t1.ticks == t2.ticks );\r
- }\r
-\r
- public static DateTime FromFileTime (long fileTime) \r
- {\r
- return new DateTime (w32file_epoch + fileTime);\r
- }\r
-\r
- // TODO: Implement me.\r
- [MonoTODO]\r
- public static DateTime FromOADate (double d)\r
- {\r
- return new DateTime(0);\r
- }\r
- \r
- // TODO: Implement me.\r
- [MonoTODO]\r
- public string[] GetDateTimeFormats() \r
- {\r
- return null;\r
- }\r
-\r
- //TODO: implement me\r
- [MonoTODO]\r
- public string[] GetDateTimeFormats(char format)\r
- {\r
- return null;\r
- }\r
- \r
- // TODO: implement me\r
- [MonoTODO]\r
- public string[] GetDateTimeFormats(IFormatProvider provider)\r
- {\r
- return null;\r
- }\r
-\r
- //TODO: implement me \r
- [MonoTODO]\r
- public string[] GetDateTimeFormats(char format,IFormatProvider provider )\r
- {\r
- return null;\r
- }\r
-\r
- public override int GetHashCode ()\r
- {\r
- return (int) ticks.Ticks;\r
- }\r
-\r
- public TypeCode GetTypeCode ()\r
- {\r
- return TypeCode.DateTime;\r
- }\r
-\r
- public static bool IsLeapYear (int year)\r
- {\r
- return ( (year % 4 == 0 && year % 100 != 0) || year % 400 == 0) ;\r
- }\r
-\r
- public static DateTime Parse (string s)\r
- {\r
- return Parse (s, null);\r
- }\r
-\r
- public static DateTime Parse (string s, IFormatProvider fp)\r
- {\r
- return Parse (s, null, DateTimeStyles.AllowWhiteSpaces);\r
- }\r
-\r
- public static DateTime Parse (string s, IFormatProvider fp, DateTimeStyles styles)\r
- {\r
- string[] formats = {\r
- // Full date and time\r
- "F", "G", "r", "s", "u", "U",\r
- // Full date and time, but no seconds\r
- "f", "g",\r
- // Only date\r
- "d", "D",\r
- // Only time\r
- "T", "t",\r
- // Only date, but no year\r
- "m",\r
- // Only date, but no day\r
- "y" \r
- };\r
-\r
- return ParseExact (s, formats, fp, styles);\r
- }\r
-\r
- public static DateTime ParseExact (string s, string format, IFormatProvider fp)\r
- {\r
- return ParseExact (s, format, fp, DateTimeStyles.None);\r
- }\r
-\r
- internal static int _ParseNumber (string s, int digits, bool leadingzero,\r
- bool sloppy_parsing, out int num_parsed)\r
- {\r
- int number = 0, i;\r
-\r
- if (sloppy_parsing)\r
- leadingzero = false;\r
-\r
- if (!leadingzero) {\r
- int real_digits = 0;\r
- for (i = 0; i < s.Length; i++) {\r
- if (!Char.IsDigit (s[i]))\r
- break;\r
-\r
- real_digits++;\r
- }\r
-\r
- digits = real_digits;\r
- }\r
-\r
- if (s.Length < digits) {\r
- num_parsed = -1;\r
- return 0;\r
- }\r
-\r
- for (i = 0; i < digits; i++) {\r
- char c = s[i];\r
- if (!Char.IsDigit (c)) {\r
- num_parsed = -1;\r
- return 0;\r
- }\r
-\r
- number = number * 10 + (byte) (c - '0');\r
- }\r
-\r
- num_parsed = digits;\r
- return number;\r
- }\r
-\r
- internal static int _ParseEnum (string s, string[] values, out int num_parsed)\r
- {\r
- int i;\r
-\r
- for (i = 0; i < values.Length; i++) {\r
- if (s.Length < values[i].Length)\r
- continue;\r
- String tmp = s.Substring (0, values[i].Length);\r
- if (String.Compare (tmp, values[i], true) == 0) {\r
- num_parsed = values[i].Length;\r
- return i;\r
- }\r
- }\r
-\r
- num_parsed = -1;\r
- return -1;\r
- }\r
-\r
- internal static bool _ParseString (string s, int maxlength, string value, out int num_parsed)\r
- {\r
- if (maxlength > 0)\r
- value = value.Substring (0, maxlength);\r
-\r
- s = s.Substring (0, value.Length);\r
-\r
- if (String.Compare (s, value, true) == 0) {\r
- num_parsed = value.Length;\r
- return true;\r
- }\r
-\r
- num_parsed = -1;\r
- return false;\r
- }\r
-\r
- internal static bool _DoParse (string s, string format, bool exact,\r
- out DateTime result,\r
- DateTimeFormatInfo dfi,\r
- DateTimeStyles style)\r
- {\r
- bool useutc = false, use_localtime = true;\r
- bool sloppy_parsing = false;\r
-\r
- if (format.Length == 1)\r
- format = _GetStandardPattern (format[0], dfi, out useutc);\r
-\r
- if ((style & DateTimeStyles.AllowLeadingWhite) != 0) {\r
- format = format.TrimStart (null);\r
- s = s.TrimStart (null);\r
- }\r
-\r
- if ((style & DateTimeStyles.AllowTrailingWhite) != 0) {\r
- format = format.TrimEnd (null);\r
- s = s.TrimEnd (null);\r
- }\r
-\r
- if ((style & DateTimeStyles.AllowInnerWhite) != 0)\r
- sloppy_parsing = true;\r
-\r
- char[] chars = format.ToCharArray ();\r
- int len = format.Length, pos = 0, num = 0;\r
-\r
- int day = -1, dayofweek = -1, month = -1, year = -1;\r
- int hour = -1, minute = -1, second = -1, millisecond = -1;\r
- int ampm = -1;\r
- int tzsign = -1, tzoffset = -1, tzoffmin = -1;\r
-\r
- result = new DateTime (0);\r
- while (pos+num < len)\r
- {\r
- if (s.Length == 0)\r
- break;\r
-\r
- if (Char.IsWhiteSpace (s[0])) {\r
- s = s.Substring (1);\r
-\r
- if (Char.IsWhiteSpace (chars[pos])) {\r
- pos++;\r
- continue;\r
- }\r
-\r
- if ((style & DateTimeStyles.AllowInnerWhite) == 0)\r
- return false;\r
- }\r
-\r
- if (chars[pos] == '\'') {\r
- num = 1;\r
- while (pos+num < len) {\r
- if (chars[pos+num] == '\'')\r
- break;\r
-\r
- if (s.Length == 0)\r
- return false;\r
- if (s[0] != chars[pos+num])\r
- return false;\r
- s = s.Substring (1);\r
-\r
- num++;\r
- }\r
- if (pos+num > len)\r
- return false;\r
-\r
- pos += num + 1;\r
- num = 0;\r
- continue;\r
- } else if (chars[pos] == '\\') {\r
- if (pos+1 >= len)\r
- return false;\r
-\r
- if (s[0] != chars[pos+num])\r
- return false;\r
- s = s.Substring (1);\r
- if (s.Length == 0)\r
- return false;\r
-\r
- pos++;\r
- continue;\r
- } else if (chars[pos] == '%') {\r
- pos++;\r
- continue;\r
- }\r
-\r
- if ((pos+num+1 < len) && (chars[pos+num+1] == chars[pos+num])) {\r
- num++;\r
- continue;\r
- }\r
-\r
- int num_parsed = 0;\r
-\r
- switch (chars[pos])\r
- {\r
- case 'd':\r
- if (day != -1)\r
- return false;\r
- if (num == 0)\r
- day = _ParseNumber (s, 2, false, sloppy_parsing, out num_parsed);\r
- else if (num == 1)\r
- day = _ParseNumber (s, 2, true, sloppy_parsing, out num_parsed);\r
- else if (num == 2)\r
- dayofweek = _ParseEnum (s, dfi.AbbreviatedDayNames, out num_parsed);\r
- else\r
- {\r
- dayofweek = _ParseEnum (s, dfi.DayNames, out num_parsed);\r
- num = 3;\r
- }\r
- break;\r
- case 'M':\r
- if (month != -1)\r
- return false;\r
- if (num == 0)\r
- month = _ParseNumber (s, 2, false, sloppy_parsing, out num_parsed);\r
- else if (num == 1)\r
- month = _ParseNumber (s, 2, true, sloppy_parsing, out num_parsed);\r
- else if (num == 2)\r
- month = _ParseEnum (s, dfi.AbbreviatedMonthNames , out num_parsed) + 1;\r
- else\r
- {\r
- month = _ParseEnum (s, dfi.MonthNames, out num_parsed) + 1;\r
- num = 3;\r
- }\r
- break;\r
- case 'y':\r
- if (year != -1)\r
- return false;\r
- if (num == 0) {\r
- year = _ParseNumber (s, 2, false, sloppy_parsing, out num_parsed);\r
- year += (year < 30) ? 2000 : 1900;\r
- } else if (num < 3) {\r
- year = _ParseNumber (s, 2, true, sloppy_parsing, out num_parsed);\r
- year += (year < 30) ? 2000 : 1900;\r
- } else {\r
- year = _ParseNumber (s, 4, false, sloppy_parsing, out num_parsed);\r
- num = 3;\r
- }\r
- \r
- if (year != 0 && (year < 1 || year > 9999))\r
- throw new ArgumentOutOfRangeException ("year", "Valid " + \r
- "values are between 1 and 9999 inclusive");\r
- break;\r
- case 'h':\r
- if (hour != -1)\r
- return false;\r
- if (num == 0)\r
- hour = _ParseNumber (s, 2, false, sloppy_parsing, out num_parsed);\r
- else\r
- {\r
- hour = _ParseNumber (s, 2, true, sloppy_parsing, out num_parsed);\r
- num = 1;\r
- }\r
-\r
- if (hour >= 12)\r
- return false;\r
-\r
- break;\r
- case 'H':\r
- if ((hour != -1) || (ampm >= 0))\r
- return false;\r
- if (num == 0)\r
- hour = _ParseNumber (s, 2, false, sloppy_parsing, out num_parsed);\r
- else\r
- {\r
- hour = _ParseNumber (s, 2, true, sloppy_parsing, out num_parsed);\r
- num = 1;\r
- }\r
- if (hour >= 24)\r
- return false;\r
-\r
- ampm = -2;\r
- break;\r
- case 'm':\r
- if (minute != -1)\r
- return false;\r
- if (num == 0)\r
- minute = _ParseNumber (s, 2, false, sloppy_parsing, out num_parsed);\r
- else\r
- {\r
- minute = _ParseNumber (s, 2, true, sloppy_parsing, out num_parsed);\r
- num = 1;\r
- }\r
- if (minute >= 60)\r
- return false;\r
-\r
- break;\r
- case 's':\r
- if (second != -1)\r
- return false;\r
- if (num == 0)\r
- second = _ParseNumber (s, 2, false, sloppy_parsing, out num_parsed);\r
- else\r
- {\r
- second = _ParseNumber (s, 2, true, sloppy_parsing, out num_parsed);\r
- num = 1;\r
- }\r
- if (second >= 60)\r
- return false;\r
-\r
- break;\r
- case 'f':\r
- if (millisecond != -1)\r
- return false;\r
- num = Math.Min (num, 6);\r
- millisecond = _ParseNumber (s, num+1, true, sloppy_parsing, out num_parsed);\r
- if (millisecond >= 1000)\r
- return false;\r
- break;\r
- case 't':\r
- if (ampm != -1)\r
- return false;\r
- if (num == 0)\r
- {\r
- if (_ParseString (s, 1, dfi.AMDesignator, out num_parsed))\r
- ampm = 0;\r
- else if (_ParseString (s, 1, dfi.PMDesignator, out num_parsed))\r
- ampm = 1;\r
- else\r
- return false;\r
- }\r
- else\r
- {\r
- if (_ParseString (s, 0, dfi.AMDesignator, out num_parsed))\r
- ampm = 0;\r
- else if (_ParseString (s, 0, dfi.PMDesignator, out num_parsed))\r
- ampm = 1;\r
- else\r
- return false;\r
- num = 1;\r
- }\r
- break;\r
- case 'z':\r
- if (tzsign != -1)\r
- return false;\r
- if (s[0] == '+')\r
- tzsign = 0;\r
- else if (s[0] == '-')\r
- tzsign = 1;\r
- else\r
- return false;\r
- s = s.Substring (1);\r
- if (num == 0)\r
- tzoffset = _ParseNumber (s, 2, false, sloppy_parsing, out num_parsed);\r
- else if (num == 1)\r
- tzoffset = _ParseNumber (s, 2, true, sloppy_parsing, out num_parsed);\r
- else\r
- {\r
- tzoffset = _ParseNumber (s, 2, true, sloppy_parsing, out num_parsed);\r
- if (num_parsed < 0)\r
- return false;\r
- s = s.Substring (num_parsed);\r
- if (!_ParseString (s, 0, dfi.TimeSeparator, out num_parsed))\r
- return false;\r
- s = s.Substring (num_parsed);\r
- tzoffmin = _ParseNumber (s, 2, true, sloppy_parsing, out num_parsed);\r
- if (num_parsed < 0)\r
- return false;\r
- num = 2;\r
- }\r
- break;\r
- case ':':\r
- if (!_ParseString (s, 0, dfi.TimeSeparator, out num_parsed))\r
- return false;\r
- break;\r
- case '/':\r
- if (!_ParseString (s, 0, dfi.DateSeparator, out num_parsed))\r
- return false;\r
- break;\r
- default:\r
- if (s[0] != chars[pos])\r
- return false;\r
- num = 0;\r
- num_parsed = 1;\r
- break;\r
- }\r
-\r
- if (num_parsed < 0)\r
- return false;\r
-\r
- s = s.Substring (num_parsed);\r
-\r
- pos = pos + num + 1;\r
- num = 0;\r
- }\r
-\r
- if (hour == -1)\r
- hour = 0;\r
- if (minute == -1)\r
- minute = 0;\r
- if (second == -1)\r
- second = 0;\r
- if (millisecond == -1)\r
- millisecond = 0;\r
-\r
- // If no date was given\r
- if ((day == -1) && (month == -1) && (year == -1)) {\r
- if ((style & DateTimeStyles.NoCurrentDateDefault) != 0) {\r
- day = 1;\r
- month = 1;\r
- year = 1;\r
- } else {\r
- day = Today.Day;\r
- month = Today.Month;\r
- year = Today.Year;\r
- }\r
- }\r
-\r
- if (day == -1)\r
- day = 1;\r
- if (month == -1)\r
- month = 1;\r
- if (year == -1) {\r
- if ((style & DateTimeStyles.NoCurrentDateDefault) != 0)\r
- year = 1;\r
- else\r
- year = Today.Year;\r
- }\r
-\r
- if (ampm == 1)\r
- hour = hour + 12;\r
-\r
- result = new DateTime (year, month, day, hour, minute, second, millisecond);\r
-\r
- if ((dayofweek != -1) && (dayofweek != (int) result.DayOfWeek))\r
- throw new FormatException (Locale.GetText ("String was not recognized as valid DateTime because the day of week was incorrect."));\r
-\r
- // If no timezone was specified, default to the local timezone.\r
- TimeSpan utcoffset;\r
- if (useutc)\r
- utcoffset = new TimeSpan (0, 0, 0);\r
- else if (tzsign == -1) {\r
- TimeZone tz = TimeZone.CurrentTimeZone;\r
- utcoffset = tz.GetUtcOffset (result);\r
- } else {\r
- if ((style & DateTimeStyles.AdjustToUniversal) != 0)\r
- use_localtime = false;\r
-\r
- if (tzoffmin == -1)\r
- tzoffmin = 0;\r
- if (tzoffset == -1)\r
- tzoffset = 0;\r
- if (tzsign == 1)\r
- tzoffset = -tzoffset;\r
-\r
- utcoffset = new TimeSpan (tzoffset, tzoffmin, 0);\r
- }\r
-\r
- long newticks = (result.ticks - utcoffset).Ticks;\r
-\r
- result = new DateTime (use_localtime, newticks);\r
-\r
- return true;\r
- }\r
-\r
-\r
- public static DateTime ParseExact (string s, string format,\r
- IFormatProvider fp, DateTimeStyles style)\r
- {\r
- string[] formats;\r
-\r
- formats = new string [1];\r
- formats[0] = format;\r
-\r
- return ParseExact (s, formats, fp, style);\r
- }\r
-\r
- public static DateTime ParseExact (string s, string[] formats,\r
- IFormatProvider fp,\r
- DateTimeStyles style)\r
- {\r
- DateTimeFormatInfo dfi = DateTimeFormatInfo.GetInstance (fp);\r
-\r
- if (s == null)\r
- throw new ArgumentNullException (Locale.GetText ("s is null"));\r
- if (formats.Length == 0)\r
- throw new ArgumentNullException (Locale.GetText ("format is null"));\r
-\r
- int i;\r
- for (i = 0; i < formats.Length; i++)\r
- {\r
- DateTime result;\r
-\r
- if (_DoParse (s, formats[i], true, out result, dfi, style))\r
- return result;\r
- }\r
-\r
- throw new FormatException ();\r
- }\r
- \r
- public TimeSpan Subtract(DateTime dt)\r
- { \r
- return new TimeSpan(ticks.Ticks) - dt.ticks;\r
- }\r
-\r
- public DateTime Subtract(TimeSpan ts)\r
- {\r
- TimeSpan newticks;\r
-\r
- newticks = (new TimeSpan (ticks.Ticks)) - ts;\r
- return new DateTime(true,newticks);\r
- }\r
-\r
- public long ToFileTime()\r
- {\r
- if(ticks.Ticks < w32file_epoch) {\r
- throw new ArgumentOutOfRangeException("file time is not valid");\r
- }\r
- \r
- return(ticks.Ticks - w32file_epoch);\r
- }\r
-\r
- public string ToLongDateString()\r
- {\r
- return ToString ("D");\r
- }\r
-\r
- public string ToLongTimeString()\r
- {\r
- return ToString ("T");\r
- }\r
-\r
- [MonoTODO]\r
- public double ToOADate()\r
- {\r
- // TODO implement me \r
- return 0;\r
- }\r
-\r
- public string ToShortDateString()\r
- {\r
- return ToString ("d");\r
- }\r
-\r
- public string ToShortTimeString()\r
- {\r
- return ToString ("t");\r
- }\r
- \r
- public override string ToString ()\r
- {\r
- return ToString ("G", null);\r
- }\r
-\r
- public string ToString (IFormatProvider fp)\r
- {\r
- return ToString (null, fp);\r
- }\r
-\r
- public string ToString (string format)\r
- {\r
- return ToString (format, null);\r
- }\r
-\r
- internal static string _GetStandardPattern (char format, DateTimeFormatInfo dfi, out bool useutc)\r
- {\r
- String pattern;\r
-\r
- useutc = false;\r
-\r
- switch (format)\r
- {\r
- case 'd':\r
- pattern = dfi.ShortDatePattern;\r
- break;\r
- case 'D':\r
- pattern = dfi.LongDatePattern;\r
- break;\r
- case 'f':\r
- pattern = dfi.LongDatePattern + " " + dfi.ShortTimePattern;\r
- break;\r
- case 'F':\r
- pattern = dfi.FullDateTimePattern;\r
- break;\r
- case 'g':\r
- pattern = dfi.ShortDatePattern + " " + dfi.ShortTimePattern;\r
- break;\r
- case 'G':\r
- pattern = dfi.ShortDatePattern + " " + dfi.LongTimePattern;\r
- break;\r
- case 'm':\r
- case 'M':\r
- pattern = dfi.MonthDayPattern;\r
- break;\r
- case 'r':\r
- case 'R':\r
- pattern = dfi.RFC1123Pattern;\r
- // commented by LP 09/jun/2002, rfc 1123 pattern is always in GMT\r
- // useutc= true;\r
- break;\r
- case 's':\r
- pattern = dfi.SortableDateTimePattern;\r
- break;\r
- case 't':\r
- pattern = dfi.ShortTimePattern;\r
- break;\r
- case 'T':\r
- pattern = dfi.LongTimePattern;\r
- break;\r
- case 'u':\r
- pattern = dfi.UniversalSortableDateTimePattern;\r
- useutc = true;\r
- break;\r
- case 'U':\r
- pattern = dfi.LongDatePattern + " " + dfi.LongTimePattern;\r
- useutc = true;\r
- break;\r
- case 'y':\r
- case 'Y':\r
- pattern = dfi.YearMonthPattern;\r
- break;\r
- default:\r
- pattern = null;\r
- break;\r
- }\r
-\r
- return pattern;\r
- }\r
-\r
- internal string _ToString (string format, DateTimeFormatInfo dfi)\r
- {\r
- String str = null, result = null;\r
- char[] chars = format.ToCharArray ();\r
- int len = format.Length, pos = 0, num = 0;\r
-\r
- TimeZone tz = TimeZone.CurrentTimeZone;\r
- TimeSpan utcoffset = tz.GetUtcOffset (this);\r
-\r
- while (pos < len)\r
- {\r
- if (chars[pos] == '\'') {\r
- num = 1;\r
- while (pos+num <= len) {\r
- if (chars[pos+num] == '\'')\r
- break;\r
-\r
- result += chars[pos+num];\r
- num++;\r
- }\r
- if (pos+num > len)\r
- throw new FormatException (Locale.GetText ("The specified format is invalid"));\r
-\r
- pos += num+1;\r
- num = 0;\r
- continue;\r
- } else if (chars[pos] == '\\') {\r
- if (pos+1 >= len)\r
- throw new FormatException (Locale.GetText ("The specified format is invalid"));\r
-\r
- result += chars[pos+1];\r
- pos += 2;\r
- continue;\r
- } else if (chars[pos] == '%') {\r
- pos++;\r
- continue;\r
- }\r
-\r
- if ((pos+num+1 < len) && (chars[pos+num+1] == chars[pos+num])) {\r
- num++;\r
- continue;\r
- }\r
-\r
- switch (chars[pos])\r
- {\r
- case 'd':\r
- if (num == 0)\r
- str = Day.ToString ("d");\r
- else if (num == 1)\r
- str = Day.ToString ("d02");\r
- else if (num == 2)\r
- str = dfi.GetAbbreviatedDayName (DayOfWeek);\r
- else {\r
- str = dfi.GetDayName (DayOfWeek);\r
- num = 3;\r
- }\r
- break;\r
- case 'M':\r
- if (num == 0)\r
- str = Month.ToString ("d");\r
- else if (num == 1)\r
- str = Month.ToString ("d02");\r
- else if (num == 2)\r
- str = dfi.GetAbbreviatedMonthName (Month);\r
- else {\r
- str = dfi.GetMonthName (Month);\r
- num = 3;\r
- }\r
- break;\r
- case 'y':\r
- if (num == 0) {\r
- int shortyear = Year % 100;\r
- str = shortyear.ToString ("d");\r
- } else if (num == 1) {\r
- int shortyear = Year % 100;\r
- str = shortyear.ToString ("d02");\r
- } else {\r
- str = Year.ToString ("d");\r
- num = 3;\r
- }\r
- break;\r
- case 'g':\r
- // FIXME\r
- break;\r
- case 'f':\r
- num = Math.Min (num, 6);\r
-\r
- long ms = (long) Millisecond;\r
- long exp = 10;\r
- for (int i = 0; i < num; i++)\r
- exp = exp * 10;\r
- long maxexp = TimeSpan.TicksPerMillisecond;\r
-\r
- exp = Math.Min (exp, maxexp);\r
- ms = ms * exp / maxexp;\r
-\r
- String prec = (num+1).ToString ("d02");\r
- str = ms.ToString (String.Concat ("d", prec));\r
-\r
- break;\r
- case 'h':\r
- if (num == 0) {\r
- int shorthour = Hour % 12;\r
- str = shorthour.ToString ("d");\r
- } else {\r
- int shorthour = Hour % 12;\r
- str = shorthour.ToString ("d02");\r
- num = 1;\r
- }\r
- break;\r
- case 'H':\r
- if (num == 0)\r
- str = Hour.ToString ("d");\r
- else {\r
- str = Hour.ToString ("d02");\r
- num = 1;\r
- }\r
- break;\r
- case 'm':\r
- if (num == 0)\r
- str = Minute.ToString ("d");\r
- else {\r
- str = Minute.ToString ("d02");\r
- num = 1;\r
- }\r
- break;\r
- case 's':\r
- if (num == 0)\r
- str = Second.ToString ("d");\r
- else {\r
- str = Second.ToString ("d02");\r
- num = 1;\r
- }\r
- break;\r
- case 't':\r
- if (Hour < 12)\r
- str = dfi.AMDesignator;\r
- else\r
- str = dfi.PMDesignator;\r
-\r
- if (num == 0)\r
- str = str.Substring (0,1);\r
- else\r
- num = 1;\r
- break;\r
- case 'z':\r
- if (num == 0) {\r
- int offset = utcoffset.Hours;\r
- str = offset.ToString ("d");\r
- if (offset > 0)\r
- str = String.Concat ("+", str);\r
- } else if (num == 1) {\r
- int offset = utcoffset.Hours;\r
- str = offset.ToString ("d02");\r
- if (offset > 0)\r
- str = String.Concat ("+", str);\r
- } else if (num == 2) {\r
- int offhour = utcoffset.Hours;\r
- int offminute = utcoffset.Minutes;\r
- str = offhour.ToString ("d02");\r
- str = String.Concat (str, dfi.TimeSeparator);\r
- str = String.Concat (str, offminute.ToString ("d02"));\r
- if (offhour > 0)\r
- str = String.Concat ("+", str);\r
- num = 2;\r
- }\r
- break;\r
- case ':':\r
- str = dfi.TimeSeparator;\r
- num = 0;\r
- break;\r
- case '/':\r
- str = dfi.DateSeparator;\r
- num = 0;\r
- break;\r
- default:\r
- str = String.Concat (chars [pos]);\r
- num = 0;\r
- break;\r
- }\r
-\r
- result = String.Concat (result, str);\r
- \r
- pos += num + 1;\r
- num = 0;\r
- }\r
-\r
- return result;\r
- }\r
-\r
- public string ToString (string format, IFormatProvider fp)\r
- {\r
- DateTimeFormatInfo dfi = DateTimeFormatInfo.GetInstance(fp);\r
-\r
- if (format == null)\r
- format = dfi.FullDateTimePattern;\r
-\r
- bool useutc = false;\r
-\r
- if (format.Length == 1) {\r
- char fchar = (format.ToCharArray ())[0];\r
- format = _GetStandardPattern (fchar, dfi, out useutc);\r
- }\r
-\r
- if (useutc)\r
- return this.ToUniversalTime ()._ToString (format, dfi);\r
- else\r
- return this._ToString (format, dfi);\r
- }\r
-\r
- public DateTime ToLocalTime()\r
- {\r
- TimeZone tz = TimeZone.CurrentTimeZone;\r
-\r
- TimeSpan offset = tz.GetUtcOffset (this);\r
-\r
- return new DateTime (true, ticks + offset);\r
- }\r
-\r
- public DateTime ToUniversalTime()\r
- {\r
- TimeZone tz = TimeZone.CurrentTimeZone;\r
-\r
- TimeSpan offset = tz.GetUtcOffset (this);\r
-\r
- return new DateTime (true, ticks - offset);\r
- }\r
-\r
- /* OPERATORS */\r
-\r
- public static DateTime operator +(DateTime d, TimeSpan t)\r
- {\r
- return new DateTime (true, d.ticks + t);\r
- }\r
-\r
- public static bool operator ==(DateTime d1, DateTime d2)\r
- {\r
- return (d1.ticks == d2.ticks);\r
- }\r
-\r
- public static bool operator >(DateTime t1,DateTime t2)\r
- {\r
- return (t1.ticks > t2.ticks);\r
- }\r
-\r
- public static bool operator >=(DateTime t1,DateTime t2)\r
- {\r
- return (t1.ticks >= t2.ticks);\r
- }\r
-\r
- public static bool operator !=(DateTime d1, DateTime d2)\r
- {\r
- return (d1.ticks != d2.ticks);\r
- }\r
-\r
- public static bool operator <(DateTime t1, DateTime t2)\r
- {\r
- return (t1.ticks < t2.ticks );\r
- }\r
-\r
- public static bool operator <=(DateTime t1,DateTime t2)\r
- {\r
- return (t1.ticks <= t2.ticks);\r
- }\r
-\r
- public static TimeSpan operator -(DateTime d1,DateTime d2)\r
- {\r
- return new TimeSpan((d1.ticks - d2.ticks).Ticks);\r
- }\r
-\r
- public static DateTime operator -(DateTime d,TimeSpan t)\r
- {\r
- return new DateTime (true, d.ticks - t);\r
- }\r
-\r
- bool IConvertible.ToBoolean(IFormatProvider provider)\r
- {\r
- throw new InvalidCastException();\r
- }\r
- \r
- byte IConvertible.ToByte(IFormatProvider provider)\r
- {\r
- throw new InvalidCastException();\r
- }\r
-\r
- char IConvertible.ToChar(IFormatProvider provider)\r
- {\r
- throw new InvalidCastException();\r
- }\r
-\r
- // TODO Implement me\r
- [MonoTODO]\r
- public System.DateTime ToDateTime(IFormatProvider provider)\r
- {\r
- return new System.DateTime(true,this.ticks);\r
- } \r
- \r
- decimal IConvertible.ToDecimal(IFormatProvider provider)\r
- {\r
- throw new InvalidCastException();\r
- }\r
-\r
- double IConvertible.ToDouble(IFormatProvider provider)\r
- {\r
- throw new InvalidCastException();\r
- }\r
-\r
- Int16 IConvertible.ToInt16(IFormatProvider provider)\r
- {\r
- throw new InvalidCastException();\r
- }\r
-\r
- Int32 IConvertible.ToInt32(IFormatProvider provider)\r
- {\r
- throw new InvalidCastException();\r
- }\r
-\r
- Int64 IConvertible.ToInt64(IFormatProvider provider)\r
- {\r
- throw new InvalidCastException();\r
- }\r
-\r
- [CLSCompliant(false)]\r
- SByte IConvertible.ToSByte(IFormatProvider provider)\r
- {\r
- throw new InvalidCastException();\r
- }\r
-\r
- Single IConvertible.ToSingle(IFormatProvider provider)\r
- {\r
- throw new InvalidCastException();\r
- }\r
-\r
- object IConvertible.ToType(Type conversionType,IFormatProvider provider)\r
- {\r
- throw new InvalidCastException();\r
- }\r
-\r
- UInt16 IConvertible.ToUInt16(IFormatProvider provider)\r
- {\r
- throw new InvalidCastException();\r
- }\r
- \r
- [CLSCompliant(false)]\r
- UInt32 IConvertible.ToUInt32(IFormatProvider provider)\r
- {\r
- throw new InvalidCastException();\r
- }\r
-\r
- [CLSCompliant(false)]\r
- UInt64 IConvertible.ToUInt64(IFormatProvider provider)\r
- {\r
- throw new InvalidCastException();\r
- }\r
- }\r
-}\r
-\r
-namespace System\r
-{\r
- public enum DayOfWeek\r
- {\r
- Sunday,\r
- Monday,\r
- Tuesday,\r
- Wednesday,\r
- Thursday,\r
- Friday,\r
- Saturday\r
- }\r
-}\r
+//
+// System.DateTime.cs
+//
+// author:
+// Marcel Narings (marcel@narings.nl)
+// Martin Baulig (martin@gnome.org)
+// Atsushi Enomoto (atsushi@ximian.com)
+//
+// (C) 2001 Marcel Narings
+
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace System
+{
+ /// <summary>
+ /// The DateTime structure represents dates and time ranging from
+ /// 1-1-0001 12:00:00 AM to 31-12-9999 23:59:00 Common Era.
+ /// </summary>
+ ///
+ [Serializable]
+ [StructLayout (LayoutKind.Auto)]
+ public struct DateTime : IFormattable, IConvertible,
+#if NET_2_0
+ IComparable, IComparable<DateTime>
+#else
+ IComparable
+#endif
+ {
+ private TimeSpan ticks;
+
+ private const int dp400 = 146097;
+ private const int dp100 = 36524;
+ private const int dp4 = 1461;
+
+ // w32 file time starts counting from 1/1/1601 00:00 GMT
+ // which is the constant ticks from the .NET epoch
+ private const long w32file_epoch = 504911232000000000L;
+
+ //private const long MAX_VALUE_TICKS = 3155378975400000000L;
+ // -- Microsoft .NET has this value.
+ private const long MAX_VALUE_TICKS = 3155378975999999999L;
+
+ //
+ // The UnixEpoch, it begins on Jan 1, 1970 at 0:0:0, expressed
+ // in Ticks
+ //
+ internal const long UnixEpoch = 621355968000000000L;
+
+ // for OLE Automation dates
+ private const long ticks18991230 = 599264352000000000L;
+ private const double OAMinValue = -657435.0d;
+ private const double OAMaxValue = 2958466.0d;
+
+ public static readonly DateTime MaxValue = new DateTime (false, MAX_VALUE_TICKS);
+ public static readonly DateTime MinValue = new DateTime (false, 0);
+
+ private static readonly string[] commonFormats = {
+ // For compatibility with MS's CLR, this format (which
+ // doesn't have a one-letter equivalent) is parsed
+ // too. It's important because it's used in XML
+ // serialization.
+
+ // Note that those format should be tried only for
+ // invalid patterns;
+
+ // FIXME: SOME OF those patterns looks tried against
+ // the current culture, since some patterns fail in
+ // some culture.
+
+ "yyyy-MM-dd",
+ "yyyy-MM-ddTHH:mm:sszzz",
+ "yyyy-MM-ddTHH:mm:ss.fffffff",
+ "yyyy-MM-ddTHH:mm:ss.fffffffzzz",
+ // UTC / allow any separator
+ "yyyy/MM/ddTHH:mm:ssZ",
+ "yyyy/M/dZ",
+ // bug #58938
+ "yyyy/M/d HH:mm:ss",
+ // bug #47720
+ "yyyy/MM/dd HH:mm:ss 'GMT'",
+ // Close to RFC1123, but without 'GMT'
+ "ddd, d MMM yyyy HH:mm:ss",
+ // use UTC ('Z'; not literal "'Z'")
+ // FIXME: 1078(af-ZA) and 1079(ka-GE) reject it
+ "yyyy/MM/dd HH':'mm':'ssZ",
+
+ // DayOfTheWeek, dd full_month_name yyyy
+ // FIXME: 1054(th-TH) rejects it
+ "dddd, dd MMMM yyyy",
+ // DayOfTheWeek, dd yyyy. This works for every locales.
+ "MMMM dd, yyyy",
+#if NET_1_1
+ // X509Certificate pattern is accepted by Parse() *in every culture*
+ "yyyyMMddHHmmssZ",
+#endif
+ // In Parse() the 'r' equivalent pattern is first parsed as universal time
+ "ddd, dd MMM yyyy HH':'mm':'ss 'GMT'",
+/*
+ // Full date and time
+ "F", "G", "r", "s", "u", "U",
+ // Full date and time, but no seconds
+ "f", "g",
+ // Only date
+ "d", "D",
+ // Only time
+ "T", "t",
+ // Only date, but no year
+ "m",
+ // Only date, but no day
+ "y"
+*/
+ };
+
+ private enum Which
+ {
+ Day,
+ DayYear,
+ Month,
+ Year
+ };
+
+ private static readonly int[] daysmonth = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+ private static readonly int[] daysmonthleap = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+ private static int AbsoluteDays (int year, int month, int day)
+ {
+ int[] days;
+ int temp = 0, m=1 ;
+
+
+
+
+
+ days = (IsLeapYear(year) ? daysmonthleap : daysmonth);
+
+ while (m < month)
+ temp += days[m++];
+ return ((day-1) + temp + (365* (year-1)) + ((year-1)/4) - ((year-1)/100) + ((year-1)/400));
+ }
+
+ private int FromTicks(Which what)
+ {
+ int num400, num100, num4, numyears;
+ int M =1;
+
+ int[] days = daysmonth;
+ int totaldays = this.ticks.Days;
+
+ num400 = (totaldays / dp400);
+ totaldays -= num400 * dp400;
+
+ num100 = (totaldays / dp100);
+ if (num100 == 4) // leap
+ num100 = 3;
+ totaldays -= (num100 * dp100);
+
+ num4 = totaldays / dp4;
+ totaldays -= (num4 * dp4);
+
+ numyears = totaldays / 365 ;
+
+ if (numyears == 4) //leap
+ numyears =3 ;
+ if (what == Which.Year )
+ return num400*400 + num100*100 + num4*4 + numyears + 1;
+
+ totaldays -= (numyears * 365) ;
+ if (what == Which.DayYear )
+ return totaldays + 1;
+
+ if ((numyears==3) && ((num100 == 3) || !(num4 == 24)) ) //31 dec leapyear
+ days = daysmonthleap;
+
+ while (totaldays >= days[M])
+ totaldays -= days[M++];
+
+ if (what == Which.Month )
+ return M;
+
+ return totaldays +1;
+ }
+
+
+ // Constructors
+
+ /// <summary>
+ /// Constructs a DateTime for specified ticks
+ /// </summary>
+ ///
+ public DateTime (long newticks)
+ // `local' must default to false here to avoid
+ // a recursion loop.
+ : this (false, newticks) {}
+
+ internal DateTime (bool local, long newticks)
+ {
+ ticks = new TimeSpan (newticks);
+ if (local) {
+ TimeZone tz = TimeZone.CurrentTimeZone;
+
+ TimeSpan utcoffset = tz.GetUtcOffset (this);
+
+ ticks = ticks + utcoffset;
+ }
+ if (ticks.Ticks < MinValue.Ticks || ticks.Ticks > MaxValue.Ticks)
+ throw new ArgumentOutOfRangeException ();
+ }
+
+ public DateTime (int year, int month, int day)
+ : this (year, month, day,0,0,0,0) {}
+
+ public DateTime (int year, int month, int day, int hour, int minute, int second)
+ : this (year, month, day, hour, minute, second, 0) {}
+
+ public DateTime (int year, int month, int day, int hour, int minute, int second, int millisecond)
+ {
+ if ( year < 1 || year > 9999 ||
+ month < 1 || month >12 ||
+ day < 1 || day > DaysInMonth(year, month) ||
+ hour < 0 || hour > 23 ||
+ minute < 0 || minute > 59 ||
+ second < 0 || second > 59 ||
+ millisecond < 0 || millisecond > 999)
+ throw new ArgumentOutOfRangeException ("Parameters describe an " +
+ "unrepresentable DateTime.");
+
+ ticks = new TimeSpan (AbsoluteDays(year,month,day), hour, minute, second, millisecond);
+ }
+
+ public DateTime (int year, int month, int day, Calendar calendar)
+ : this (year, month, day, 0, 0, 0, 0, calendar) {}
+
+
+ public DateTime (int year, int month, int day, int hour, int minute, int second, Calendar calendar)
+ : this (year, month, day, hour, minute, second, 0, calendar) {}
+
+
+ public DateTime (int year, int month, int day, int hour, int minute, int second, int millisecond, Calendar calendar)
+ : this (year, month, day, hour, minute, second, millisecond)
+ {
+ if (calendar == null)
+ throw new ArgumentNullException();
+ }
+
+ internal DateTime (bool check, TimeSpan value)
+ {
+ if (check && (value.Ticks < MinValue.Ticks || value.Ticks > MaxValue.Ticks))
+ throw new ArgumentOutOfRangeException ();
+
+ ticks = value;
+ }
+
+ /* Properties */
+
+ public DateTime Date
+ {
+ get
+ {
+ return new DateTime (Year, Month, Day);
+ }
+ }
+
+ public int Month
+ {
+ get
+ {
+ return FromTicks(Which.Month);
+ }
+ }
+
+
+ public int Day
+ {
+ get
+ {
+ return FromTicks(Which.Day);
+ }
+ }
+
+ public DayOfWeek DayOfWeek
+ {
+ get
+ {
+ return ( (DayOfWeek) ((ticks.Days+1) % 7) );
+ }
+ }
+
+ public int DayOfYear
+ {
+ get
+ {
+ return FromTicks(Which.DayYear);
+ }
+ }
+
+ public TimeSpan TimeOfDay
+ {
+ get
+ {
+ return new TimeSpan(ticks.Ticks % TimeSpan.TicksPerDay );
+ }
+
+ }
+
+ public int Hour
+ {
+ get
+ {
+ return ticks.Hours;
+ }
+ }
+
+ public int Minute
+ {
+ get
+ {
+ return ticks.Minutes;
+ }
+ }
+
+ public int Second
+ {
+ get
+ {
+ return ticks.Seconds;
+ }
+ }
+
+ public int Millisecond
+ {
+ get
+ {
+ return ticks.Milliseconds;
+ }
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern long GetNow ();
+
+ public static DateTime Now
+ {
+ get
+ {
+ return new DateTime (true, GetNow ());
+ }
+ }
+
+ public long Ticks
+ {
+ get
+ {
+ return ticks.Ticks;
+ }
+ }
+
+ public static DateTime Today
+ {
+ get {
+ DateTime now = Now;
+ return new DateTime (now.Year, now.Month, now.Day);
+ }
+ }
+
+ public static DateTime UtcNow
+ {
+ get {
+ return new DateTime (GetNow ());
+ }
+ }
+
+ public int Year
+ {
+ get
+ {
+ return FromTicks(Which.Year);
+ }
+ }
+
+ /* methods */
+
+ public DateTime Add (TimeSpan ts)
+ {
+ return AddTicks (ts.Ticks);
+ }
+
+ public DateTime AddDays (double days)
+ {
+ return AddMilliseconds (Math.Round (days * 86400000));
+ }
+
+ public DateTime AddTicks (long t)
+ {
+ if ((t + ticks.Ticks) > MAX_VALUE_TICKS || (t + ticks.Ticks) < 0) {
+ throw new ArgumentOutOfRangeException();
+ }
+ return new DateTime (t + ticks.Ticks);
+ }
+
+ public DateTime AddHours (double hours)
+ {
+ return AddMilliseconds (hours * 3600000);
+ }
+
+ public DateTime AddMilliseconds (double ms)
+ {
+ if ((ms * TimeSpan.TicksPerMillisecond) > long.MaxValue ||
+ (ms * TimeSpan.TicksPerMillisecond) < long.MinValue) {
+ throw new ArgumentOutOfRangeException();
+ }
+ long msticks = (long) (ms * TimeSpan.TicksPerMillisecond);
+
+ return AddTicks (msticks);
+ }
+
+ // required to match MS implementation for OADate (OLE Automation)
+ private DateTime AddRoundedMilliseconds (double ms)
+ {
+ if ((ms * TimeSpan.TicksPerMillisecond) > long.MaxValue ||
+ (ms * TimeSpan.TicksPerMillisecond) < long.MinValue) {
+ throw new ArgumentOutOfRangeException ();
+ }
+ long msticks = (long) (ms += ms > 0 ? 0.5 : -0.5) * TimeSpan.TicksPerMillisecond;
+
+ return AddTicks (msticks);
+ }
+
+ public DateTime AddMinutes (double minutes)
+ {
+ return AddMilliseconds (minutes * 60000);
+ }
+
+ public DateTime AddMonths (int months)
+ {
+ int day, month, year, maxday ;
+ DateTime temp ;
+
+ day = this.Day;
+ month = this.Month + (months % 12);
+ year = this.Year + months/12 ;
+
+ if (month < 1)
+ {
+ month = 12 + month ;
+ year -- ;
+ }
+ else if (month>12)
+ {
+ month = month -12;
+ year ++;
+ }
+ maxday = DaysInMonth(year, month);
+ if (day > maxday)
+ day = maxday;
+
+ temp = new DateTime (year, month, day);
+ return temp.Add (this.TimeOfDay);
+ }
+
+ public DateTime AddSeconds (double seconds)
+ {
+ return AddMilliseconds (seconds*1000);
+ }
+
+ public DateTime AddYears (int years )
+ {
+ return AddMonths(years * 12);
+ }
+
+ public static int Compare (DateTime t1, DateTime t2)
+ {
+ if (t1.ticks < t2.ticks)
+ return -1;
+ else if (t1.ticks > t2.ticks)
+ return 1;
+ else
+ return 0;
+ }
+
+ public int CompareTo (object v)
+ {
+ if ( v == null)
+ return 1;
+
+ if (!(v is System.DateTime))
+ throw new ArgumentException (Locale.GetText (
+ "Value is not a System.DateTime"));
+
+ return Compare (this, (DateTime) v);
+ }
+
+#if NET_2_0
+ public int CompareTo (DateTime value)
+ {
+ return Compare (this, value);
+ }
+
+ public bool Equals (DateTime value)
+ {
+ return value.ticks == ticks;
+ }
+#endif
+
+ public static int DaysInMonth (int year, int month)
+ {
+ int[] days ;
+
+ if (month < 1 || month >12)
+ throw new ArgumentOutOfRangeException ();
+
+ days = (IsLeapYear(year) ? daysmonthleap : daysmonth);
+ return days[month];
+ }
+
+ public override bool Equals (object o)
+ {
+ if (!(o is System.DateTime))
+ return false;
+
+ return ((DateTime) o).ticks == ticks;
+ }
+
+ public static bool Equals (DateTime t1, DateTime t2 )
+ {
+ return (t1.ticks == t2.ticks );
+ }
+
+ public static DateTime FromFileTime (long fileTime)
+ {
+ if (fileTime < 0)
+ throw new ArgumentOutOfRangeException ("fileTime", "< 0");
+
+ return new DateTime (true, w32file_epoch + fileTime);
+ }
+
+#if NET_1_1
+ public static DateTime FromFileTimeUtc (long fileTime)
+ {
+ if (fileTime < 0)
+ throw new ArgumentOutOfRangeException ("fileTime", "< 0");
+
+ return new DateTime (false, w32file_epoch + fileTime);
+ }
+#endif
+
+ public static DateTime FromOADate (double d)
+ {
+ // An OLE Automation date is implemented as a floating-point number
+ // whose value is the number of days from midnight, 30 December 1899.
+
+ // d must be negative 657435.0 through positive 2958466.0.
+ if ((d <= OAMinValue) || (d >= OAMaxValue))
+ throw new ArgumentException ("d", "[-657435,2958466]");
+
+ DateTime dt = new DateTime (ticks18991230);
+ if (d < 0.0d) {
+ Double days = Math.Ceiling (d);
+ // integer part is the number of days (negative)
+ dt = dt.AddRoundedMilliseconds (days * 86400000);
+ // but decimals are the number of hours (in days fractions) and positive
+ Double hours = (days - d);
+ dt = dt.AddRoundedMilliseconds (hours * 86400000);
+ }
+ else {
+ dt = dt.AddRoundedMilliseconds (d * 86400000);
+ }
+
+ return dt;
+ }
+
+ public string[] GetDateTimeFormats()
+ {
+ return GetDateTimeFormats (CultureInfo.CurrentCulture);
+ }
+
+ public string[] GetDateTimeFormats(char format)
+ {
+ if ("dDgGfFmMrRstTuUyY".IndexOf (format) < 0)
+ throw new FormatException ("Invalid format character.");
+ string[] result = new string[1];
+ result[0] = this.ToString(format.ToString());
+ return result;
+ }
+
+ public string[] GetDateTimeFormats(IFormatProvider provider)
+ {
+ DateTimeFormatInfo info = (DateTimeFormatInfo) provider.GetFormat (typeof(DateTimeFormatInfo));
+// return GetDateTimeFormats (info.GetAllDateTimePatterns ());
+ ArrayList al = new ArrayList ();
+ foreach (char c in "dDgGfFmMrRstTuUyY")
+ al.AddRange (GetDateTimeFormats (c, info));
+ return al.ToArray (typeof (string)) as string [];
+ }
+
+ public string[] GetDateTimeFormats(char format,IFormatProvider provider )
+ {
+ if ("dDgGfFmMrRstTuUyY".IndexOf (format) < 0)
+ throw new FormatException ("Invalid format character.");
+
+ // LAMESPEC: There is NO assurance that 'U' ALWAYS
+ // euqals to 'F', but since we have to iterate all
+ // the pattern strings, we cannot just use
+ // ToString("U", provider) here. I believe that the
+ // method's behavior cannot be formalized.
+ bool adjustutc = false;
+ switch (format) {
+ case 'U':
+// case 'r':
+// case 'R':
+// case 'u':
+ adjustutc = true;
+ break;
+ }
+ DateTimeFormatInfo info = (DateTimeFormatInfo) provider.GetFormat (typeof(DateTimeFormatInfo));
+ return GetDateTimeFormats (adjustutc, info.GetAllDateTimePatterns (format), info);
+ }
+
+ private string [] GetDateTimeFormats (bool adjustutc, string [] patterns, DateTimeFormatInfo dfi)
+ {
+ string [] results = new string [patterns.Length];
+ DateTime val = adjustutc ? ToUniversalTime () : this;
+ for (int i = 0; i < results.Length; i++)
+ results [i] = val._ToString (patterns [i], dfi);
+ return results;
+ }
+
+ public override int GetHashCode ()
+ {
+ return (int) ticks.Ticks;
+ }
+
+ public TypeCode GetTypeCode ()
+ {
+ return TypeCode.DateTime;
+ }
+
+ public static bool IsLeapYear (int year)
+ {
+ return ( (year % 4 == 0 && year % 100 != 0) || year % 400 == 0) ;
+ }
+
+ public static DateTime Parse (string s)
+ {
+ return Parse (s, null);
+ }
+
+ public static DateTime Parse (string s, IFormatProvider fp)
+ {
+ return Parse (s, fp, DateTimeStyles.AllowWhiteSpaces);
+ }
+
+ [MonoTODO ("see the comments inline")]
+ public static DateTime Parse (string s, IFormatProvider fp, DateTimeStyles styles)
+ {
+ // This method should try only expected patterns.
+ // Should not try extra patterns.
+ // Right now we also try InvariantCulture, but I
+ // confirmed in some cases this method rejects what
+ // InvariantCulture supports (can be checked against
+ // "th-TH" with Gregorian Calendar). So basically it
+ // should not be done.
+ // I think it should be CurrentCulture to be tested,
+ // but right now we don't support all the supported
+ // patterns for each culture, so try InvariantCulture
+ // as a quick remedy.
+ if (s == null)
+ throw new ArgumentNullException (Locale.GetText ("s is null"));
+ DateTime result;
+
+ if (fp == null)
+ fp = CultureInfo.CurrentCulture;
+ DateTimeFormatInfo dfi = DateTimeFormatInfo.GetInstance (fp);
+
+ bool longYear = false;
+ // Try common formats.
+ if (ParseExact (s, commonFormats, dfi, styles, out result, false, ref longYear))
+ return result;
+
+ // Try common formats, also with invariant culture
+ if (ParseExact (s, commonFormats, DateTimeFormatInfo.InvariantInfo, styles, out result, false, ref longYear))
+ return result;
+
+ // Next, try all the patterns
+ string [] patterns = new string [] {"d", "D", "g", "G", "f", "F", "m", "M", "r", "R", "s", "t", "T", "u", "U", "y", "Y"};
+
+ if (ParseExact (s, patterns, dfi, styles, out result, false, ref longYear))
+ return result;
+
+ if (longYear) {
+ throw new ArgumentOutOfRangeException ("year",
+ "Valid values are between 1 and 9999 inclusive");
+ }
+
+ throw new FormatException ("String was not recognized as a valid DateTime.");
+ }
+
+ public static DateTime ParseExact (string s, string format, IFormatProvider fp)
+ {
+ return ParseExact (s, format, fp, DateTimeStyles.None);
+ }
+
+ internal static int _ParseNumber (string s, int valuePos,
+ int digits,
+ bool leadingzero,
+ bool sloppy_parsing,
+ bool next_not_digit,
+ out int num_parsed)
+ {
+ int number = 0, i;
+
+ if (sloppy_parsing)
+ leadingzero = false;
+
+ if (!leadingzero) {
+ int real_digits = 0;
+ for (i = valuePos; i < s.Length && i < digits + valuePos; i++) {
+ if (!Char.IsDigit (s[i]))
+ break;
+
+ real_digits++;
+ }
+
+ digits = real_digits;
+ }
+
+ if (s.Length - valuePos < digits) {
+ num_parsed = -1;
+ return 0;
+ }
+
+ if (s.Length - valuePos > digits &&
+ next_not_digit &&
+ Char.IsDigit (s[digits + valuePos])) {
+ /* More digits left over */
+ num_parsed = -1;
+ return(0);
+ }
+
+ for (i = valuePos; i < digits + valuePos; i++) {
+ char c = s[i];
+ if (!Char.IsDigit (c)) {
+ num_parsed = -1;
+ return 0;
+ }
+
+ number = number * 10 + (byte) (c - '0');
+ }
+
+ num_parsed = digits;
+ return number;
+ }
+
+ internal static int _ParseEnum (string s, int sPos, string[] values, out int num_parsed)
+ {
+ int i;
+
+ for (i = 0; i < values.Length; i++) {
+ if (s.Length - sPos < values[i].Length)
+ continue;
+ else if (values [i].Length == 0)
+ continue;
+ String tmp = s.Substring (sPos, values[i].Length);
+ if (String.Compare (tmp, values[i], true) == 0) {
+ num_parsed = values[i].Length;
+ return i;
+ }
+ }
+
+ num_parsed = -1;
+ return -1;
+ }
+
+ internal static bool _ParseString (string s, int sPos, int maxlength, string value, out int num_parsed)
+ {
+ if (maxlength <= 0)
+ maxlength = value.Length;
+
+ if (String.Compare (s, sPos, value, 0, maxlength, true, CultureInfo.InvariantCulture) == 0) {
+ num_parsed = maxlength;
+ return true;
+ }
+
+ num_parsed = -1;
+ return false;
+ }
+
+ private static bool _DoParse (string s, string format, bool exact,
+ out DateTime result,
+ DateTimeFormatInfo dfi,
+ DateTimeStyles style,
+ ref bool longYear)
+ {
+ bool useutc = false, use_localtime = true;
+ bool use_invariant = false;
+ bool sloppy_parsing = false;
+ int valuePos = 0;
+ if (format.Length == 1)
+ format = _GetStandardPattern (format [0], dfi, out useutc, out use_invariant);
+ else if (!exact && format.IndexOf ("GMT") >= 0)
+ useutc = true;
+
+ if ((style & DateTimeStyles.AllowLeadingWhite) != 0) {
+ format = format.TrimStart (null);
+
+ s = s.TrimStart (null); // it could be optimized, but will make little good.
+ }
+
+ if ((style & DateTimeStyles.AllowTrailingWhite) != 0) {
+ format = format.TrimEnd (null);
+ s = s.TrimEnd (null); // it could be optimized, but will make little good.
+ }
+
+ if (use_invariant)
+ dfi = DateTimeFormatInfo.InvariantInfo;
+
+ if ((style & DateTimeStyles.AllowInnerWhite) != 0)
+ sloppy_parsing = true;
+
+ string chars = format;
+ int len = format.Length, pos = 0, num = 0;
+
+ int day = -1, dayofweek = -1, month = -1, year = -1;
+ int hour = -1, minute = -1, second = -1;
+ double fractionalSeconds = -1;
+ int ampm = -1;
+ int tzsign = -1, tzoffset = -1, tzoffmin = -1;
+ bool next_not_digit;
+
+ result = new DateTime (0);
+ while (pos+num < len)
+ {
+ if (s.Length == valuePos)
+ break;
+
+ if (chars[pos] == '\'') {
+ num = 1;
+ while (pos+num < len) {
+ if (chars[pos+num] == '\'')
+ break;
+
+ if (valuePos == s.Length)
+ return false;
+ if (s [valuePos] != chars [pos + num])
+ return false;
+ valuePos++;
+
+ num++;
+ }
+ if (pos+num > len)
+ return false;
+
+ pos += num + 1;
+ num = 0;
+ continue;
+ } else if (chars[pos] == '"') {
+ num = 1;
+ while (pos+num < len) {
+ if (chars[pos+num] == '"')
+ break;
+
+ if (valuePos == s.Length)
+ return false;
+ if (s [valuePos] != chars[pos+num])
+ return false;
+ valuePos++;
+
+ num++;
+ }
+ if (pos+num > len)
+ return false;
+
+ pos += num + 1;
+ num = 0;
+ continue;
+ } else if (chars[pos] == '\\') {
+ if (pos+1 >= len)
+ return false;
+
+ if (s [valuePos] != chars [pos + num])
+ return false;
+ valuePos++;
+ if (valuePos == s.Length)
+ return false;
+
+ pos++;
+ continue;
+ } else if (chars[pos] == '%') {
+ pos++;
+ continue;
+ } else if (Char.IsWhiteSpace (s [valuePos])) {
+ valuePos++;
+
+ if (Char.IsWhiteSpace (chars[pos])) {
+ pos++;
+ continue;
+ }
+
+ if (exact && (style & DateTimeStyles.AllowInnerWhite) == 0)
+ return false;
+ int ws = valuePos;
+ while (ws < s.Length) {
+ if (Char.IsWhiteSpace (s [ws]))
+ ws++;
+ else
+ break;
+ }
+ valuePos = ws;
+ }
+
+
+ if ((pos+num+1 < len) && (chars[pos+num+1] == chars[pos+num])) {
+ num++;
+ continue;
+ }
+
+ int num_parsed = 0;
+
+ if (pos+num+1 < len) {
+ char next_char = chars[pos+num+1];
+
+ next_not_digit = !(next_char == 'd' ||
+ next_char == 'M' ||
+ next_char == 'y' ||
+ next_char == 'h' ||
+ next_char == 'H' ||
+ next_char == 'm' ||
+ next_char == 's' ||
+ next_char == 'f' ||
+ next_char == 'z' ||
+ next_char == '"' ||
+ next_char == '\'' ||
+ Char.IsDigit (next_char));
+ } else {
+ next_not_digit = true;
+ }
+
+ switch (chars[pos])
+ {
+ case 'd':
+ if (day != -1)
+ return false;
+ if (num == 0)
+ day = _ParseNumber (s, valuePos, 2, false, sloppy_parsing, next_not_digit, out num_parsed);
+ else if (num == 1)
+ day = _ParseNumber (s, valuePos, 2, true, sloppy_parsing, next_not_digit, out num_parsed);
+ else if (num == 2)
+ dayofweek = _ParseEnum (s, valuePos, dfi.AbbreviatedDayNames, out num_parsed);
+ else
+ {
+ dayofweek = _ParseEnum (s, valuePos, dfi.DayNames, out num_parsed);
+ num = 3;
+ }
+ break;
+ case 'M':
+ if (month != -1)
+ return false;
+ if (num == 0)
+ month = _ParseNumber (s, valuePos, 2, false, sloppy_parsing, next_not_digit, out num_parsed);
+ else if (num == 1)
+ month = _ParseNumber (s, valuePos, 2, true, sloppy_parsing, next_not_digit, out num_parsed);
+ else if (num == 2)
+ month = _ParseEnum (s, valuePos, dfi.AbbreviatedMonthNames , out num_parsed) + 1;
+ else
+ {
+ month = _ParseEnum (s, valuePos, dfi.MonthNames, out num_parsed) + 1;
+ num = 3;
+ }
+ break;
+ case 'y':
+ if (year != -1)
+ return false;
+
+ if (num == 0) {
+ year = _ParseNumber (s, valuePos, 2, false, sloppy_parsing, next_not_digit, out num_parsed);
+ } else if (num < 3) {
+ year = _ParseNumber (s, valuePos, 2, true, sloppy_parsing, next_not_digit, out num_parsed);
+ } else {
+ year = _ParseNumber (s, valuePos, 4, false, sloppy_parsing, next_not_digit, out num_parsed);
+ if ((year >= 1000) && (num_parsed == 4) && (!longYear) && (s.Length > 4 + valuePos)) {
+ int np = 0;
+ int ly = _ParseNumber (s, valuePos, 5, false, sloppy_parsing, next_not_digit, out np);
+ longYear = (ly > 9999);
+ }
+ num = 3;
+ }
+
+ //FIXME: We should do use dfi.Calendat.TwoDigitYearMax
+ if (num_parsed <= 2)
+ year += (year < 30) ? 2000 : 1900;
+ break;
+ case 'h':
+ if (hour != -1)
+ return false;
+ if (num == 0)
+ hour = _ParseNumber (s, valuePos, 2, false, sloppy_parsing, next_not_digit, out num_parsed);
+ else
+ {
+ hour = _ParseNumber (s, valuePos, 2, true, sloppy_parsing, next_not_digit, out num_parsed);
+ num = 1;
+ }
+
+ if (hour > 12)
+ return false;
+ if (hour == 12)
+ hour = 0;
+
+ break;
+ case 'H':
+ if ((hour != -1) || (ampm >= 0))
+ return false;
+ if (num == 0)
+ hour = _ParseNumber (s, valuePos, 2, false, sloppy_parsing, next_not_digit, out num_parsed);
+ else
+ {
+ hour = _ParseNumber (s, valuePos, 2, true, sloppy_parsing, next_not_digit, out num_parsed);
+ num = 1;
+ }
+ if (hour >= 24)
+ return false;
+
+ ampm = -2;
+ break;
+ case 'm':
+ if (minute != -1)
+ return false;
+ if (num == 0)
+ minute = _ParseNumber (s, valuePos, 2, false, sloppy_parsing, next_not_digit, out num_parsed);
+ else
+ {
+ minute = _ParseNumber (s, valuePos, 2, true, sloppy_parsing, next_not_digit, out num_parsed);
+ num = 1;
+ }
+ if (minute >= 60)
+ return false;
+
+ break;
+ case 's':
+ if (second != -1)
+ return false;
+ if (num == 0)
+ second = _ParseNumber (s, valuePos, 2, false, sloppy_parsing, next_not_digit, out num_parsed);
+ else
+ {
+ second = _ParseNumber (s, valuePos, 2, true, sloppy_parsing, next_not_digit, out num_parsed);
+ num = 1;
+ }
+ if (second >= 60)
+ return false;
+
+ break;
+ case 'f':
+ if (fractionalSeconds != -1)
+ return false;
+ num = Math.Min (num, 6);
+ double decimalNumber = (double) _ParseNumber (s, valuePos, num+1, true, sloppy_parsing, next_not_digit, out num_parsed);
+ if (num_parsed == -1)
+ return false;
+
+ else
+ fractionalSeconds = decimalNumber / Math.Pow(10.0, num_parsed);
+ break;
+ case 't':
+ if (ampm != -1)
+ return false;
+ if (num == 0)
+ {
+ if (_ParseString (s, valuePos, 1, dfi.AMDesignator, out num_parsed))
+ ampm = 0;
+ else if (_ParseString (s, valuePos, 1, dfi.PMDesignator, out num_parsed))
+ ampm = 1;
+ else
+ return false;
+ }
+ else
+ {
+ if (_ParseString (s, valuePos, 0, dfi.AMDesignator, out num_parsed))
+ ampm = 0;
+ else if (_ParseString (s, valuePos, 0, dfi.PMDesignator, out num_parsed))
+ ampm = 1;
+ else
+ return false;
+ num = 1;
+ }
+ break;
+ case 'z':
+ if (tzsign != -1)
+ return false;
+ if (s [valuePos] == '+')
+ tzsign = 0;
+ else if (s [valuePos] == '-')
+ tzsign = 1;
+ else
+ return false;
+ valuePos++;
+ if (num == 0)
+ tzoffset = _ParseNumber (s, valuePos, 2, false, sloppy_parsing, next_not_digit, out num_parsed);
+ else if (num == 1)
+ tzoffset = _ParseNumber (s, valuePos, 2, true, sloppy_parsing, false, out num_parsed);
+ else
+ {
+ tzoffset = _ParseNumber (s, valuePos, 2, true, sloppy_parsing, next_not_digit, out num_parsed);
+ if (num_parsed < 0)
+ return false;
+ valuePos += num_parsed;
+ if (Char.IsDigit (s [valuePos]))
+ num_parsed = 0;
+ else if (!_ParseString (s, valuePos, 0, dfi.TimeSeparator, out num_parsed))
+ return false;
+ valuePos += num_parsed;
+ tzoffmin = _ParseNumber (s, valuePos, 2, true, sloppy_parsing, false, out num_parsed);
+ if (num_parsed < 0)
+ return false;
+ num = 2;
+ }
+ break;
+
+ // LAMESPEC: This should be part of UTCpattern
+ // string and thus should not be considered here.
+ //
+ // Note that 'Z' is not defined as a pattern
+ // character. Keep it for X509 certificate
+ // verification. Also, "Z" != "'Z'" under MS.NET
+ // ("'Z'" is just literal; handled above)
+ case 'Z':
+ if (s [valuePos] != 'Z')
+ return false;
+ num = 0;
+ num_parsed = 1;
+ useutc = true;
+ break;
+
+ case ':':
+ if (!_ParseString (s, valuePos, 0, dfi.TimeSeparator, out num_parsed))
+ return false;
+ break;
+ case '/':
+ /* Accept any character for
+ * DateSeparator, except
+ * TimeSeparator, a digit or a
+ * letter. Not documented,
+ * but seems to be MS
+ * behaviour here. See bug
+ * 54047.
+ */
+ if (exact && s [valuePos] != '/')
+ return false;
+
+ if (_ParseString (s, valuePos, 0,
+ dfi.TimeSeparator,
+ out num_parsed) ||
+ Char.IsDigit (s [valuePos]) ||
+ Char.IsLetter (s [valuePos])) {
+ return(false);
+ }
+
+ num = 0;
+ if (num_parsed <= 0) {
+ num_parsed = 1;
+ }
+
+ break;
+ default:
+ if (s [valuePos] != chars[pos]) {
+ // FIXME: It is not sure, but
+ // IsLetter() is introduced
+ // because we have to reject
+ // "2002a02b25" but have to
+ // allow "2002$02$25". The same
+ // thing applies to '/' case.
+ if (exact ||
+ Char.IsDigit (s [valuePos]) ||
+ Char.IsLetter (s [valuePos]))
+ return false;
+ }
+ num = 0;
+ num_parsed = 1;
+ break;
+ }
+
+ if (num_parsed < 0)
+ return false;
+
+ valuePos += num_parsed;
+
+ if (!exact) {
+ switch (chars [pos]) {
+ case 'm':
+ case 's':
+ case 'f':
+ case 'z':
+ if (s.Length > valuePos && s [valuePos] == 'Z'
+ && (pos + 1 == chars.Length
+ || chars [pos + 1] != 'Z')) {
+ useutc = true;
+ valuePos++;
+ }
+ break;
+ }
+ }
+
+ pos = pos + num + 1;
+ num = 0;
+ }
+
+ if (exact && pos < len)
+ return false;
+
+ if (s.Length != valuePos) // extraneous tail.
+ return false;
+
+ if (hour == -1)
+ hour = 0;
+ if (minute == -1)
+ minute = 0;
+
+ if (second == -1)
+ second = 0;
+ if (fractionalSeconds == -1)
+ fractionalSeconds = 0;
+
+ // If no date was given
+ if ((day == -1) && (month == -1) && (year == -1)) {
+ if ((style & DateTimeStyles.NoCurrentDateDefault) != 0) {
+ day = 1;
+ month = 1;
+ year = 1;
+ } else {
+ day = Today.Day;
+ month = Today.Month;
+ year = Today.Year;
+ }
+ }
+
+
+ if (day == -1)
+ day = 1;
+ if (month == -1)
+ month = 1;
+ if (year == -1) {
+ if ((style & DateTimeStyles.NoCurrentDateDefault) != 0)
+ year = 1;
+ else
+ year = Today.Year;
+ }
+
+ if (ampm == 1)
+ hour = hour + 12;
+
+ // For anything out of range
+ // return false
+ if ( year < 1 || year > 9999 ||
+ month < 1 || month >12 ||
+ day < 1 || day > DaysInMonth(year, month) ||
+ hour < 0 || hour > 23 ||
+ minute < 0 || minute > 59 ||
+ second < 0 || second > 59 )
+ return false;
+
+ result = new DateTime (year, month, day, hour, minute, second, 0);
+ result = result.AddSeconds(fractionalSeconds);
+
+//Console.WriteLine ("**** Parsed as {1} {0} {2}", new object [] {useutc ? "[u]" : "", format, use_localtime ? "[lt]" : ""});
+ if ((dayofweek != -1) && (dayofweek != (int) result.DayOfWeek))
+ throw new FormatException (Locale.GetText ("String was not recognized as valid DateTime because the day of week was incorrect."));
+
+ // If no timezone was specified, default to the local timezone.
+ TimeSpan utcoffset;
+
+ if (useutc)
+ utcoffset = new TimeSpan (0, 0, 0);
+ else if (tzsign == -1) {
+ TimeZone tz = TimeZone.CurrentTimeZone;
+ utcoffset = tz.GetUtcOffset (result);
+ } else {
+ if ((style & DateTimeStyles.AdjustToUniversal) != 0)
+ use_localtime = false;
+
+ if (tzoffmin == -1)
+ tzoffmin = 0;
+ if (tzoffset == -1)
+ tzoffset = 0;
+ if (tzsign == 1)
+ tzoffset = -tzoffset;
+
+ utcoffset = new TimeSpan (tzoffset, tzoffmin, 0);
+ }
+
+ long newticks = (result.ticks - utcoffset).Ticks;
+
+ result = new DateTime (use_localtime, newticks);
+
+ return true;
+ }
+
+
+ public static DateTime ParseExact (string s, string format,
+ IFormatProvider fp, DateTimeStyles style)
+ {
+ string[] formats;
+
+ formats = new string [1];
+ formats[0] = format;
+
+ return ParseExact (s, formats, fp, style);
+ }
+
+ public static DateTime ParseExact (string s, string[] formats,
+ IFormatProvider fp,
+ DateTimeStyles style)
+ {
+ DateTimeFormatInfo dfi = DateTimeFormatInfo.GetInstance (fp);
+
+ if (s == null)
+ throw new ArgumentNullException (Locale.GetText ("s is null"));
+ if (formats == null || formats.Length == 0)
+ throw new ArgumentNullException (Locale.GetText ("format is null"));
+
+ DateTime result;
+ bool longYear = false;
+ if (!ParseExact (s, formats, dfi, style, out result, true, ref longYear))
+ throw new FormatException ();
+ return result;
+ }
+
+ private static bool ParseExact (string s, string [] formats,
+ DateTimeFormatInfo dfi, DateTimeStyles style, out DateTime ret,
+ bool exact, ref bool longYear)
+ {
+ int i;
+ for (i = 0; i < formats.Length; i++)
+ {
+ DateTime result;
+
+ if (_DoParse (s, formats[i], exact, out result, dfi, style, ref longYear)) {
+ ret = result;
+ return true;
+ }
+ }
+ ret = DateTime.MinValue;
+ return false;
+ }
+
+ public TimeSpan Subtract(DateTime dt)
+ {
+ return new TimeSpan(ticks.Ticks) - dt.ticks;
+ }
+
+ public DateTime Subtract(TimeSpan ts)
+ {
+ TimeSpan newticks;
+
+ newticks = (new TimeSpan (ticks.Ticks)) - ts;
+ return new DateTime(true,newticks);
+ }
+
+ public long ToFileTime()
+ {
+ DateTime universalTime = ToUniversalTime();
+
+ if (universalTime.Ticks < w32file_epoch) {
+ throw new ArgumentOutOfRangeException("file time is not valid");
+ }
+
+ return(universalTime.Ticks - w32file_epoch);
+ }
+
+#if NET_1_1
+ public long ToFileTimeUtc()
+ {
+ if (Ticks < w32file_epoch) {
+ throw new ArgumentOutOfRangeException("file time is not valid");
+ }
+
+ return (Ticks - w32file_epoch);
+ }
+#endif
+
+ public string ToLongDateString()
+ {
+ return ToString ("D");
+ }
+
+ public string ToLongTimeString()
+ {
+ return ToString ("T");
+ }
+
+ public double ToOADate ()
+ {
+ long t = this.Ticks;
+ // uninitialized DateTime case
+ if (t == 0)
+ return 0;
+ // we can't reach minimum value
+ if (t < 31242239136000000)
+ return OAMinValue + 0.001;
+
+ TimeSpan ts = new TimeSpan (this.Ticks - ticks18991230);
+ double result = ts.TotalDays;
+ // t < 0 (where 599264352000000000 == 0.0d for OA)
+ if (t < 599264352000000000) {
+ // negative days (int) but decimals are positive
+ double d = Math.Ceiling (result);
+ result = d - 2 - (result - d);
+ }
+ else {
+ // we can't reach maximum value
+ if (result >= OAMaxValue)
+ result = OAMaxValue - 0.00000001d;
+ }
+ return result;
+ }
+
+ public string ToShortDateString()
+ {
+ return ToString ("d");
+ }
+
+ public string ToShortTimeString()
+ {
+ return ToString ("t");
+ }
+
+ public override string ToString ()
+ {
+ return ToString ("G", null);
+ }
+
+ public string ToString (IFormatProvider fp)
+ {
+ return ToString (null, fp);
+ }
+
+ public string ToString (string format)
+ {
+ return ToString (format, null);
+ }
+
+ internal static string _GetStandardPattern (char format, DateTimeFormatInfo dfi, out bool useutc, out bool use_invariant)
+ {
+ String pattern;
+
+ useutc = false;
+ use_invariant = false;
+
+ switch (format)
+ {
+ case 'd':
+ pattern = dfi.ShortDatePattern;
+ break;
+ case 'D':
+ pattern = dfi.LongDatePattern;
+ break;
+ case 'f':
+ pattern = dfi.LongDatePattern + " " + dfi.ShortTimePattern;
+ break;
+ case 'F':
+ pattern = dfi.FullDateTimePattern;
+ break;
+ case 'g':
+ pattern = dfi.ShortDatePattern + " " + dfi.ShortTimePattern;
+ break;
+ case 'G':
+ pattern = dfi.ShortDatePattern + " " + dfi.LongTimePattern;
+ break;
+ case 'm':
+ case 'M':
+ pattern = dfi.MonthDayPattern;
+ break;
+ case 'r':
+ case 'R':
+ pattern = dfi.RFC1123Pattern;
+ // commented by LP 09/jun/2002, rfc 1123 pattern is always in GMT
+ // uncommented by AE 27/may/2004
+// useutc = true;
+ use_invariant = true;
+ break;
+ case 's':
+ pattern = dfi.SortableDateTimePattern;
+ break;
+ case 't':
+ pattern = dfi.ShortTimePattern;
+ break;
+ case 'T':
+ pattern = dfi.LongTimePattern;
+ break;
+ case 'u':
+ pattern = dfi.UniversalSortableDateTimePattern;
+ useutc = true;
+ break;
+ case 'U':
+// pattern = dfi.LongDatePattern + " " + dfi.LongTimePattern;
+ pattern = dfi.FullDateTimePattern;
+ useutc = true;
+ break;
+ case 'y':
+ case 'Y':
+ pattern = dfi.YearMonthPattern;
+ break;
+ default:
+ pattern = null;
+ break;
+ }
+
+ return pattern;
+ }
+
+ internal string _ToString (string format, DateTimeFormatInfo dfi)
+ {
+ // the length of the format is usually a good guess of the number
+ // of chars in the result. Might save us a few bytes sometimes
+ // Add + 10 for cases like mmmm dddd
+ StringBuilder result = new StringBuilder (format.Length + 10);
+
+ // For some cases, the output should not use culture dependent calendar
+ DateTimeFormatInfo inv = DateTimeFormatInfo.InvariantInfo;
+ if (format == inv.RFC1123Pattern)
+ dfi = inv;
+ else if (format == inv.UniversalSortableDateTimePattern)
+ dfi = inv;
+
+ int i = 0;
+
+ while (i < format.Length) {
+ int tokLen;
+ char ch = format [i];
+
+ switch (ch) {
+
+ //
+ // Time Formats
+ //
+ case 'h':
+ // hour, [1, 12]
+ tokLen = CountRepeat (format, i, ch);
+
+ int hr = this.Hour % 12;
+ if (hr == 0)
+ hr = 12;
+
+ ZeroPad (result, hr, tokLen == 1 ? 1 : 2);
+ break;
+ case 'H':
+ // hour, [0, 23]
+ tokLen = CountRepeat (format, i, ch);
+ ZeroPad (result, this.Hour, tokLen == 1 ? 1 : 2);
+ break;
+ case 'm':
+ // minute, [0, 59]
+ tokLen = CountRepeat (format, i, ch);
+ ZeroPad (result, this.Minute, tokLen == 1 ? 1 : 2);
+ break;
+ case 's':
+ // second [0, 29]
+ tokLen = CountRepeat (format, i, ch);
+ ZeroPad (result, this.Second, tokLen == 1 ? 1 : 2);
+ break;
+ case 'f':
+ // fraction of second, to same number of
+ // digits as there are f's
+
+ tokLen = CountRepeat (format, i, ch);
+ if (tokLen > 7)
+ throw new FormatException ("Invalid Format String");
+
+ int dec = (int)((long)(this.Ticks % TimeSpan.TicksPerSecond) / (long) Math.Pow (10, 7 - tokLen));
+ ZeroPad (result, dec, tokLen);
+
+ break;
+ case 't':
+ // AM/PM. t == first char, tt+ == full
+ tokLen = CountRepeat (format, i, ch);
+ string desig = this.Hour < 12 ? dfi.AMDesignator : dfi.PMDesignator;
+
+ if (tokLen == 1) {
+ if (desig.Length >= 1)
+ result.Append (desig [0]);
+ }
+ else
+ result.Append (desig);
+
+ break;
+ case 'z':
+ // timezone. t = +/-h; tt = +/-hh; ttt+=+/-hh:mm
+ tokLen = CountRepeat (format, i, ch);
+ TimeSpan offset = TimeZone.CurrentTimeZone.GetUtcOffset (this);
+
+ if (offset.Ticks >= 0)
+ result.Append ('+');
+ else
+ result.Append ('-');
+
+ switch (tokLen) {
+ case 1:
+ result.Append (Math.Abs (offset.Hours));
+ break;
+ case 2:
+ result.Append (Math.Abs (offset.Hours).ToString ("00"));
+ break;
+ default:
+ result.Append (Math.Abs (offset.Hours).ToString ("00"));
+ result.Append (':');
+ result.Append (Math.Abs (offset.Minutes).ToString ("00"));
+ break;
+ }
+ break;
+ //
+ // Date tokens
+ //
+ case 'd':
+ // day. d(d?) = day of month (leading 0 if two d's)
+ // ddd = three leter day of week
+ // dddd+ full day-of-week
+ tokLen = CountRepeat (format, i, ch);
+
+ if (tokLen <= 2)
+ ZeroPad (result, dfi.Calendar.GetDayOfMonth (this), tokLen == 1 ? 1 : 2);
+ else if (tokLen == 3)
+ result.Append (dfi.GetAbbreviatedDayName (dfi.Calendar.GetDayOfWeek (this)));
+ else
+ result.Append (dfi.GetDayName (dfi.Calendar.GetDayOfWeek (this)));
+
+ break;
+ case 'M':
+ // Month.m(m?) = month # (with leading 0 if two mm)
+ // mmm = 3 letter name
+ // mmmm+ = full name
+ tokLen = CountRepeat (format, i, ch);
+ int month = dfi.Calendar.GetMonth(this);
+ if (tokLen <= 2)
+ ZeroPad (result, month, tokLen);
+ else if (tokLen == 3)
+ result.Append (dfi.GetAbbreviatedMonthName (month));
+ else
+ result.Append (dfi.GetMonthName (month));
+
+ break;
+ case 'y':
+ // Year. y(y?) = two digit year, with leading 0 if yy
+ // yyy+ full year, if yyy and yr < 1000, displayed as three digits
+ tokLen = CountRepeat (format, i, ch);
+
+ if (tokLen <= 2)
+ ZeroPad (result, dfi.Calendar.GetYear (this) % 100, tokLen);
+ else
+ ZeroPad (result, dfi.Calendar.GetYear (this), (tokLen == 3 ? 3 : 4));
+
+ break;
+ case 'g':
+ // Era name
+ tokLen = CountRepeat (format, i, ch);
+ result.Append (dfi.GetEraName (dfi.Calendar.GetEra (this)));
+ break;
+
+ //
+ // Other
+ //
+ case ':':
+ result.Append (dfi.TimeSeparator);
+ tokLen = 1;
+ break;
+ case '/':
+ result.Append (dfi.DateSeparator);
+ tokLen = 1;
+ break;
+ case '\'': case '"':
+ tokLen = ParseQuotedString (format, i, result);
+ break;
+ case '%':
+ if (i >= format.Length - 1)
+ throw new FormatException ("% at end of date time string");
+ if (format [i + 1] == '%')
+ throw new FormatException ("%% in date string");
+
+ // Look for the next char
+ tokLen = 1;
+ break;
+ case '\\':
+ // C-Style escape
+ if (i >= format.Length - 1)
+ throw new FormatException ("\\ at end of date time string");
+
+ result.Append (format [i + 1]);
+ tokLen = 2;
+
+ break;
+ default:
+ // catch all
+ result.Append (ch);
+ tokLen = 1;
+ break;
+ }
+ i += tokLen;
+ }
+ return result.ToString ();
+ }
+
+ static int CountRepeat (string fmt, int p, char c)
+ {
+ int l = fmt.Length;
+ int i = p + 1;
+ while ((i < l) && (fmt [i] == c))
+ i++;
+
+ return i - p;
+ }
+
+ static int ParseQuotedString (string fmt, int pos, StringBuilder output)
+ {
+ // pos == position of " or '
+
+ int len = fmt.Length;
+ int start = pos;
+ char quoteChar = fmt [pos++];
+
+ while (pos < len) {
+ char ch = fmt [pos++];
+
+ if (ch == quoteChar)
+ return pos - start;
+
+ if (ch == '\\') {
+ // C-Style escape
+ if (pos >= len)
+ throw new FormatException("Un-ended quote");
+
+ output.Append (fmt [pos++]);
+ } else {
+ output.Append (ch);
+ }
+ }
+
+ throw new FormatException("Un-ended quote");
+ }
+
+ static unsafe void ZeroPad (StringBuilder output, int digits, int len)
+ {
+ // more than enough for an int
+ char* buffer = stackalloc char [16];
+ int pos = 16;
+
+ do {
+ buffer [-- pos] = (char) ('0' + digits % 10);
+ digits /= 10;
+ len --;
+ } while (digits > 0);
+
+ while (len -- > 0)
+ buffer [-- pos] = '0';
+
+ output.Append (new string (buffer, pos, 16 - pos));
+ }
+
+ public string ToString (string format, IFormatProvider fp)
+
+ {
+ DateTimeFormatInfo dfi = DateTimeFormatInfo.GetInstance(fp);
+
+ if (format == null)
+ format = "G";
+
+ bool useutc = false, use_invariant = false;
+
+ if (format.Length == 1) {
+ char fchar = format [0];
+ format = _GetStandardPattern (fchar, dfi, out useutc, out use_invariant);
+ }
+
+ // Don't convert UTC value. It just adds 'Z' for
+ // 'u' format, for the same ticks.
+ return this._ToString (format, dfi);
+ }
+
+ public DateTime ToLocalTime()
+ {
+ TimeZone tz = TimeZone.CurrentTimeZone;
+
+ TimeSpan offset = tz.GetUtcOffset (this);
+
+ if (offset.Ticks > 0) {
+ if (DateTime.MaxValue - offset < this)
+ return DateTime.MaxValue;
+ } else if (offset.Ticks < 0) {
+ // MS.NET fails to check validity here
+ // - it may throw ArgumentOutOfRangeException
+ /*
+ if (DateTime.MinValue - offset > this)
+ return DateTime.MinValue;
+ */
+ }
+
+ DateTime lt = new DateTime(true, ticks+offset);
+ TimeSpan ltoffset = tz.GetUtcOffset(lt);
+ if(ltoffset != offset)
+ lt = lt.Add(ltoffset.Subtract(offset));
+
+ return lt;
+ }
+
+ public DateTime ToUniversalTime()
+ {
+ TimeZone tz = TimeZone.CurrentTimeZone;
+
+ TimeSpan offset = tz.GetUtcOffset (this);
+
+ if (offset.Ticks < 0) {
+ if (DateTime.MaxValue + offset < this)
+ return DateTime.MaxValue;
+ } else if (offset.Ticks > 0) {
+ if (DateTime.MinValue + offset > this)
+ return DateTime.MinValue;
+ }
+
+ return new DateTime (false, ticks - offset);
+ }
+
+ /* OPERATORS */
+
+ public static DateTime operator +(DateTime d, TimeSpan t)
+ {
+ return new DateTime (true, d.ticks + t);
+ }
+
+ public static bool operator ==(DateTime d1, DateTime d2)
+ {
+ return (d1.ticks == d2.ticks);
+ }
+
+ public static bool operator >(DateTime t1,DateTime t2)
+ {
+ return (t1.ticks > t2.ticks);
+ }
+
+ public static bool operator >=(DateTime t1,DateTime t2)
+ {
+ return (t1.ticks >= t2.ticks);
+ }
+
+ public static bool operator !=(DateTime d1, DateTime d2)
+ {
+ return (d1.ticks != d2.ticks);
+ }
+
+ public static bool operator <(DateTime t1, DateTime t2)
+ {
+ return (t1.ticks < t2.ticks );
+ }
+
+ public static bool operator <=(DateTime t1,DateTime t2)
+ {
+ return (t1.ticks <= t2.ticks);
+ }
+
+ public static TimeSpan operator -(DateTime d1,DateTime d2)
+ {
+ return new TimeSpan((d1.ticks - d2.ticks).Ticks);
+ }
+
+ public static DateTime operator -(DateTime d,TimeSpan t)
+ {
+ return new DateTime (true, d.ticks - t);
+ }
+
+ bool IConvertible.ToBoolean(IFormatProvider provider)
+ {
+ throw new InvalidCastException();
+ }
+
+ byte IConvertible.ToByte(IFormatProvider provider)
+ {
+ throw new InvalidCastException();
+
+ }
+
+ char IConvertible.ToChar(IFormatProvider provider)
+ {
+ throw new InvalidCastException();
+ }
+
+ System.DateTime IConvertible.ToDateTime(IFormatProvider provider)
+ {
+ return this;
+ }
+
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
+ {
+ throw new InvalidCastException();
+ }
+
+ double IConvertible.ToDouble(IFormatProvider provider)
+ {
+ throw new InvalidCastException();
+ }
+
+ Int16 IConvertible.ToInt16(IFormatProvider provider)
+ {
+ throw new InvalidCastException();
+ }
+
+ Int32 IConvertible.ToInt32(IFormatProvider provider)
+ {
+ throw new InvalidCastException();
+ }
+
+ Int64 IConvertible.ToInt64(IFormatProvider provider)
+ {
+ throw new InvalidCastException();
+ }
+
+ SByte IConvertible.ToSByte(IFormatProvider provider)
+ {
+ throw new InvalidCastException();
+ }
+
+ Single IConvertible.ToSingle(IFormatProvider provider)
+ {
+ throw new InvalidCastException();
+ }
+
+ object IConvertible.ToType (Type conversionType, IFormatProvider provider)
+ {
+ if (conversionType == null)
+ throw new ArgumentNullException ("conversionType");
+
+ if (conversionType == typeof (DateTime))
+ return this;
+ else if (conversionType == typeof (String))
+ return this.ToString (provider);
+ else if (conversionType == typeof (Object))
+ return this;
+ else
+ throw new InvalidCastException();
+ }
+
+ UInt16 IConvertible.ToUInt16(IFormatProvider provider)
+ {
+ throw new InvalidCastException();
+ }
+
+ UInt32 IConvertible.ToUInt32(IFormatProvider provider)
+ {
+ throw new InvalidCastException();
+ }
+
+ UInt64 IConvertible.ToUInt64(IFormatProvider provider)
+ {
+ throw new InvalidCastException();
+ }
+ }
+}
+
+namespace System
+{
+ public enum DayOfWeek
+ {
+ Sunday,
+ Monday,
+ Tuesday,
+ Wednesday,
+ Thursday,
+ Friday,
+ Saturday
+ }
+}