+++ /dev/null
-//
-// System.DateTime.cs
-//
-// Authors:
-// Marcel Narings (marcel@narings.nl)
-// Martin Baulig (martin@gnome.org)
-// Atsushi Enomoto (atsushi@ximian.com)
-// Marek Safar (marek.safar@gmail.com)
-//
-// (C) 2001 Marcel Narings
-// Copyright (C) 2004-2006 Novell, Inc (http://www.novell.com)
-// Copyright (C) 2012 Xamarin Inc (http://www.xamarin.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.Collections.Generic;
-using System.Globalization;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Text;
-using System.Runtime.Serialization;
-
-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, IComparable, ISerializable, IComparable<DateTime>, IEquatable <DateTime>
- {
- //
- // Encodes the DateTime in 64 bits, top two bits contain the DateTimeKind,
- // the rest contains the 62 bit value for the ticks. This reduces the
- // memory usage from 16 to 8 bytes, see bug: 592221. This also fixes the
- // 622127 issue and simplifies the code in reflection.c to encode DateTimes
- //
- long encoded;
- const long TicksMask = 0x3fffffffffffffff;
- const long KindMask = unchecked ((long) 0xc000000000000000);
- const int KindShift = 62;
-
- 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 (3155378975999999999);
- public static readonly DateTime MinValue = new DateTime (0);
-
- // DateTime.Parse patterns
- // Patterns are divided to date and time patterns. The algorithm will
- // try combinations of these patterns. The algorithm also looks for
- // day of the week, AM/PM GMT and Z independently of the patterns.
- private static readonly string[] ParseTimeFormats = new string [] {
- "H:m:s.fff zzz",
- "H:m:s.fffffffzzz",
- "H:m:s.fffffff",
- "H:m:s.ffffff",
- "H:m:s.ffffffzzz",
- "H:m:s.fffff",
- "H:m:s.ffff",
- "H:m:s.fff",
- "H:m:s.ff",
- "H:m:s.f",
- "H:m:s tt zzz",
- "H:m:szzz",
- "H:m:s",
- "H:mzzz",
- "H:m",
- "H tt", // Specifies AM to disallow '8'.
- "H'\u6642'm'\u5206's'\u79D2'"
- };
-
- // DateTime.Parse date patterns extend ParseExact patterns as follows:
- // MMM - month short name or month full name
- // MMMM - month number or short name or month full name
-
- // Parse behaves differently according to the ShorDatePattern of the
- // DateTimeFormatInfo. The following define the date patterns for
- // different orders of day, month and year in ShorDatePattern.
- // Note that the year cannot go between the day and the month.
- private static readonly string[] ParseYearDayMonthFormats = new string [] {
- "yyyy/M/dT",
- "M/yyyy/dT",
- "yyyy'\u5E74'M'\u6708'd'\u65E5",
-
-
- "yyyy/d/MMMM",
- "yyyy/MMM/d",
- "d/MMMM/yyyy",
- "MMM/d/yyyy",
- "d/yyyy/MMMM",
- "MMM/yyyy/d",
-
- "yy/d/M",
- };
-
- private static readonly string[] ParseYearMonthDayFormats = new string [] {
- "yyyy/M/dT",
- "M/yyyy/dT",
- "yyyy'\u5E74'M'\u6708'd'\u65E5",
-
- "yyyy/MMMM/d",
- "yyyy/d/MMM",
- "MMMM/d/yyyy",
- "d/MMM/yyyy",
- "MMMM/yyyy/d",
- "d/yyyy/MMM",
-
- "yy/MMMM/d",
- "yy/d/MMM",
- "MMM/yy/d",
- };
-
- private static readonly string[] ParseDayMonthYearFormats = new string [] {
- "yyyy/M/dT",
- "M/yyyy/dT",
- "yyyy'\u5E74'M'\u6708'd'\u65E5",
-
- "yyyy/MMMM/d",
- "yyyy/d/MMM",
- "d/MMMM/yyyy",
- "MMM/d/yyyy",
- "MMMM/yyyy/d",
- "d/yyyy/MMM",
-
- "d/MMMM/yy",
- "yy/MMM/d",
- "d/yy/MMM",
- "yy/d/MMM",
- "MMM/d/yy",
- "MMM/yy/d",
- };
-
- private static readonly string[] ParseMonthDayYearFormats = new string [] {
- "yyyy/M/dT",
- "M/yyyy/dT",
- "yyyy'\u5E74'M'\u6708'd'\u65E5",
-
- "yyyy/MMMM/d",
- "yyyy/d/MMM",
- "MMMM/d/yyyy",
- "d/MMM/yyyy",
- "MMMM/yyyy/d",
- "d/yyyy/MMM",
-
- "MMMM/d/yy",
- "MMM/yy/d",
- "d/MMM/yy",
- "yy/MMM/d",
- "d/yy/MMM",
- "yy/d/MMM",
- };
-
- private static readonly string[] ParseGenericYearMonthDayFormats = new string [] {
- "yyyy/M/dT",
- "yyyy/M/d",
- "M/yyyy/dT",
- "M/yyyy/d",
- "yyyy'\u5E74'M'\u6708'd'\u65E5",
- "yyyy'-'M'-'dT",
- "yyyy'-'M'-'d",
- };
-
- // Patterns influenced by the MonthDayPattern in DateTimeFormatInfo.
- // Note that these patterns cannot be followed by the time.
- private static readonly string[] MonthDayShortFormats = new string [] {
- "MMMM/d",
- "d/MMM",
- "yyyy/MMMM",
- };
- private static readonly string[] DayMonthShortFormats = new string [] {
- "d/MMMM",
- "MMM/yy",
- "yyyy/MMMM",
- };
-
- private static readonly string[] ExoticAndNonStandardFormats = new string[] {
- "ddMMMyyyy"
- };
-
- 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 = (int) ((encoded & TicksMask) / TimeSpan.TicksPerDay);
-
- 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;
- }
-
- static void InvalidTickValue (long ticks)
- {
- string msg = Locale.GetText ("Value {0} is outside the valid range [0,{1}].", ticks, MAX_VALUE_TICKS);
- throw new ArgumentOutOfRangeException ("ticks", msg);
- }
-
- // Constructors
-
- /// <summary>
- /// Constructs a DateTime for specified ticks
- /// </summary>
- ///
- public DateTime (long ticks)
- {
- if (ticks < 0 || ticks > MAX_VALUE_TICKS)
- InvalidTickValue (ticks);
- encoded = ticks;
- }
-
- 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.");
-
- encoded = new TimeSpan (AbsoluteDays (year,month,day), hour, minute, second, millisecond).Ticks;
- }
-
- 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)
- {
- if (calendar == null)
- throw new ArgumentNullException ("calendar");
- encoded = calendar.ToDateTime (year, month, day, hour, minute, second, millisecond).encoded;
- }
-
- public DateTime (long ticks, DateTimeKind kind)
- {
- if (ticks < 0 || ticks > MAX_VALUE_TICKS)
- InvalidTickValue (ticks);
- if (kind < 0 || kind > DateTimeKind.Local)
- throw new ArgumentException ("Invalid DateTimeKind value.", "kind");
-
- encoded = ((long)kind << KindShift) | ticks;
- }
-
- internal DateTime (long ticks, DateTimeKind kind, Boolean isAmbiguousDst)
- : this (ticks, kind)
- {
- }
-
- public DateTime (int year, int month, int day, int hour, int minute, int second, DateTimeKind kind)
- : this (year, month, day, hour, minute, second)
- {
- if (kind < 0 || kind > DateTimeKind.Local)
- throw new ArgumentException ("Invalid DateTimeKind value.", "kind");
- encoded |= ((long)kind << KindShift);
- }
-
- public DateTime (int year, int month, int day, int hour, int minute, int second, int millisecond, DateTimeKind kind)
- : this (year, month, day, hour, minute, second, millisecond)
- {
- if (kind < 0 || kind > DateTimeKind.Local)
- throw new ArgumentException ("Invalid DateTimeKind value.", "kind");
- encoded |= ((long)kind << KindShift);
- }
-
- public DateTime (int year, int month, int day, int hour, int minute, int second, int millisecond, Calendar calendar, DateTimeKind kind)
- : this (year, month, day, hour, minute, second, millisecond, calendar)
- {
- if (kind < 0 || kind > DateTimeKind.Local)
- throw new ArgumentException ("Invalid DateTimeKind value.", "kind");
- encoded |= ((long)kind << KindShift);
- }
-
- //
- // Not visible, but can be invoked during deserialization
- //
- DateTime (SerializationInfo info, StreamingContext context)
- {
- if (info.HasKey ("dateData")){
- encoded = (Int64)info.GetUInt64 ("dateData");
- } else if (info.HasKey ("ticks")){
- encoded = info.GetInt64 ("ticks") & TicksMask;
- } else {
- encoded = 0;
- }
- }
-
-
- /* Properties */
-
- public DateTime Date {
- get {
- DateTime ret = new DateTime (Year, Month, Day);
- ret.encoded |= encoded & KindMask;
- return ret;
- }
- }
-
- public int Month {
- get {
- return FromTicks (Which.Month);
- }
- }
-
- public int Day {
- get {
- return FromTicks (Which.Day);
- }
- }
-
- public DayOfWeek DayOfWeek {
- get {
- return (DayOfWeek) ((((encoded & TicksMask)/TimeSpan.TicksPerDay)+1) % 7);
- }
- }
-
- public int DayOfYear {
- get {
- return FromTicks (Which.DayYear);
- }
- }
-
- public TimeSpan TimeOfDay {
- get {
- return new TimeSpan ((encoded & TicksMask) % TimeSpan.TicksPerDay);
- }
-
- }
-
- public int Hour {
- get {
- return (int) ((encoded & TicksMask) % TimeSpan.TicksPerDay / TimeSpan.TicksPerHour);
- }
- }
-
- public int Minute {
- get {
- return (int) ((encoded & TicksMask) % TimeSpan.TicksPerHour / TimeSpan.TicksPerMinute);
- }
- }
-
- public int Second {
- get {
- return (int) ((encoded & TicksMask) % TimeSpan.TicksPerMinute / TimeSpan.TicksPerSecond);
- }
- }
-
- public int Millisecond {
- get {
- return (int) ((encoded & TicksMask) % TimeSpan.TicksPerSecond / TimeSpan.TicksPerMillisecond);
- }
- }
-
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- internal static extern long GetTimeMonotonic ();
-
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- internal static extern long GetNow ();
-
- internal static void ClearCachedData ()
- {
- to_local_time_span_object = null;
- }
-
- //
- // To reduce the time consumed by DateTime.Now, we keep
- // the difference to map the system time into a local
- // time into `to_local_time_span', we record the timestamp
- // for this in `last_now'
- //
- static object to_local_time_span_object;
- static long last_now;
-
- public static DateTime Now {
- get {
- long now = GetNow ();
- DateTime dt = new DateTime (now);
-
- if (to_local_time_span_object == null || Math.Abs (now - last_now) > TimeSpan.TicksPerMinute){
- to_local_time_span_object = TimeZone.CurrentTimeZone.GetLocalTimeDiff (dt);
- last_now = now;
-
- }
-
- // This is boxed, so we avoid locking.
- DateTime ret = dt + (TimeSpan) to_local_time_span_object;
- ret.encoded |= ((long)DateTimeKind.Local << KindShift);
- return ret;
- }
- }
-
- public long Ticks {
- get {
- return encoded & TicksMask;
- }
- }
-
- public static DateTime Today {
- get {
- DateTime now = Now;
- DateTime today = new DateTime (now.Year, now.Month, now.Day);
- today.encoded |= ((long)DateTimeKind.Local << KindShift);
- return today;
- }
- }
-
- public static DateTime UtcNow {
- get {
- return new DateTime (GetNow (), DateTimeKind.Utc);
- }
- }
-
- public int Year {
- get {
- return FromTicks (Which.Year);
- }
- }
-
- public DateTimeKind Kind {
- get {
- return (DateTimeKind) ((ulong)encoded >> KindShift);
- }
- }
-
- /* methods */
-
- public DateTime Add (TimeSpan value)
- {
- DateTime ret = AddTicks (value.Ticks);
- return ret;
- }
-
- public DateTime AddDays (double value)
- {
- return AddMilliseconds (Math.Round (value * 86400000));
- }
-
- public DateTime AddTicks (long value)
- {
- long res = value + (encoded & TicksMask);
- if (res < 0 || res > MAX_VALUE_TICKS)
- throw new ArgumentOutOfRangeException();
-
- DateTime ret = new DateTime (res);
- ret.encoded |= (encoded & KindMask);
- return ret;
- }
-
- public DateTime AddHours (double value)
- {
- return AddMilliseconds (value * 3600000);
- }
-
- public DateTime AddMilliseconds (double value)
- {
- if ((value * TimeSpan.TicksPerMillisecond) > long.MaxValue ||
- (value * TimeSpan.TicksPerMillisecond) < long.MinValue) {
- throw new ArgumentOutOfRangeException();
- }
- long msticks = (long) Math.Round (value * 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 value)
- {
- return AddMilliseconds (value * 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);
- temp.encoded |= encoded & KindMask;
- return temp.Add (this.TimeOfDay);
- }
-
- public DateTime AddSeconds (double value)
- {
- return AddMilliseconds (value * 1000);
- }
-
- public DateTime AddYears (int value)
- {
- return AddMonths (value * 12);
- }
-
- public static int Compare (DateTime t1, DateTime t2)
- {
- long t1t = t1.encoded & TicksMask;
- long t2t = t2.encoded & TicksMask;
-
- if (t1t < t2t)
- return -1;
- else if (t1t > t2t)
- return 1;
- else
- return 0;
- }
-
- public int CompareTo (object value)
- {
- if (value == null)
- return 1;
-
- if (!(value is System.DateTime))
- throw new ArgumentException (Locale.GetText (
- "Value is not a System.DateTime"));
-
- return Compare (this, (DateTime) value);
- }
-
- public bool IsDaylightSavingTime ()
- {
- if ((int)((ulong)encoded >> KindShift) == (int) DateTimeKind.Utc)
- return false;
- return TimeZone.CurrentTimeZone.IsDaylightSavingTime (this);
- }
-
- public int CompareTo (DateTime value)
- {
- return Compare (this, value);
- }
-
- public bool Equals (DateTime value)
- {
- return (value.encoded & TicksMask) == (encoded & TicksMask);
- }
-
- public long ToBinary ()
- {
- if ((encoded & ((long)DateTimeKind.Local << KindShift)) != 0)
- return (long) ((ulong) ToUniversalTime ().Ticks | 0x8000000000000000);
-
- return encoded;
- }
-
- public static DateTime FromBinary (long dateData)
- {
- switch ((ulong)dateData >> KindShift) {
- case 1: // Utc
- return new DateTime (dateData & TicksMask, DateTimeKind.Utc);
- case 0: // Unspecified
- return new DateTime (dateData, DateTimeKind.Unspecified);
- default: // Local
- return new DateTime (dateData & TicksMask, DateTimeKind.Utc).ToLocalTime ();
- }
- }
-
- public static DateTime SpecifyKind (DateTime value, DateTimeKind kind)
- {
- return new DateTime (value.Ticks, kind);
- }
-
- public static int DaysInMonth (int year, int month)
- {
- int[] days ;
-
- if (month < 1 || month >12)
- throw new ArgumentOutOfRangeException ();
-
- if (year < 1 || year > 9999)
- throw new ArgumentOutOfRangeException ();
-
- days = (IsLeapYear(year) ? daysmonthleap : daysmonth);
- return days[month];
- }
-
- public override bool Equals (object value)
- {
- if (!(value is System.DateTime))
- return false;
-
- return (((DateTime) value).encoded & TicksMask) == (encoded & TicksMask);
- }
-
- public static bool Equals (DateTime t1, DateTime t2 )
- {
- return (t1.encoded & TicksMask) == (t2.encoded & TicksMask);
- }
-
- public static DateTime FromFileTime (long fileTime)
- {
- if (fileTime < 0)
- throw new ArgumentOutOfRangeException ("fileTime", "< 0");
-
- return new DateTime (w32file_epoch + fileTime).ToLocalTime ();
- }
-
- public static DateTime FromFileTimeUtc (long fileTime)
- {
- if (fileTime < 0)
- throw new ArgumentOutOfRangeException ("fileTime", "< 0");
-
- return new DateTime (w32file_epoch + fileTime, DateTimeKind.Utc);
- }
-
- 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 ());
- var l = new List<string> ();
- foreach (char c in "dDgGfFmMrRstTuUyY")
- l.AddRange (GetDateTimeFormats (c, info));
- return l.ToArray ();
- }
-
- public string[] GetDateTimeFormats(char format,IFormatProvider provider )
- {
- return DateTimeFormat.GetAllDateTimes(this, format, DateTimeFormatInfo.GetInstance(provider));
- }
-
- 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] = DateTimeUtils.ToString (val, patterns [i], dfi);
- return results;
- }
-
- public override int GetHashCode ()
- {
- return (int) encoded;
- }
-
- public TypeCode GetTypeCode ()
- {
- return TypeCode.DateTime;
- }
-
- public static bool IsLeapYear (int year)
- {
- if (year < 1 || year > 9999)
- throw new ArgumentOutOfRangeException ();
- 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 provider)
- {
- return Parse (s, provider, DateTimeStyles.AllowWhiteSpaces);
- }
-
- public static DateTime Parse (string s, IFormatProvider provider, DateTimeStyles styles)
- {
- if (s == null)
- throw new ArgumentNullException ("s");
-
- DateTime res;
- DateTimeOffset dto;
- Exception exception = null;
- if (!CoreParse (s, provider, styles, out res, out dto, true, ref exception))
- throw exception;
-
- return res;
- }
-
- const string formatExceptionMessage = "String was not recognized as a valid DateTime.";
-
- internal static bool CoreParse (string s, IFormatProvider provider, DateTimeStyles styles,
- out DateTime result, out DateTimeOffset dto, bool setExceptionOnError, ref Exception exception)
- {
- dto = new DateTimeOffset (0, TimeSpan.Zero);
- if (s == null || s.Length == 0) {
- if (setExceptionOnError)
- exception = new FormatException (formatExceptionMessage);
- result = MinValue;
- return false;
- }
-
- if (provider == null)
- provider = CultureInfo.CurrentCulture;
- DateTimeFormatInfo dfi = DateTimeFormatInfo.GetInstance (provider);
-
- // Try first all the combinations of ParseAllDateFormats & ParseTimeFormats
- string[] allDateFormats = YearMonthDayFormats (dfi);
- if (allDateFormats == null){
- result = MinValue;
- return false;
- }
-
- bool longYear = false;
- for (int i = 0; i < allDateFormats.Length; i++) {
- string firstPart = allDateFormats [i];
- bool incompleteFormat = false;
- if (_DoParse (s, firstPart, "", false, out result, out dto, dfi, styles, true, ref incompleteFormat, ref longYear))
- return true;
-
- if (!incompleteFormat)
- continue;
-
- for (int j = 0; j < ParseTimeFormats.Length; j++) {
- if (_DoParse (s, firstPart, ParseTimeFormats [j], false, out result, out dto, dfi, styles, true, ref incompleteFormat, ref longYear))
- return true;
- }
-
- if (_DoParse (s, firstPart, "zzz", false, out result, out dto, dfi, styles, true, ref incompleteFormat, ref longYear))
- return true;
- }
-
- //
- // Month day formats
- //
- int dayIndex = dfi.MonthDayPattern.IndexOf('d');
- int monthIndex = dfi.MonthDayPattern.IndexOf('M');
- if (dayIndex == -1 || monthIndex == -1){
- result = MinValue;
- if (setExceptionOnError)
- exception = new FormatException (Locale.GetText("Order of month and date is not defined by {0}", dfi.MonthDayPattern));
- return false;
- }
- bool is_day_before_month = dayIndex < monthIndex;
- string[] monthDayFormats = is_day_before_month ? DayMonthShortFormats : MonthDayShortFormats;
- for (int i = 0; i < monthDayFormats.Length; i++) {
- bool incompleteFormat = false;
- if (_DoParse (s, monthDayFormats[i], "", false, out result, out dto, dfi, styles, true, ref incompleteFormat, ref longYear))
- return true;
- }
-
- for (int j = 0; j < ParseTimeFormats.Length; j++) {
- string firstPart = ParseTimeFormats [j];
- bool incompleteFormat = false;
- if (_DoParse (s, firstPart, "", false, out result, out dto, dfi, styles, false, ref incompleteFormat, ref longYear))
- return true;
- if (!incompleteFormat)
- continue;
-
- for (int i = 0; i < monthDayFormats.Length; i++) {
- if (_DoParse (s, firstPart, monthDayFormats [i], false, out result, out dto, dfi, styles, false, ref incompleteFormat, ref longYear))
- return true;
- }
- for (int i = 0; i < allDateFormats.Length; i++) {
- string dateFormat = allDateFormats [i];
- if (dateFormat[dateFormat.Length - 1] == 'T')
- continue; // T formats must be before the time part
- if (_DoParse (s, firstPart, dateFormat, false, out result, out dto, dfi, styles, false, ref incompleteFormat, ref longYear))
- return true;
- }
- }
-
- // Try as a last resort all the patterns
- if (CoreParseExact (s, dfi.GetAllDateTimePatternsInternal (), dfi, styles, out result, out dto, false, ref longYear, setExceptionOnError, ref exception))
- return true;
-
- if (CoreParseExact (s, ExoticAndNonStandardFormats, dfi, styles, out result, out dto, false, ref longYear, setExceptionOnError, ref exception))
- return true;
-
- if (!setExceptionOnError)
- return false;
-
- // .NET 2.x does not throw an ArgumentOutOfRangeException, but .NET 1.1 does.
- exception = new FormatException (formatExceptionMessage);
- return false;
- }
-
- public static DateTime ParseExact (string s, string format, IFormatProvider provider)
- {
- return ParseExact (s, format, provider, DateTimeStyles.None);
- }
-
- private static string[] YearMonthDayFormats (DateTimeFormatInfo dfi)
- {
- int dayIndex = dfi.ShortDatePattern.IndexOf('d');
- int monthIndex = dfi.ShortDatePattern.IndexOf('M');
- int yearIndex = dfi.ShortDatePattern.IndexOf('y');
- if (dayIndex == -1 || monthIndex == -1 || yearIndex == -1)
- return ParseGenericYearMonthDayFormats;
-
- if (yearIndex < monthIndex)
- if (monthIndex < dayIndex)
- return ParseYearMonthDayFormats;
- else if (yearIndex < dayIndex)
- return ParseYearDayMonthFormats;
- else {
- // The year cannot be between the date and the month
- return ParseGenericYearMonthDayFormats;
- }
- else if (dayIndex < monthIndex)
- return ParseDayMonthYearFormats;
- else if (dayIndex < yearIndex)
- return ParseMonthDayYearFormats;
- else {
- // The year cannot be between the month and the date
- return ParseGenericYearMonthDayFormats;
- }
- }
-
- private static int _ParseNumber (string s, int valuePos,
- int min_digits,
- int digits,
- bool leadingzero,
- bool sloppy_parsing,
- 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 (digits < min_digits) {
- num_parsed = -1;
- return 0;
- }
-
- if (s.Length - valuePos < digits) {
- 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;
- }
-
- private static int _ParseEnum (string s, int sPos, string[] values, string[] invValues, bool exact, out int num_parsed)
- {
- // FIXME: I know this is somehow lame code. Probably
- // it should iterate all the enum value and return
- // the longest match. However right now I don't see
- // anything but "1" and "10" - "12" that might match
- // two or more values. (They are only abbrev month
- // names, so do reverse order search). See bug #80094.
- for (int i = values.Length - 1; i >= 0; i--) {
- if (!exact && invValues [i].Length > values[i].Length) {
- if (invValues [i].Length > 0 && _ParseString (s, sPos, 0, invValues [i], out num_parsed))
- return i;
- if (values [i].Length > 0 && _ParseString (s, sPos, 0, values [i], out num_parsed))
- return i;
- }
- else {
- if (values [i].Length > 0 && _ParseString (s, sPos, 0, values [i], out num_parsed))
- return i;
- if (!exact && invValues [i].Length > 0 && _ParseString (s, sPos, 0, invValues [i], out num_parsed))
- return i;
- }
- }
-
- num_parsed = -1;
- return -1;
- }
-
- private static bool _ParseString (string s, int sPos, int maxlength, string value, out int num_parsed)
- {
- if (maxlength <= 0)
- maxlength = value.Length;
-
- if (sPos + maxlength <= s.Length && String.CompareOrdinalCaseInsensitive (s, sPos, value, 0, maxlength) == 0) {
- num_parsed = maxlength;
- return true;
- }
-
- num_parsed = -1;
- return false;
- }
-
- // Note that in case of Parse (exact == false) we check both for AM/PM
- // and the culture spcific AM/PM strings.
- private static bool _ParseAmPm(string s,
- int valuePos,
- int num,
- DateTimeFormatInfo dfi,
- bool exact,
- out int num_parsed,
- ref int ampm)
- {
- num_parsed = -1;
- if (ampm != -1)
- return false;
-
- if (!IsLetter (s, valuePos)) {
- if (dfi.AMDesignator != "")
- return false;
- if (exact)
- ampm = 0;
- num_parsed = 0;
- return true;
- }
- DateTimeFormatInfo invInfo = DateTimeFormatInfo.InvariantInfo;
- if (!exact && _ParseString (s, valuePos, num, invInfo.PMDesignator, out num_parsed) ||
- dfi.PMDesignator != "" && _ParseString(s, valuePos, num, dfi.PMDesignator, out num_parsed))
- ampm = 1;
- else if (!exact && _ParseString (s, valuePos, num, invInfo.AMDesignator, out num_parsed) ||
- _ParseString (s, valuePos, num, dfi.AMDesignator, out num_parsed)) {
- if (exact || num_parsed != 0)
- ampm = 0;
- }
- else
- return false;
- return true;
- }
-
- // Note that in case of Parse (exact == false) we check both for ':'
- // and the culture spcific TimeSperator
- private static bool _ParseTimeSeparator (string s, int sPos, DateTimeFormatInfo dfi, bool exact, out int num_parsed)
- {
- return _ParseString (s, sPos, 0, dfi.TimeSeparator, out num_parsed) ||
- !exact && _ParseString (s, sPos, 0, ":", out num_parsed);
- }
-
- // Accept any character for DateSeparator, except TimeSeparator,
- // a digit or a letter.
- // Not documented, but seems to be MS behaviour here. See bug 54047.
- private static bool _ParseDateSeparator (string s, int sPos, DateTimeFormatInfo dfi, bool exact, out int num_parsed)
- {
- num_parsed = -1;
- if (exact && s [sPos] != '/')
- return false;
-
- if (_ParseTimeSeparator (s, sPos, dfi, exact, out num_parsed) ||
- Char.IsDigit (s [sPos]) || Char.IsLetter (s [sPos]))
- return(false);
-
- num_parsed = 1;
- return true;
- }
-
- private static bool IsLetter (string s, int pos)
- {
- return pos < s.Length && Char.IsLetter (s [pos]);
- }
-
- // To implement better DateTime.Parse we use two format strings one
- // for Date and one for Time. This allows us to define two different
- // arrays of formats for Time and Dates and to combine them more or less
- // efficiently. When this mode is used flexibleTwoPartsParsing is true.
- private static bool _DoParse (string s,
- string firstPart,
- string secondPart,
- bool exact,
- out DateTime result,
- out DateTimeOffset dto,
- DateTimeFormatInfo dfi,
- DateTimeStyles style,
- bool firstPartIsDate,
- ref bool incompleteFormat,
- ref bool longYear,
- bool dateTimeOffset = false)
- {
- bool useutc = false;
- bool use_invariant = false;
- bool sloppy_parsing = false;
- dto = new DateTimeOffset (0, TimeSpan.Zero);
- bool flexibleTwoPartsParsing = !exact && secondPart != null;
- incompleteFormat = false;
- int valuePos = 0;
- string format = firstPart;
- bool afterTFormat = false;
- DateTimeFormatInfo invInfo = DateTimeFormatInfo.InvariantInfo;
- if (format.Length == 1)
- format = DateTimeUtils.GetStandardPattern (format [0], dfi, out useutc, out use_invariant, dateTimeOffset);
-
- result = new DateTime (0);
- if (format == null)
- return false;
-
- if (s == null)
- return false;
-
- 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 = invInfo;
-
- if ((style & DateTimeStyles.AllowInnerWhite) != 0)
- sloppy_parsing = true;
-
- string chars = format;
- int len = format.Length, pos = 0, num = 0;
- if (len == 0)
- return false;
-
- 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 isFirstPart = true;
- bool format_with_24_hours = false;
-
- for (; ; )
- {
- if (valuePos == s.Length)
- break;
-
- int num_parsed = 0;
- if (flexibleTwoPartsParsing && pos + num == 0)
- {
- bool isLetter = IsLetter(s, valuePos);
- if (isLetter) {
- if (s [valuePos] == 'Z')
- num_parsed = 1;
- else
- _ParseString (s, valuePos, 0, "GMT", out num_parsed);
- if (num_parsed > 0 && !IsLetter (s, valuePos + num_parsed)) {
- valuePos += num_parsed;
- useutc = true;
- continue;
- }
- }
- if (!afterTFormat && _ParseAmPm (s, valuePos, 0, dfi, exact, out num_parsed, ref ampm)) {
- if (IsLetter (s, valuePos + num_parsed))
- ampm = -1;
- else if (num_parsed > 0) {
- valuePos += num_parsed;
- continue;
- }
- }
-
- if (!afterTFormat && dayofweek == -1 && isLetter) {
- dayofweek = _ParseEnum (s, valuePos, dfi.RawDayNames, invInfo.RawDayNames, exact, out num_parsed);
- if (dayofweek == -1)
- dayofweek = _ParseEnum (s, valuePos, dfi.RawAbbreviatedDayNames, invInfo.RawAbbreviatedDayNames, exact, out num_parsed);
- if (dayofweek != -1 && !IsLetter (s, valuePos + num_parsed)) {
- valuePos += num_parsed;
- continue;
- }
- else
- dayofweek = -1;
- }
-
- if (char.IsWhiteSpace (s [valuePos]) || s [valuePos] == ',') {
- valuePos += 1;
- continue;
- }
- num_parsed = 0;
- }
-
- if (pos + num >= len)
- {
- if (flexibleTwoPartsParsing && num == 0) {
- afterTFormat = isFirstPart && firstPart [firstPart.Length - 1] == 'T';
- if (!isFirstPart && format == "")
- break;
-
- pos = 0;
- if (isFirstPart)
- format = secondPart;
- else
- format = "";
- chars = format;
- len = chars.Length;
- isFirstPart = false;
- continue;
- }
- break;
- }
-
- bool leading_zeros = true;
-
- if (chars[pos] == '\'') {
- num = 1;
- while (pos+num < len) {
- if (chars[pos+num] == '\'')
- break;
-
- if (valuePos == s.Length || s [valuePos] != chars [pos + num])
- return false;
-
- valuePos++;
- num++;
- }
-
- 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 || s [valuePos] != chars[pos+num])
- return false;
-
- valuePos++;
- num++;
- }
-
- pos += num + 1;
- num = 0;
- continue;
- } else if (chars[pos] == '\\') {
- pos += num + 1;
- num = 0;
- if (pos >= len)
- return false;
- if (s [valuePos] != chars [pos])
- return false;
-
- valuePos++;
- pos++;
- continue;
- } else if (chars[pos] == '%') {
- pos++;
- continue;
- } else if (char.IsWhiteSpace (s [valuePos]) ||
- s [valuePos] == ',' && (!exact && chars [pos] == '/' || Char.IsWhiteSpace (chars [pos]))) {
- valuePos++;
- num = 0;
- if (exact && (style & DateTimeStyles.AllowInnerWhite) == 0) {
- if (!Char.IsWhiteSpace (chars[pos]))
- return false;
- pos++;
- continue;
- }
-
- int ws = valuePos;
- while (ws < s.Length) {
- if (Char.IsWhiteSpace (s [ws]) || s [ws] == ',')
- ws++;
- else
- break;
- }
- valuePos = ws;
- ws = pos;
- while (ws < chars.Length) {
- if (Char.IsWhiteSpace (chars [ws]) || chars [ws] == ',')
- ws++;
- else
- break;
- }
- pos = ws;
- // A whitespace may match a '/' in the pattern.
- if (!exact && pos < chars.Length && chars[pos] == '/')
- if (!_ParseDateSeparator (s, valuePos, dfi, exact, out num_parsed))
- pos++;
- continue;
- }
-
- if ((pos+num+1 < len) && (chars[pos+num+1] == chars[pos+num])) {
- num++;
- continue;
- }
-
- switch (chars[pos])
- {
- case 'd':
- if (num < 2 && day != -1 || num >= 2 && dayofweek != -1)
- return false;
- if (num == 0)
- day = _ParseNumber (s, valuePos, 1, 2, false, sloppy_parsing, out num_parsed);
- else if (num == 1)
- day = _ParseNumber (s, valuePos, 1, 2, true, sloppy_parsing, out num_parsed);
- else if (num == 2)
- dayofweek = _ParseEnum (s, valuePos, dfi.RawAbbreviatedDayNames, invInfo.RawAbbreviatedDayNames, exact, out num_parsed);
- else
- dayofweek = _ParseEnum (s, valuePos, dfi.RawDayNames, invInfo.RawDayNames, exact, out num_parsed);
- break;
- case 'M':
- if (month != -1)
- return false;
-
- if (flexibleTwoPartsParsing) {
- num_parsed = -1;
- if (num == 0 || num == 3)
- month = _ParseNumber (s, valuePos, 1, 2, false, sloppy_parsing, out num_parsed);
- if (num > 1 && num_parsed == -1)
- month = _ParseEnum (s, valuePos, dfi.RawMonthNames, invInfo.RawMonthNames, exact, out num_parsed) + 1;
- if (num > 1 && num_parsed == -1)
- month = _ParseEnum (s, valuePos, dfi.RawAbbreviatedMonthNames, invInfo.RawAbbreviatedMonthNames, exact, out num_parsed) + 1;
- break;
- }
-
- if (num == 0)
- month = _ParseNumber (s, valuePos, 1, 2, false, sloppy_parsing, out num_parsed);
- else if (num == 1)
- month = _ParseNumber (s, valuePos, 1, 2, true, sloppy_parsing, out num_parsed);
- else if (num == 2)
- month = _ParseEnum (s, valuePos, dfi.RawAbbreviatedMonthNames, invInfo.RawAbbreviatedMonthNames, exact, out num_parsed) + 1;
- else
- month = _ParseEnum (s, valuePos, dfi.RawMonthNames, invInfo.RawMonthNames, exact, out num_parsed) + 1;
- break;
- case 'y':
- if (year != -1)
- return false;
-
- if (num == 0) {
- year = _ParseNumber (s, valuePos, 1, 2, false, sloppy_parsing, out num_parsed);
- } else if (num < 3) {
- year = _ParseNumber (s, valuePos, 1, 2, true, sloppy_parsing, out num_parsed);
- } else {
- year = _ParseNumber (s, valuePos, exact ? num + 1 : 3, num + 1, false, sloppy_parsing, out num_parsed);
- longYear = (year > 9999);
- }
-
- //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, 1, 2, false, sloppy_parsing, out num_parsed);
- else
- hour = _ParseNumber (s, valuePos, 1, 2, true, sloppy_parsing, out num_parsed);
-
- if (hour > 12)
- return false;
- if (hour == 12)
- hour = 0;
-
- break;
- case 'H':
- if (hour != -1 || !flexibleTwoPartsParsing && ampm >= 0)
- return false;
- if (num == 0)
- hour = _ParseNumber (s, valuePos, 1, 2, false, sloppy_parsing, out num_parsed);
- else
- hour = _ParseNumber (s, valuePos, 1, 2, true, sloppy_parsing, out num_parsed);
-
- if (hour >= 24)
- return false;
-
- format_with_24_hours = true;
- break;
- case 'm':
- if (minute != -1)
- return false;
- if (num == 0)
- minute = _ParseNumber (s, valuePos, 1, 2, false, sloppy_parsing, out num_parsed);
- else
- minute = _ParseNumber (s, valuePos, 1, 2, true, sloppy_parsing, out num_parsed);
-
- if (minute >= 60)
- return false;
-
- break;
- case 's':
- if (second != -1)
- return false;
- if (num == 0)
- second = _ParseNumber (s, valuePos, 1, 2, false, sloppy_parsing, out num_parsed);
- else
- second = _ParseNumber (s, valuePos, 1, 2, true, sloppy_parsing, out num_parsed);
-
- if (second >= 60)
- return false;
-
- break;
- case 'F':
- leading_zeros = false;
- goto case 'f';
- case 'f':
- if (num > 6 || fractionalSeconds != -1)
- return false;
- double decimalNumber = (double) _ParseNumber (s, valuePos, 0, num+1, leading_zeros, sloppy_parsing, out num_parsed);
- if (num_parsed == -1)
- return false;
- fractionalSeconds = decimalNumber / Math.Pow(10.0, num_parsed);
-
- //Parse ISO8601 with an unlimited number of fractional digits.
- if (!exact && num == 6 && hour != -1 && minute != -1 && second != -1) {
- var total_num_parsed = num_parsed;
- while (true) {
- valuePos += num_parsed;
- decimalNumber = (double) _ParseNumber (s, valuePos, 0, 1, leading_zeros, sloppy_parsing, out num_parsed);
- if (num_parsed < 1) {
- num_parsed = 0;
- break;
- }
-
- total_num_parsed += num_parsed;
- if (total_num_parsed > 15)
- continue; //not enough precision, ignore additional digits.
-
- fractionalSeconds += decimalNumber / Math.Pow (10.0, total_num_parsed);
- }
- }
- break;
- case 't':
- if (!_ParseAmPm (s, valuePos, num > 0 ? 0 : 1, dfi, exact, out num_parsed, ref ampm))
- return false;
- 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, 1, 2, false, sloppy_parsing, out num_parsed);
- else if (num == 1)
- tzoffset = _ParseNumber (s, valuePos, 1, 2, true, sloppy_parsing, out num_parsed);
- else {
- tzoffset = _ParseNumber (s, valuePos, 1, 2, true, /*sloppy_parsing*/true, out num_parsed);
- valuePos += num_parsed;
- if (num_parsed < 0)
- return false;
-
- num_parsed = 0;
- if (valuePos < s.Length && Char.IsDigit (s [valuePos]) ||
- _ParseTimeSeparator (s, valuePos, dfi, exact, out num_parsed)) {
- valuePos += num_parsed;
- tzoffmin = _ParseNumber (s, valuePos, 1, 2, true, sloppy_parsing, out num_parsed);
- if (num_parsed < 0)
- return false;
- }
- else if (!flexibleTwoPartsParsing)
- return false;
- else
- num_parsed = 0;
- }
- break;
- case 'K':
- if (s [valuePos] == 'Z') {
- valuePos++;
- useutc = true;
- }
- else if (s [valuePos] == '+' || s [valuePos] == '-') {
- if (tzsign != -1)
- return false;
- if (s [valuePos] == '+')
- tzsign = 0;
- else if (s [valuePos] == '-')
- tzsign = 1;
- valuePos++;
-
- // zzz
- tzoffset = _ParseNumber (s, valuePos, 0, 2, true, sloppy_parsing, out num_parsed);
- valuePos += num_parsed;
- if (num_parsed < 0)
- return false;
-
- 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, 0, 2, true, sloppy_parsing, out num_parsed);
- if (num_parsed < 0)
- return false;
- }
- 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 'G':
- if (s [valuePos] != 'G')
- return false;
-
- if ((pos + 2 < len) && (valuePos + 2 < s.Length) &&
- (chars [pos + 1] == 'M') && (s[valuePos + 1] == 'M') &&
- (chars [pos + 2] == 'T') && (s[valuePos + 2] == 'T'))
- {
- useutc = true;
- num = 2;
- num_parsed = 3;
- }
- else {
- num = 0;
- num_parsed = 1;
- }
- break;
- case ':':
- if (!_ParseTimeSeparator (s, valuePos, dfi, exact, out num_parsed))
- return false;
- break;
- case '/':
- if (!_ParseDateSeparator (s, valuePos, dfi, exact, out num_parsed))
- return false;
-
- num = 0;
- break;
- case '.':
- if (s[valuePos] == '.') {
- num = 0;
- num_parsed = 1;
- break;
- }
-
- // '.FFF....' can be mapped to nothing
- if (pos + 1 < len && chars[pos + 1] == 'F') {
- ++pos;
- while (pos + 1 < len && chars[pos + 1] == 'F') {
- ++pos;
- }
-
- num = 0;
- num_parsed = 0;
- break;
- }
-
- return false;
-
- default:
- if (s [valuePos] != chars [pos])
- return false;
-
- num = 0;
- num_parsed = 1;
- break;
- }
-
- if (num_parsed < 0)
- return false;
-
- valuePos += num_parsed;
-
- if (!exact && !flexibleTwoPartsParsing) {
- switch (chars [pos]) {
- case 'm':
- case 's':
- case 'F':
- 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 (pos + 1 < len && chars [pos] == '.' && chars [pos + 1] == 'F') {
- pos++;
- while (pos < len && chars [pos] == 'F') // '.FFF....' can be mapped to nothing. See bug #444103
- pos++;
- }
- while (pos < len && chars [pos] == 'K') // 'K' can be mapped to nothing
- pos++;
-
- if (pos < len)
- return false;
-
- if (s.Length > valuePos) // extraneous tail.
- {
- if (valuePos == 0)
- return false;
-
- if (Char.IsDigit (s [valuePos]) && Char.IsDigit (s [valuePos - 1]))
- return false;
- if (Char.IsLetter (s [valuePos]) && Char.IsLetter (s [valuePos - 1]))
- return false;
- incompleteFormat = true;
- 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 = DateTime.Today.Day;
- month = DateTime.Today.Month;
- year = DateTime.Today.Year;
- }
- }
-
- if (day == -1)
- day = 1;
- if (month == -1)
- month = 1;
- if (year == -1) {
- if ((style & DateTimeStyles.NoCurrentDateDefault) != 0)
- year = 1;
- else
- year = DateTime.Today.Year;
- }
-
- if (ampm == 0) { // AM designator
- if (hour >= 12 && format_with_24_hours && exact)
- return false;
-
- if (hour == 12)
- hour = 0;
- } else if (ampm == 1) { // PM designator
- if (hour < 12) {
- if (format_with_24_hours && exact)
- return false;
-
- hour += 12;
- }
- }
-
- try {
- result = dfi.Calendar.ToDateTime (year, month, day, hour, minute, second, 0);
- } catch {
- return false;
- }
-
- result = result.AddSeconds(fractionalSeconds);
-
- if (dayofweek != -1 && dayofweek != (int) result.DayOfWeek)
- return false;
-
- if (tzsign == -1) {
- if (result != DateTime.MinValue) {
- try {
- if (((style & DateTimeStyles.AssumeUniversal) != 0) || useutc) {
- dto = new DateTimeOffset (result, TimeSpan.Zero);
- } else if ((style & DateTimeStyles.AssumeLocal) != 0) {
- var offset = use_invariant ?
- TimeSpan.Zero :
- TimeZone.CurrentTimeZone.GetUtcOffset (DateTime.Now);
- dto = new DateTimeOffset (result, offset);
- } else {
- dto = new DateTimeOffset (result);
- }
- } catch { } // We handle this error in DateTimeOffset.Parse
- }
- } else {
- if (tzoffmin == -1)
- tzoffmin = 0;
- if (tzoffset == -1)
- tzoffset = 0;
- if (tzsign == 1) {
- tzoffset = -tzoffset;
- tzoffmin = -tzoffmin;
- }
- try {
- dto = new DateTimeOffset (result, new TimeSpan (tzoffset, tzoffmin, 0));
- } catch {} // We handle this error in DateTimeOffset.Parse
- }
- bool adjustToUniversal = (style & DateTimeStyles.AdjustToUniversal) != 0;
-
- if (tzsign != -1) {
- long newticks = (result - dto.Offset).Ticks;
- if (newticks < 0)
- newticks += TimeSpan.TicksPerDay;
- result = new DateTime (newticks, DateTimeKind.Utc);
- if ((style & DateTimeStyles.RoundtripKind) != 0)
- result = result.ToLocalTime ();
- } else if (useutc || ((style & DateTimeStyles.AssumeUniversal) != 0))
- result.encoded |= ((long) DateTimeKind.Utc << KindShift);
- else if ((style & DateTimeStyles.AssumeLocal) != 0)
- result.encoded |= ((long) DateTimeKind.Local << KindShift);
-
- bool adjustToLocal = !adjustToUniversal && (style & DateTimeStyles.RoundtripKind) == 0;
- if ((DateTimeKind)(((ulong) result.encoded >> KindShift)) != DateTimeKind.Unspecified) {
- if (adjustToUniversal)
- result = result.ToUniversalTime ();
- else if (adjustToLocal)
- result = result.ToLocalTime ();
- }
- return true;
- }
-
-
- public static DateTime ParseExact (string s, string format,
- IFormatProvider provider, DateTimeStyles style)
- {
- if (format == null)
- throw new ArgumentNullException ("format");
-
- string [] formats = new string [1];
- formats[0] = format;
-
- return ParseExact (s, formats, provider, style);
- }
-
- public static DateTime ParseExact (string s, string[] formats,
- IFormatProvider provider,
- DateTimeStyles style)
- {
- DateTimeFormatInfo dfi = DateTimeFormatInfo.GetInstance (provider);
- CheckStyle (style);
- if (s == null)
- throw new ArgumentNullException ("s");
- if (formats == null)
- throw new ArgumentNullException ("formats");
- if (formats.Length == 0)
- throw new FormatException ("Format specifier was invalid.");
-
- DateTime result;
- DateTimeOffset dto;
- bool longYear = false;
- Exception e = null;
- if (!CoreParseExact (s, formats, dfi, style, out result, out dto, true, ref longYear, true, ref e))
- throw e;
- return result;
- }
-
- private static void CheckStyle (DateTimeStyles style)
- {
- if ( (style & DateTimeStyles.RoundtripKind) != 0)
- {
- if ((style & DateTimeStyles.AdjustToUniversal) != 0 || (style & DateTimeStyles.AssumeLocal) != 0 ||
- (style & DateTimeStyles.AssumeUniversal) != 0)
- throw new ArgumentException ("The DateTimeStyles value RoundtripKind cannot be used with the values AssumeLocal, AssumeUniversal or AdjustToUniversal.", "style");
- }
- if ((style & DateTimeStyles.AssumeUniversal) != 0 && (style & DateTimeStyles.AssumeLocal) != 0)
- throw new ArgumentException ("The DateTimeStyles values AssumeLocal and AssumeUniversal cannot be used together.", "style");
- }
-
- public static bool TryParse (string s, out DateTime result)
- {
- if (s != null){
- try {
- Exception exception = null;
- DateTimeOffset dto;
-
- return CoreParse (s, null, DateTimeStyles.AllowWhiteSpaces, out result, out dto, false, ref exception);
- } catch { }
- }
- result = MinValue;
- return false;
- }
-
- public static bool TryParse (string s, IFormatProvider provider, DateTimeStyles styles, out DateTime result)
- {
- if (s != null){
- try {
- Exception exception = null;
- DateTimeOffset dto;
-
- return CoreParse (s, provider, styles, out result, out dto, false, ref exception);
- } catch {}
- }
- result = MinValue;
- return false;
- }
-
- public static bool TryParseExact (string s, string format,
- IFormatProvider provider,
- DateTimeStyles style,
- out DateTime result)
- {
- string[] formats;
- formats = new string [1];
- formats[0] = format;
-
- return TryParseExact (s, formats, provider, style, out result);
- }
-
- public static bool TryParseExact (string s, string[] formats,
- IFormatProvider provider,
- DateTimeStyles style,
- out DateTime result)
- {
- try {
- DateTimeFormatInfo dfi = DateTimeFormatInfo.GetInstance (provider);
- DateTimeOffset dto;
-
- bool longYear = false;
- Exception e = null;
- return CoreParseExact (s, formats, dfi, style, out result, out dto, true, ref longYear, false, ref e);
- } catch {
- result = MinValue;
- return false;
- }
- }
-
- internal static bool CoreParseExact (string s, string [] formats,
- DateTimeFormatInfo dfi, DateTimeStyles style,
- out DateTime ret, out DateTimeOffset dto,
- bool exact, ref bool longYear,
- bool setExceptionOnError, ref Exception exception,
- bool dateTimeOffset = false)
- {
- dto = new DateTimeOffset (0, TimeSpan.Zero);
- int i;
- bool incompleteFormat = false;
- for (i = 0; i < formats.Length; i++)
- {
- DateTime result;
- string format = formats[i];
- if (format == null || format == String.Empty)
- break;
-
- if (_DoParse (s, formats[i], null, exact, out result, out dto, dfi, style, false, ref incompleteFormat, ref longYear, dateTimeOffset)) {
- ret = result;
- return true;
- }
- }
-
- if (setExceptionOnError)
- exception = new FormatException ("Invalid format string");
- ret = DateTime.MinValue;
- return false;
- }
-
- public TimeSpan Subtract (DateTime value)
- {
- return new TimeSpan (Ticks) - new TimeSpan (value.Ticks);
- }
-
- public DateTime Subtract(TimeSpan value)
- {
- long newticks;
-
- newticks = Ticks - value.Ticks;
- if (newticks < 0 || newticks > MAX_VALUE_TICKS)
- throw new ArgumentOutOfRangeException ();
- DateTime ret = new DateTime (newticks);
- ret.encoded |= (encoded & KindMask);
- return ret;
- }
-
- public long ToFileTime()
- {
- DateTime universalTime = ToUniversalTime();
-
- if (universalTime.Ticks < w32file_epoch) {
- throw new ArgumentOutOfRangeException("file time is not valid");
- }
-
- return(universalTime.Ticks - w32file_epoch);
- }
-
- public long ToFileTimeUtc()
- {
- if (Kind == DateTimeKind.Local)
- return ToFileTime ();
-
- if (Ticks < w32file_epoch) {
- throw new ArgumentOutOfRangeException("file time is not valid");
- }
-
- return (Ticks - w32file_epoch);
- }
-
- 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 provider)
- {
- return ToString (null, provider);
- }
-
- public string ToString (string format)
- {
- return ToString (format, null);
- }
-
- public string ToString (string format, IFormatProvider provider)
- {
- DateTimeFormatInfo dfi = DateTimeFormatInfo.GetInstance (provider);
-
- if (format == null || format == String.Empty)
- format = "G";
-
- if (format.Length == 1) {
- char fchar = format [0];
- bool use_invariant, useutc;
- format = DateTimeUtils.GetStandardPattern (fchar, dfi, out useutc, out use_invariant);
- if (fchar == 'U')
- return DateTimeUtils.ToString (ToUniversalTime (), format, dfi);
-// return ToUniversalTime()._ToString (format, dfi);
-
- if (format == null)
- throw new FormatException ("format is not one of the format specifier characters defined for DateTimeFormatInfo");
-
- if (use_invariant)
- dfi = DateTimeFormatInfo.InvariantInfo;
- }
-
- // Don't convert UTC value. It just adds 'Z' for
- // 'u' format, for the same ticks.
- return DateTimeUtils.ToString (this, format, dfi);
- }
-
- public DateTime ToLocalTime ()
- {
- return TimeZone.CurrentTimeZone.ToLocalTime (this);
- }
-
- internal DateTime ToLocalTime (bool throwOnOverflow)
- {
- return ToLocalTime ();
- }
-
- public DateTime ToUniversalTime()
- {
- return TimeZone.CurrentTimeZone.ToUniversalTime (this);
- }
-
- /* OPERATORS */
-
- public static DateTime operator +(DateTime d, TimeSpan t)
- {
- try {
- long res = checked ((d.encoded & TicksMask) + t.Ticks);
- if (res < 0 || res > MAX_VALUE_TICKS){
- throw new ArgumentOutOfRangeException ();
- }
-
- return new DateTime (res, d.Kind);
- } catch (OverflowException){
- throw new ArgumentOutOfRangeException ();
- }
- }
-
- public static bool operator ==(DateTime d1, DateTime d2)
- {
- return ((d1.encoded & TicksMask) == (d2.encoded & TicksMask));
- }
-
- public static bool operator >(DateTime t1,DateTime t2)
- {
- return ((t1.encoded & TicksMask) > (t2.encoded & TicksMask));
- }
-
- public static bool operator >=(DateTime t1,DateTime t2)
- {
- return ((t1.encoded & TicksMask) >= (t2.encoded & TicksMask));
- }
-
- public static bool operator !=(DateTime d1, DateTime d2)
- {
- return ((d1.encoded & TicksMask) != (d2.encoded & TicksMask));
- }
-
- public static bool operator <(DateTime t1, DateTime t2)
- {
- return ((t1.encoded & TicksMask) < (t2.encoded & TicksMask));
- }
-
- public static bool operator <=(DateTime t1, DateTime t2)
- {
- return ((t1.encoded & TicksMask) <= (t2.encoded & TicksMask));
- }
-
- public static TimeSpan operator -(DateTime d1, DateTime d2)
- {
- return new TimeSpan ((d1.encoded & TicksMask) - (d2.encoded & TicksMask));
- }
-
- public static DateTime operator -(DateTime d, TimeSpan t)
- {
- try {
- long res = checked ((d.encoded & TicksMask) - t.Ticks);
- if (res < 0 || res > MAX_VALUE_TICKS)
- throw new ArgumentOutOfRangeException ();
- return new DateTime (res, d.Kind);
- } catch (OverflowException){
- throw new ArgumentOutOfRangeException ();
- }
- }
-
- 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 targetType, IFormatProvider provider)
- {
- if (targetType == null)
- throw new ArgumentNullException ("targetType");
-
- if (targetType == typeof (DateTime))
- return this;
- else if (targetType == typeof (String))
- return this.ToString (provider);
- else if (targetType == 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();
- }
-
- void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
- {
- long t = Ticks;
- info.AddValue ("ticks", t);
-
- // This is the new .NET format, encodes the kind on the top bits
- info.AddValue ("dateData", (UInt64)encoded);
- }
-
-#region Extracted from Microsoft reference sources
-
- // Number of 100ns ticks per time unit
- private const long TicksPerMillisecond = 10000;
- private const long TicksPerSecond = TicksPerMillisecond * 1000;
- private const long TicksPerMinute = TicksPerSecond * 60;
- private const long TicksPerHour = TicksPerMinute * 60;
- private const long TicksPerDay = TicksPerHour * 24;
-
- // Number of milliseconds per time unit
- private const int MillisPerSecond = 1000;
- private const int MillisPerMinute = MillisPerSecond * 60;
- private const int MillisPerHour = MillisPerMinute * 60;
- private const int MillisPerDay = MillisPerHour * 24;
-
- // Number of days in a non-leap year
- private const int DaysPerYear = 365;
- // Number of days in 4 years
- private const int DaysPer4Years = DaysPerYear * 4 + 1; // 1461
- // Number of days in 100 years
- private const int DaysPer100Years = DaysPer4Years * 25 - 1; // 36524
- // Number of days in 400 years
- private const int DaysPer400Years = DaysPer100Years * 4 + 1; // 146097
-
- // Number of days from 1/1/0001 to 12/31/1600
- private const int DaysTo1601 = DaysPer400Years * 4; // 584388
- // Number of days from 1/1/0001 to 12/30/1899
- private const int DaysTo1899 = DaysPer400Years * 4 + DaysPer100Years * 3 - 367;
- // Number of days from 1/1/0001 to 12/31/9999
- private const int DaysTo10000 = DaysPer400Years * 25 - 366; // 3652059
-
- internal const long MinTicks = 0;
- internal const long MaxTicks = DaysTo10000 * TicksPerDay - 1;
- private const long MaxMillis = (long)DaysTo10000 * MillisPerDay;
-
- private const long FileTimeOffset = DaysTo1601 * TicksPerDay;
- private const long DoubleDateOffset = DaysTo1899 * TicksPerDay;
- // The minimum OA date is 0100/01/01 (Note it's year 100).
- // The maximum OA date is 9999/12/31
- private const long OADateMinAsTicks = (DaysPer100Years - DaysPerYear) * TicksPerDay;
- // All OA dates must be greater than (not >=) OADateMinAsDouble
- private const double OADateMinAsDouble = -657435.0;
- // All OA dates must be less than (not <=) OADateMaxAsDouble
- private const double OADateMaxAsDouble = 2958466.0;
-
- private const int DatePartYear = 0;
- private const int DatePartDayOfYear = 1;
- private const int DatePartMonth = 2;
- private const int DatePartDay = 3;
-
- private static readonly int[] DaysToMonth365 = {
- 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
- private static readonly int[] DaysToMonth366 = {
- 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366};
-
- // Returns the tick count corresponding to the given year, month, and day.
- // Will check the if the parameters are valid.
- private static long DateToTicks(int year, int month, int day) {
- if (year >= 1 && year <= 9999 && month >= 1 && month <= 12) {
- int[] days = IsLeapYear(year)? DaysToMonth366: DaysToMonth365;
- if (day >= 1 && day <= days[month] - days[month - 1]) {
- int y = year - 1;
- int n = y * 365 + y / 4 - y / 100 + y / 400 + days[month - 1] + day - 1;
- return n * TicksPerDay;
- }
- }
- throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("ArgumentOutOfRange_BadYearMonthDay"));
- }
-
- // Return the tick count corresponding to the given hour, minute, second.
- // Will check the if the parameters are valid.
- private static long TimeToTicks(int hour, int minute, int second)
- {
- //TimeSpan.TimeToTicks is a family access function which does no error checking, so
- //we need to put some error checking out here.
- if (hour >= 0 && hour < 24 && minute >= 0 && minute < 60 && second >=0 && second < 60)
- {
- return (TimeSpan.TimeToTicks(hour, minute, second));
- }
- throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("ArgumentOutOfRange_BadHourMinuteSecond"));
- }
-
- // Tries to construct a DateTime from a given year, month, day, hour,
- // minute, second and millisecond.
- //
- internal static Boolean TryCreate(int year, int month, int day, int hour, int minute, int second, int millisecond, out DateTime result) {
- result = DateTime.MinValue;
- if (year < 1 || year > 9999 || month < 1 || month > 12) {
- return false;
- }
- int[] days = IsLeapYear(year) ? DaysToMonth366 : DaysToMonth365;
- if (day < 1 || day > days[month] - days[month - 1]) {
- return false;
- }
- if (hour < 0 || hour >= 24 || minute < 0 || minute >= 60 || second < 0 || second >= 60) {
- return false;
- }
- if (millisecond < 0 || millisecond >= MillisPerSecond) {
- return false;
- }
- long ticks = DateToTicks(year, month, day) + TimeToTicks(hour, minute, second);
-
- ticks += millisecond * TicksPerMillisecond;
- if (ticks < MinTicks || ticks > MaxTicks) {
- return false;
- }
- result = new DateTime(ticks, DateTimeKind.Unspecified);
- return true;
- }
-#endregion
-
-#if MONOTOUCH
- static DateTime () {
- if (MonoTouchAOTHelper.FalseFlag) {
- var comparer = new System.Collections.Generic.GenericComparer <DateTime> ();
- var eqcomparer = new System.Collections.Generic.GenericEqualityComparer <DateTime> ();
- }
- }
-#endif
- }
-}