public static DateTime Parse(string value) { const string method = "Parse"; // Check that there is something there and of the right length. if (value == null) { throw new NullParameterException(typeof(DateTime), method, "value"); } if (value.Length < Constants.DateTime.ParseFormatMinLength) { throw new InvalidParameterFormatException(typeof(DateTime), method, "value", value, Constants.DateTime.ParseFormat); } // Check for separators in the right places. if (value[2] != '/' || value[5] != '/' || value[10] != ' ' || value[13] != ':' || value[16] != ':' || value[19] != '.') { throw new InvalidParameterFormatException(typeof(DateTime), method, "value", value, Constants.DateTime.ParseFormat); } // Extract each part. int year = ParseInt(value, 6, 4, false); int month = ParseInt(value, 3, 2, false); int day = ParseInt(value, 0, 2, false); int hour = ParseInt(value, 11, 2, false); int minute = ParseInt(value, 14, 2, false); int second = ParseInt(value, 17, 2, false); int millisecond = ParseInt(value, 20, 3, false); int microsecond = ParseInt(value, 23, 3, false); int nanosecond = ParseInt(value, 26, 3, false); // Time zone if (value.Length > Constants.DateTime.ParseFormatMinLength) { if (value[29] != ' ') { throw new InvalidParameterFormatException(typeof(DateTime), method, "value", value, Constants.DateTime.ParseFormat); } Type.TimeZone timeZone = Type.TimeZone.Parse(value.Substring(30)); return(new DateTime(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond, timeZone)); } else { return(new DateTime(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond)); } }
/// <summary> /// Converts the XML representation of a date, time and time zone to a DateTime /// object. The input string can be a valid XSD dateTime /// (http://www.w3.org/TR/xmlschema-2/#dateTime) OR an XSD dateTime in UTC /// (with time zone designator 'Z'), followed by a space and a time zone name or /// abbreviation. /// </summary> /// <remarks> /// Valid input examples: /// /// "2004-03-24T17:04:00.56Z" (valid XSD dateTime). The resulting DateTime will have /// TimeZone set to UTC. /// /// "2004-03-24T17:04:00-06:00" (the same DateTime in a UTC-06:00 time zone). /// The resulting DateTime will have TimeZone set to a time zone 6 hours behind /// UTC with no daylight savings. /// /// "2004-03-24T06:04:00Z AEST" (the same DateTime in AEST). The resulting DateTime /// will have TimeZone set to AUS Eastern Standard Time. /// /// "2004-03-24T06:04:00Z AUS Eastern Standard Time" (same as above with the full /// time zone name). /// /// "2004-03-24T06:04:00Z +11:00" (the same DateTime in a UTC+11:00 time zone). /// </remarks> internal static DateTime FromXml(string value) { const string method = "FromXml"; // Check that there is something there and of the right length. if (value == null) { throw new NullParameterException(typeof(DateTime), method, "value"); } if (value.Length < DateTimeHelper.DateTimeXmlFormatMinLength) { throw new InvalidParameterFormatException(typeof(DateTime), method, "value", value, DateTimeHelper.DateTimeXmlFormat); } // Check for separators in the right places. if (value[4] != '-' || value[7] != '-' || value[10] != 'T' || value[13] != ':' || value[16] != ':') { throw new InvalidParameterFormatException(typeof(DateTime), method, "value", value, DateTimeHelper.DateTimeXmlFormat); } // Extract each part, except for fractional seconds. int year = ParseInt(value, 0, 4, true); int month = ParseInt(value, 5, 2, true); int day = ParseInt(value, 8, 2, true); int hour = ParseInt(value, 11, 2, true); int minute = ParseInt(value, 14, 2, true); int second = ParseInt(value, 17, 2, true); int millisecond = 0; int microsecond = 0; int nanosecond = 0; int offset; // Fractional seconds if (value[19] == '.') { int index = 20; while (index < value.Length && System.Char.IsDigit(value, index)) { index++; } if (index == 20) { throw new InvalidParameterFormatException(typeof(DateTime), method, "value", value, DateTimeHelper.DateTimeXmlFormat); } string fraction = value.Substring(20, index - 20); if (fraction.Length < 9) { fraction = fraction.PadRight(9, '0'); } millisecond = System.Int32.Parse(fraction.Substring(0, 3)); microsecond = System.Int32.Parse(fraction.Substring(3, 3)); nanosecond = System.Int32.Parse(fraction.Substring(6, 3)); // XSD dateTime type allows arbitrary precision, so extra decimal // places are valid. Just ignore them. offset = index; } else { offset = 19; } // Time zone // A time zone must be specified if (value.Length == offset) { throw new InvalidParameterFormatException(typeof(DateTime), method, "value", value, DateTimeHelper.DateTimeXmlFormat); } if (value[offset] == 'Z') { DateTime dateTime = new DateTime(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond, Type.TimeZone.UTC); if (value.Length == offset + 1) { return(dateTime); // Leave the time zone as UTC } else { // We should have a space followed by a time zone name (or abbreviation) if (value[offset + 1] != ' ') { throw new InvalidParameterFormatException(typeof(DateTime), method, "value", value, DateTimeHelper.DateTimeXmlFormat); } // Convert to the specified time zone string timeZoneString = value.Substring(offset + 2); if (timeZoneString.Length == 0) { throw new InvalidParameterFormatException(typeof(DateTime), method, "value", value, DateTimeHelper.DateTimeXmlFormat); } Type.TimeZone timeZone = Type.TimeZone.Parse(timeZoneString); return(dateTime.ToTimeZone(timeZone)); } } else { // Parse the rest of the string as a time zone - it must begin with // '+' or '-', a time zone name is not acceptable here. if (value[offset] != '+' && value[offset] != '-') { throw new InvalidParameterFormatException(typeof(DateTime), method, "value", value, DateTimeHelper.DateTimeXmlFormat); } Type.TimeZone timeZone = Type.TimeZone.Parse(value.Substring(offset)); return(new DateTime(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond, timeZone)); } }