Esempio n. 1
0
        /// <summary>
        /// This method is used to convert an ISO 8601 formatted date string to a DateTime value that it
        /// represents.
        /// </summary>
        /// <param name="dateTimeText">The ISO 8601 formatted date to parse.</param>
        /// <param name="toLocalTime">If true and the string is in a universal time format, the value is
        /// converted to local time before being returned.  If false, it is returned as a universal time
        /// value.</param>
        /// <returns>The specified string converted to a local date/time</returns>
        /// <exception cref="ArgumentException">This is thrown if the specified date/time string is not valid</exception>
        /// <remarks><para>The <see cref="System.DateTime.Parse(string)"/> method is capable of parsing a string
        /// in a very specific layout of the ISO 8601 format (SortableDateTimePattern).  However, if the string
        /// deviates even slightly from that pattern, it cannot be parsed.  This method takes an ISO 8601
        /// formatted date string in any of various formats and returns the DateTime value that it represents.</para>
        /// 
        /// <para>This method does not handle all possible forms of the ISO 8601 format, just those related to
        /// date and time values (<c>YYYY-MM-DDTHH:MM:SS.MMMM+HH:MM</c>).  Date and time separators (except the
        /// 'T') are optional as is the time zone specifier.  The time indicator ('T') and the time value can be
        /// omitted entirely if not needed.  A 'Z' (Zulu) can appear in place of the time zone specifier to
        /// indicate universal time.  Date/times in universal time format or with a time zone offset are
        /// converted to local time if the <c>bToLocalTime</c> parameter is set to true.  All other values are
        /// assumed to be local time already and will be returned unmodified as are date-only values.</para></remarks>
        public static DateTime FromISO8601String(string dateTimeText, bool toLocalTime)
        {
            DateTime convertedDate;
            int year, day, month, hour = 0, minutes = 0, wholeSeconds = 0, milliseconds = 0;
            double fracSeconds;

            Match m = reISO8601.Match(dateTimeText);

            if(!m.Success)
                throw new ArgumentException(LR.GetString("ExDUBadISOFormat"), "dateTimeText");

            // Day parts must be there
            year = Convert.ToInt32(m.Groups["Year"].Value, CultureInfo.InvariantCulture);
            month = Convert.ToInt32(m.Groups["Month"].Value, CultureInfo.InvariantCulture);
            day = Convert.ToInt32(m.Groups["Day"].Value, CultureInfo.InvariantCulture);

            // Time parts are optional
            if(m.Groups["Hour"].Value.Length != 0)
            {
                hour = Convert.ToInt32(m.Groups["Hour"].Value, CultureInfo.InvariantCulture);

                if(m.Groups["Minutes"].Value.Length != 0)
                {
                    minutes = Convert.ToInt32(m.Groups["Minutes"].Value, CultureInfo.InvariantCulture);

                    if(m.Groups["Seconds"].Value.Length != 0)
                    {
                        fracSeconds = Convert.ToDouble(m.Groups["Seconds"].Value, CultureInfo.InvariantCulture);
                        wholeSeconds = (int)fracSeconds;
                        milliseconds = (int)((fracSeconds - wholeSeconds) * 1000);
                    }
                }
            }

            convertedDate = new DateTime(year, month, day);

            // Sometimes we get something like 240000 to represent the time for a whole day.  By adding the time
            // parts as a time span, we bypass any potential problems with the DateTime() constructor that
            // expects the time parts to be within bounds.
            convertedDate += new TimeSpan(0, hour, minutes, wholeSeconds, milliseconds);

            // Convert to local time if necessary
            if(m.Groups["Zulu"].Value.Length != 0)
            {
                if(toLocalTime)
                   convertedDate = convertedDate.ToLocalTime();
            }
            else
                if(m.Groups["TZHours"].Value.Length != 0)
                {
                    // If a time zone offset was specified, add it to the time to get UTC
                    hour = Convert.ToInt32(m.Groups["TZHours"].Value, CultureInfo.InvariantCulture);

                    if(m.Groups["TZMinutes"].Value.Length == 0)
                        minutes = 0;
                    else
                        minutes = Convert.ToInt32(m.Groups["TZMinutes"].Value, CultureInfo.InvariantCulture);

                    convertedDate = convertedDate.AddMinutes(0 - (hour * 60 + minutes));

                    if(toLocalTime)
                        convertedDate = convertedDate.ToLocalTime();
                }

            return convertedDate;
        }