private static bool ParseISO8601(ref DateTimeRawInfo raw, ref __DTString str, DateTimeStyles styles, ref DateTimeResult result) { if (raw.year >= 0 && raw.GetNumber(0) >= 0) { raw.GetNumber(1); } str.Index--; int second = 0; double num = 0.0; str.SkipWhiteSpaces(); int hour; if (!DateTimeParse.ParseDigits(ref str, 2, out hour)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } str.SkipWhiteSpaces(); if (!str.Match(':')) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } str.SkipWhiteSpaces(); int minute; if (!DateTimeParse.ParseDigits(ref str, 2, out minute)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } str.SkipWhiteSpaces(); if (str.Match(':')) { str.SkipWhiteSpaces(); if (!DateTimeParse.ParseDigits(ref str, 2, out second)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if (str.Match('.')) { if (!DateTimeParse.ParseFraction(ref str, out num)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } str.Index--; } str.SkipWhiteSpaces(); } if (str.GetNext()) { char @char = str.GetChar(); if (@char == '+' || @char == '-') { result.flags |= ParseFlags.TimeZoneUsed; if (!DateTimeParse.ParseTimeZone(ref str, ref result.timeZoneOffset)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } } else { if (@char == 'Z' || @char == 'z') { result.flags |= ParseFlags.TimeZoneUsed; result.timeZoneOffset = TimeSpan.Zero; result.flags |= ParseFlags.TimeZoneUtc; } else { str.Index--; } } str.SkipWhiteSpaces(); if (str.Match('#')) { if (!DateTimeParse.VerifyValidPunctuation(ref str)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } str.SkipWhiteSpaces(); } if (str.Match('\0') && !DateTimeParse.VerifyValidPunctuation(ref str)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if (str.GetNext()) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } } Calendar defaultInstance = GregorianCalendar.GetDefaultInstance(); DateTime parsedDate; if (!defaultInstance.TryToDateTime(raw.year, raw.GetNumber(0), raw.GetNumber(1), hour, minute, second, 0, result.era, out parsedDate)) { result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null); return false; } parsedDate = parsedDate.AddTicks((long)Math.Round(num * 10000000.0)); result.parsedDate = parsedDate; return DateTimeParse.DetermineTimeZoneAdjustments(ref result, styles, false); }
/*=================================MatchAbbreviatedTimeMark================================== **Action: Parse the abbreviated time mark (AM/PM) from string starting at str.Index. **Returns: TM_AM or TM_PM. **Arguments: str: a __DTString. The parsing will start from the ** next character after str.Index. **Exceptions: FormatException if a abbreviated time mark can not be found. ==============================================================================*/ private static bool MatchAbbreviatedTimeMark(ref __DTString str, DateTimeFormatInfo dtfi, ref TM result) { // NOTENOTE : the assumption here is that abbreviated time mark is the first // character of the AM/PM designator. If this invariant changes, we have to // change the code below. if (str.GetNext()) { if (str.GetChar() == dtfi.AMDesignator[0]) { result = TM.AM; return (true); } if (str.GetChar() == dtfi.PMDesignator[0]) { result = TM.PM; return (true); } } return false; }
// Given a specified format character, parse and update the parsing result. // private static bool ParseByFormat( ref __DTString str, ref __DTString format, ref ParsingInfo parseInfo, DateTimeFormatInfo dtfi, ref DateTimeResult result) { int tokenLen = 0; int tempYear = 0, tempMonth = 0, tempDay = 0, tempDayOfWeek = 0, tempHour = 0, tempMinute = 0, tempSecond = 0; double tempFraction = 0; TM tempTimeMark = 0; char ch = format.GetChar(); switch (ch) { case 'y': tokenLen = format.GetRepeatCount(); bool parseResult; if (dtfi.HasForceTwoDigitYears) { parseResult = ParseDigits(ref str, 1, 4, out tempYear); } else { if (tokenLen <= 2) { parseInfo.fUseTwoDigitYear = true; } parseResult = ParseDigits(ref str, tokenLen, out tempYear); } if (!parseResult && parseInfo.fCustomNumberParser) { parseResult = parseInfo.parseNumberDelegate(ref str, tokenLen, out tempYear); } if (!parseResult) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return (false); } if (!CheckNewValue(ref result.Year, tempYear, ch, ref result)) { return (false); } break; case 'M': tokenLen = format.GetRepeatCount(); if (tokenLen <= 2) { if (!ParseDigits(ref str, tokenLen, out tempMonth)) { if (!parseInfo.fCustomNumberParser || !parseInfo.parseNumberDelegate(ref str, tokenLen, out tempMonth)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return (false); } } } else { if (tokenLen == 3) { if (!MatchAbbreviatedMonthName(ref str, dtfi, ref tempMonth)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return (false); } } else { if (!MatchMonthName(ref str, dtfi, ref tempMonth)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return (false); } } result.flags |= ParseFlags.ParsedMonthName; } if (!CheckNewValue(ref result.Month, tempMonth, ch, ref result)) { return (false); } break; case 'd': // Day & Day of week tokenLen = format.GetRepeatCount(); if (tokenLen <= 2) { // "d" & "dd" if (!ParseDigits(ref str, tokenLen, out tempDay)) { if (!parseInfo.fCustomNumberParser || !parseInfo.parseNumberDelegate(ref str, tokenLen, out tempDay)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return (false); } } if (!CheckNewValue(ref result.Day, tempDay, ch, ref result)) { return (false); } } else { if (tokenLen == 3) { // "ddd" if (!MatchAbbreviatedDayName(ref str, dtfi, ref tempDayOfWeek)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return (false); } } else { // "dddd*" if (!MatchDayName(ref str, dtfi, ref tempDayOfWeek)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return (false); } } if (!CheckNewValue(ref parseInfo.dayOfWeek, tempDayOfWeek, ch, ref result)) { return (false); } } break; case 'g': tokenLen = format.GetRepeatCount(); // Put the era value in result.era. if (!MatchEraName(ref str, dtfi, ref result.era)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return (false); } break; case 'h': parseInfo.fUseHour12 = true; tokenLen = format.GetRepeatCount(); if (!ParseDigits(ref str, (tokenLen < 2? 1 : 2), out tempHour)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return (false); } if (!CheckNewValue(ref result.Hour, tempHour, ch, ref result)) { return (false); } break; case 'H': tokenLen = format.GetRepeatCount(); if (!ParseDigits(ref str, (tokenLen < 2? 1 : 2), out tempHour)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return (false); } if (!CheckNewValue(ref result.Hour, tempHour, ch, ref result)) { return (false); } break; case 'm': tokenLen = format.GetRepeatCount(); if (!ParseDigits(ref str, (tokenLen < 2? 1 : 2), out tempMinute)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return (false); } if (!CheckNewValue(ref result.Minute, tempMinute, ch, ref result)) { return (false); } break; case 's': tokenLen = format.GetRepeatCount(); if (!ParseDigits(ref str, (tokenLen < 2? 1 : 2), out tempSecond)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return (false); } if (!CheckNewValue(ref result.Second, tempSecond, ch, ref result)) { return (false); } break; case 'f': case 'F': tokenLen = format.GetRepeatCount(); if (tokenLen <= DateTimeFormat.MaxSecondsFractionDigits) { if (!ParseFractionExact(ref str, tokenLen, ref tempFraction)) { if (ch == 'f') { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return (false); } } if (result.fraction < 0) { result.fraction = tempFraction; } else { if (tempFraction != result.fraction) { result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_RepeatDateTimePattern", ch); return (false); } } } else { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return (false); } break; case 't': // AM/PM designator tokenLen = format.GetRepeatCount(); if (tokenLen == 1) { if (!MatchAbbreviatedTimeMark(ref str, dtfi, ref tempTimeMark)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return (false); } } else { if (!MatchTimeMark(ref str, dtfi, ref tempTimeMark)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return (false); } } if (parseInfo.timeMark == TM.NotSet) { parseInfo.timeMark = tempTimeMark; } else { if (parseInfo.timeMark != tempTimeMark) { result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_RepeatDateTimePattern", ch); return (false); } } break; case 'z': // timezone offset tokenLen = format.GetRepeatCount(); { TimeSpan tempTimeZoneOffset = new TimeSpan(0); if (!ParseTimeZoneOffset(ref str, tokenLen, ref tempTimeZoneOffset)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return (false); } if ((result.flags & ParseFlags.TimeZoneUsed) != 0 && tempTimeZoneOffset != result.timeZoneOffset) { result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_RepeatDateTimePattern", 'z'); return (false); } result.timeZoneOffset = tempTimeZoneOffset; result.flags |= ParseFlags.TimeZoneUsed; } break; case 'Z': if ((result.flags & ParseFlags.TimeZoneUsed) != 0 && result.timeZoneOffset != TimeSpan.Zero) { result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_RepeatDateTimePattern", 'Z'); return (false); } result.flags |= ParseFlags.TimeZoneUsed; result.timeZoneOffset = new TimeSpan(0); result.flags |= ParseFlags.TimeZoneUtc; // The updating of the indexes is to reflect that ParseExact MatchXXX methods assume that // they need to increment the index and Parse GetXXX do not. Since we are calling a Parse // method from inside ParseExact we need to adjust this. Long term, we should try to // eliminate this discrepancy. str.Index++; if (!GetTimeZoneName(ref str)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } str.Index--; break; case 'K': // This should parse either as a blank, the 'Z' character or a local offset like "-07:00" if (str.Match('Z')) { if ((result.flags & ParseFlags.TimeZoneUsed) != 0 && result.timeZoneOffset != TimeSpan.Zero) { result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_RepeatDateTimePattern", 'K'); return (false); } result.flags |= ParseFlags.TimeZoneUsed; result.timeZoneOffset = new TimeSpan(0); result.flags |= ParseFlags.TimeZoneUtc; } else if (str.Match('+') || str.Match('-')) { str.Index--; // Put the character back for the parser TimeSpan tempTimeZoneOffset = new TimeSpan(0); if (!ParseTimeZoneOffset(ref str, 3, ref tempTimeZoneOffset)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return (false); } if ((result.flags & ParseFlags.TimeZoneUsed) != 0 && tempTimeZoneOffset != result.timeZoneOffset) { result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_RepeatDateTimePattern", 'K'); return (false); } result.timeZoneOffset = tempTimeZoneOffset; result.flags |= ParseFlags.TimeZoneUsed; } // Otherwise it is unspecified and we consume no characters break; case ':': // We match the separator in time pattern with the character in the time string if both equal to ':' or the date separator is matching the characters in the date string // We have to exclude the case when the time separator is more than one character and starts with ':' something like "::" for instance. if (((dtfi.TimeSeparator.Length > 1 && dtfi.TimeSeparator[0] == ':') || !str.Match(':')) && !str.Match(dtfi.TimeSeparator)) { // A time separator is expected. result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } break; case '/': // We match the separator in date pattern with the character in the date string if both equal to '/' or the date separator is matching the characters in the date string // We have to exclude the case when the date separator is more than one character and starts with '/' something like "//" for instance. if (((dtfi.DateSeparator.Length > 1 && dtfi.DateSeparator[0] == '/') || !str.Match('/')) && !str.Match(dtfi.DateSeparator)) { // A date separator is expected. result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } break; case '\"': case '\'': StringBuilder enquotedString = new StringBuilder(); // Use ParseQuoteString so that we can handle escape characters within the quoted string. if (!TryParseQuoteString(format.Value, format.Index, enquotedString, out tokenLen)) { result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadQuote", ch); return (false); } format.Index += tokenLen - 1; // Some cultures uses space in the quoted string. E.g. Spanish has long date format as: // "dddd, dd' de 'MMMM' de 'yyyy". When inner spaces flag is set, we should skip whitespaces if there is space // in the quoted string. String quotedStr = enquotedString.ToString(); for (int i = 0; i < quotedStr.Length; i++) { if (quotedStr[i] == ' ' && parseInfo.fAllowInnerWhite) { str.SkipWhiteSpaces(); } else if (!str.Match(quotedStr[i])) { // Can not find the matching quoted string. result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } } // The "r" and "u" formats incorrectly quoted 'GMT' and 'Z', respectively. We cannot // correct this mistake for DateTime.ParseExact for compatibility reasons, but we can // fix it for DateTimeOffset.ParseExact as DateTimeOffset has not been publically released // with this issue. if ((result.flags & ParseFlags.CaptureOffset) != 0) { if ((result.flags & ParseFlags.Rfc1123Pattern) != 0 && quotedStr == GMTName) { result.flags |= ParseFlags.TimeZoneUsed; result.timeZoneOffset = TimeSpan.Zero; } else if ((result.flags & ParseFlags.UtcSortPattern) != 0 && quotedStr == ZuluName) { result.flags |= ParseFlags.TimeZoneUsed; result.timeZoneOffset = TimeSpan.Zero; } } break; case '%': // Skip this so we can get to the next pattern character. // Used in case like "%d", "%y" // Make sure the next character is not a '%' again. if (format.Index >= format.Value.Length - 1 || format.Value[format.Index + 1] == '%') { result.SetFailure(ParseFailureKind.Format, "Format_BadFormatSpecifier", null); return false; } break; case '\\': // Escape character. For example, "\d". // Get the next character in format, and see if we can // find a match in str. if (format.GetNext()) { if (!str.Match(format.GetChar())) { // Can not find a match for the escaped character. result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } } else { result.SetFailure(ParseFailureKind.Format, "Format_BadFormatSpecifier", null); return false; } break; case '.': if (!str.Match(ch)) { if (format.GetNext()) { // If we encounter the pattern ".F", and the dot is not present, it is an optional // second fraction and we can skip this format. if (format.Match('F')) { format.GetRepeatCount(); break; } } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } break; default: if (ch == ' ') { if (parseInfo.fAllowInnerWhite) { // Skip whitespaces if AllowInnerWhite. // Do nothing here. } else { if (!str.Match(ch)) { // If the space does not match, and trailing space is allowed, we do // one more step to see if the next format character can lead to // successful parsing. // This is used to deal with special case that a empty string can match // a specific pattern. // The example here is af-ZA, which has a time format like "hh:mm:ss tt". However, // its AM symbol is "" (empty string). If fAllowTrailingWhite is used, and time is in // the AM, we will trim the whitespaces at the end, which will lead to a failure // when we are trying to match the space before "tt". if (parseInfo.fAllowTrailingWhite) { if (format.GetNext()) { if (ParseByFormat(ref str, ref format, ref parseInfo, dtfi, ref result)) { return (true); } } } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } // Found a macth. } } else { if (format.MatchSpecifiedWord(GMTName)) { format.Index += (GMTName.Length - 1); // Found GMT string in format. This means the DateTime string // is in GMT timezone. result.flags |= ParseFlags.TimeZoneUsed; result.timeZoneOffset = TimeSpan.Zero; if (!str.Match(GMTName)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } } else if (!str.Match(ch)) { // ch is expected. result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } } break; } // switch return (true); }
//////////////////////////////////////////////////////////////////////// // // Actions: // Parse the current word as a Hebrew number. // This is used by DateTime.ParseExact(). // //////////////////////////////////////////////////////////////////////// internal static bool MatchHebrewDigits(ref __DTString str, int digitLen, out int number) { number = 0; // Create a context object so that we can parse the Hebrew number text character by character. HebrewNumberParsingContext context = new HebrewNumberParsingContext(0); // Set this to ContinueParsing so that we will run the following while loop in the first time. HebrewNumberParsingState state = HebrewNumberParsingState.ContinueParsing; while (state == HebrewNumberParsingState.ContinueParsing && str.GetNext()) { state = HebrewNumber.ParseByChar(str.GetChar(), ref context); } if (state == HebrewNumberParsingState.FoundEndOfHebrewNumber) { // If we have reached a terminal state, update the result and returns. number = context.result; return (true); } // If we run out of the character before reaching FoundEndOfHebrewNumber, or // the state is InvalidHebrewNumber or ContinueParsing, we fail to match a Hebrew number. // Return an error. return false; }
/*=================================ParseSign================================== **Action: Parse a positive or a negative sign. **Returns: true if postive sign. flase if negative sign. **Arguments: str: a __DTString. The parsing will start from the ** next character after str.Index. **Exceptions: FormatException if end of string is encountered or a sign ** symbol is not found. ==============================================================================*/ private static bool ParseSign(ref __DTString str, ref bool result) { if (!str.GetNext()) { // A sign symbol ('+' or '-') is expected. However, end of string is encountered. return false; } char ch = str.GetChar(); if (ch == '+') { result = true; return (true); } else if (ch == '-') { result = false; return (true); } // A sign symbol ('+' or '-') is expected. return false; }
private static bool MatchAbbreviatedTimeMark(ref __DTString str, DateTimeFormatInfo dtfi, ref DateTimeParse.TM result) { if (str.GetNext()) { if (str.GetChar() == dtfi.AMDesignator[0]) { result = DateTimeParse.TM.AM; return true; } if (str.GetChar() == dtfi.PMDesignator[0]) { result = DateTimeParse.TM.PM; return true; } } return false; }
/*=================================ParseSign================================== **Action: Parse a positive or a negative sign. **Returns: true if postive sign. flase if negative sign. **Arguments: str: a __DTString. The parsing will start from the ** next character after str.Index. **Exceptions: FormatException if end of string is encountered or a sign ** symbol is not found. ==============================================================================*/ private static bool ParseSign(__DTString str, bool isThrowExp, ref bool result) { if (!str.GetNext()) { // A sign symbol ('+' or '-') is expected. However, end of string is encountered. return (ParseFormatError(isThrowExp, "Format_BadDateTime")); } char ch = str.GetChar(); if (ch == '+') { result = true; return (true); } else if (ch == '-') { result = false; return (true); } // A sign symbol ('+' or '-') is expected. return (ParseFormatError(isThrowExp, "Format_BadDateTime")); }
private static bool ParseByFormat(ref __DTString str, ref __DTString format, ref ParsingInfo parseInfo, DateTimeFormatInfo dtfi, ref DateTimeResult result) { bool flag; int returnValue = 0; int num2 = 0; int num3 = 0; int num4 = 0; int num5 = 0; int num6 = 0; int num7 = 0; int num8 = 0; double num9 = 0.0; TM aM = TM.AM; char failureMessageFormatArgument = format.GetChar(); switch (failureMessageFormatArgument) { case '%': if ((format.Index < (format.Value.Length - 1)) && (format.Value[format.Index + 1] != '%')) { goto Label_0A5A; } result.SetFailure(ParseFailureKind.Format, "Format_BadFormatSpecifier", null); return false; case '\'': case '"': { StringBuilder builder = new StringBuilder(); if (!TryParseQuoteString(format.Value, format.Index, builder, out returnValue)) { result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadQuote", failureMessageFormatArgument); return false; } format.Index += returnValue - 1; string str2 = builder.ToString(); for (int i = 0; i < str2.Length; i++) { if ((str2[i] == ' ') && parseInfo.fAllowInnerWhite) { str.SkipWhiteSpaces(); } else if (!str.Match(str2[i])) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } } if ((result.flags & ParseFlags.CaptureOffset) != 0) { if (((result.flags & ParseFlags.Rfc1123Pattern) != 0) && (str2 == "GMT")) { result.flags |= ParseFlags.TimeZoneUsed; result.timeZoneOffset = TimeSpan.Zero; } else if (((result.flags & ParseFlags.UtcSortPattern) != 0) && (str2 == "Z")) { result.flags |= ParseFlags.TimeZoneUsed; result.timeZoneOffset = TimeSpan.Zero; } } goto Label_0A5A; } case '.': if (!str.Match(failureMessageFormatArgument)) { if (!format.GetNext() || !format.Match('F')) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } format.GetRepeatCount(); } goto Label_0A5A; case '/': if (str.Match(dtfi.DateSeparator)) { goto Label_0A5A; } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; case ':': if (str.Match(dtfi.TimeSeparator)) { goto Label_0A5A; } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; case 'F': case 'f': returnValue = format.GetRepeatCount(); if (returnValue <= 7) { if (!ParseFractionExact(ref str, returnValue, ref num9) && (failureMessageFormatArgument == 'f')) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if (result.fraction >= 0.0) { if (num9 != result.fraction) { result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_RepeatDateTimePattern", failureMessageFormatArgument); return false; } } else { result.fraction = num9; } goto Label_0A5A; } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; case 'H': returnValue = format.GetRepeatCount(); if (ParseDigits(ref str, (returnValue < 2) ? 1 : 2, out num6)) { if (!CheckNewValue(ref result.Hour, num6, failureMessageFormatArgument, ref result)) { return false; } goto Label_0A5A; } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; case 'K': if (!str.Match('Z')) { if (str.Match('+') || str.Match('-')) { str.Index--; TimeSpan span2 = new TimeSpan(0L); if (!ParseTimeZoneOffset(ref str, 3, ref span2)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if (((result.flags & ParseFlags.TimeZoneUsed) != 0) && (span2 != result.timeZoneOffset)) { result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_RepeatDateTimePattern", 'K'); return false; } result.timeZoneOffset = span2; result.flags |= ParseFlags.TimeZoneUsed; } goto Label_0A5A; } if (((result.flags & ParseFlags.TimeZoneUsed) == 0) || !(result.timeZoneOffset != TimeSpan.Zero)) { result.flags |= ParseFlags.TimeZoneUsed; result.timeZoneOffset = new TimeSpan(0L); result.flags |= ParseFlags.TimeZoneUtc; goto Label_0A5A; } result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_RepeatDateTimePattern", 'K'); return false; case 'M': returnValue = format.GetRepeatCount(); if (returnValue > 2) { if (returnValue == 3) { if (!MatchAbbreviatedMonthName(ref str, dtfi, ref num3)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } } else if (!MatchMonthName(ref str, dtfi, ref num3)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } result.flags |= ParseFlags.ParsedMonthName; goto Label_0223; } if (ParseDigits(ref str, returnValue, out num3) || (parseInfo.fCustomNumberParser && parseInfo.parseNumberDelegate(ref str, returnValue, out num3))) { goto Label_0223; } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; case 'Z': if (((result.flags & ParseFlags.TimeZoneUsed) == 0) || !(result.timeZoneOffset != TimeSpan.Zero)) { result.flags |= ParseFlags.TimeZoneUsed; result.timeZoneOffset = new TimeSpan(0L); result.flags |= ParseFlags.TimeZoneUtc; str.Index++; if (!GetTimeZoneName(ref str)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } str.Index--; goto Label_0A5A; } result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_RepeatDateTimePattern", 'Z'); return false; case '\\': if (!format.GetNext()) { result.SetFailure(ParseFailureKind.Format, "Format_BadFormatSpecifier", null); return false; } if (str.Match(format.GetChar())) { goto Label_0A5A; } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; case 'd': returnValue = format.GetRepeatCount(); if (returnValue > 2) { if (returnValue == 3) { if (!MatchAbbreviatedDayName(ref str, dtfi, ref num5)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } } else if (!MatchDayName(ref str, dtfi, ref num5)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if (!CheckNewValue(ref parseInfo.dayOfWeek, num5, failureMessageFormatArgument, ref result)) { return false; } goto Label_0A5A; } if (ParseDigits(ref str, returnValue, out num4) || (parseInfo.fCustomNumberParser && parseInfo.parseNumberDelegate(ref str, returnValue, out num4))) { if (!CheckNewValue(ref result.Day, num4, failureMessageFormatArgument, ref result)) { return false; } goto Label_0A5A; } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; case 'g': returnValue = format.GetRepeatCount(); if (MatchEraName(ref str, dtfi, ref result.era)) { goto Label_0A5A; } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; case 'h': parseInfo.fUseHour12 = true; returnValue = format.GetRepeatCount(); if (ParseDigits(ref str, (returnValue < 2) ? 1 : 2, out num6)) { if (!CheckNewValue(ref result.Hour, num6, failureMessageFormatArgument, ref result)) { return false; } goto Label_0A5A; } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; case 's': returnValue = format.GetRepeatCount(); if (ParseDigits(ref str, (returnValue < 2) ? 1 : 2, out num8)) { if (!CheckNewValue(ref result.Second, num8, failureMessageFormatArgument, ref result)) { return false; } goto Label_0A5A; } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; case 't': if (format.GetRepeatCount() != 1) { if (!MatchTimeMark(ref str, dtfi, ref aM)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } goto Label_04DE; } if (MatchAbbreviatedTimeMark(ref str, dtfi, ref aM)) { goto Label_04DE; } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; case 'm': returnValue = format.GetRepeatCount(); if (!ParseDigits(ref str, (returnValue < 2) ? 1 : 2, out num7)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if (CheckNewValue(ref result.Minute, num7, failureMessageFormatArgument, ref result)) { goto Label_0A5A; } return false; case 'y': returnValue = format.GetRepeatCount(); if (!dtfi.HasForceTwoDigitYears) { if (returnValue <= 2) { parseInfo.fUseTwoDigitYear = true; } flag = ParseDigits(ref str, returnValue, out num2); break; } flag = ParseDigits(ref str, 1, 4, out num2); break; case 'z': { returnValue = format.GetRepeatCount(); TimeSpan span = new TimeSpan(0L); if (ParseTimeZoneOffset(ref str, returnValue, ref span)) { if (((result.flags & ParseFlags.TimeZoneUsed) != 0) && (span != result.timeZoneOffset)) { result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_RepeatDateTimePattern", 'z'); return false; } result.timeZoneOffset = span; result.flags |= ParseFlags.TimeZoneUsed; goto Label_0A5A; } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } default: if (failureMessageFormatArgument == ' ') { if (!parseInfo.fAllowInnerWhite && !str.Match(failureMessageFormatArgument)) { if ((parseInfo.fAllowTrailingWhite && format.GetNext()) && ParseByFormat(ref str, ref format, ref parseInfo, dtfi, ref result)) { return true; } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } } else if (format.MatchSpecifiedWord("GMT")) { format.Index += "GMT".Length - 1; result.flags |= ParseFlags.TimeZoneUsed; result.timeZoneOffset = TimeSpan.Zero; if (!str.Match("GMT")) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } } else if (!str.Match(failureMessageFormatArgument)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } goto Label_0A5A; } if (!flag && parseInfo.fCustomNumberParser) { flag = parseInfo.parseNumberDelegate(ref str, returnValue, out num2); } if (!flag) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if (CheckNewValue(ref result.Year, num2, failureMessageFormatArgument, ref result)) { goto Label_0A5A; } return false; Label_0223: if (CheckNewValue(ref result.Month, num3, failureMessageFormatArgument, ref result)) { goto Label_0A5A; } return false; Label_04DE: if (parseInfo.timeMark == TM.NotSet) { parseInfo.timeMark = aM; } else if (parseInfo.timeMark != aM) { result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_RepeatDateTimePattern", failureMessageFormatArgument); return false; } Label_0A5A: return true; }
private static bool ParseISO8601(ref DateTimeRawInfo raw, ref __DTString str, DateTimeStyles styles, ref DateTimeResult result) { int num; int num2; DateTime time; if ((raw.year >= 0) && (raw.GetNumber(0) >= 0)) { raw.GetNumber(1); } str.Index--; int num3 = 0; double num4 = 0.0; str.SkipWhiteSpaces(); if (!ParseDigits(ref str, 2, out num)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } str.SkipWhiteSpaces(); if (!str.Match(':')) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } str.SkipWhiteSpaces(); if (!ParseDigits(ref str, 2, out num2)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } str.SkipWhiteSpaces(); if (str.Match(':')) { str.SkipWhiteSpaces(); if (!ParseDigits(ref str, 2, out num3)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if (str.Match('.')) { if (!ParseFraction(ref str, out num4)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } str.Index--; } str.SkipWhiteSpaces(); } if (str.GetNext()) { switch (str.GetChar()) { case '+': case '-': result.flags |= ParseFlags.TimeZoneUsed; if (!ParseTimeZone(ref str, ref result.timeZoneOffset)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } break; case 'Z': case 'z': result.flags |= ParseFlags.TimeZoneUsed; result.timeZoneOffset = TimeSpan.Zero; result.flags |= ParseFlags.TimeZoneUtc; break; default: str.Index--; break; } str.SkipWhiteSpaces(); if (str.Match('#')) { if (!VerifyValidPunctuation(ref str)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } str.SkipWhiteSpaces(); } if (str.Match('\0') && !VerifyValidPunctuation(ref str)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if (str.GetNext()) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } } if (!GregorianCalendar.GetDefaultInstance().TryToDateTime(raw.year, raw.GetNumber(0), raw.GetNumber(1), num, num2, num3, 0, result.era, out time)) { result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null); return false; } time = time.AddTicks((long) Math.Round((double) (num4 * 10000000.0))); result.parsedDate = time; if (!DetermineTimeZoneAdjustments(ref result, styles, false)) { return false; } return true; }
/*=================================ParseTimeZone========================== **Action: Parse the timezone offset in the following format: ** "+8", "+08", "+0800", "+0800" ** This method is used by DateTime.Parse(). **Returns: The TimeZone offset. **Arguments: ** str the parsing string **Exceptions: ** FormatException if invalid timezone format is found. ============================================================================*/ private static TimeSpan ParseTimeZone(__DTString str, char offsetChar) { // The hour/minute offset for timezone. int hourOffset = 0; int minuteOffset = 0; if (str.GetNextDigit()) { // Get the first digit, Try if we can parse timezone in the form of "+8". hourOffset = str.GetDigit(); if (str.GetNextDigit()) { // Parsing "+18" hourOffset *= 10; hourOffset += str.GetDigit(); if (str.GetNext()) { char ch; if (Char.IsDigit(ch = str.GetChar())) { // Parsing "+1800" // Put the char back, since we already get the char in the previous GetNext() call. str.Index--; if (ParseDigits(str, 2, true, out minuteOffset)) { // ParseDigits() does not advance the char for us, so do it here. str.Index++; } else { throw new FormatException(Environment.GetResourceString("Format_BadDateTime")); } } else if (ch == ':') { // Parsing "+18:00" if (ParseDigits(str, 2, true, out minuteOffset)) { str.Index++; } else { throw new FormatException(Environment.GetResourceString("Format_BadDateTime")); } } else { // Not a digit, not a colon, put this char back. str.Index--; } } } // The next char is not a digit, so we get the timezone in the form of "+8". } else { // Invalid timezone: No numbers after +/-. throw new FormatException(Environment.GetResourceString("Format_BadDateTime")); } TimeSpan timezoneOffset = new TimeSpan(hourOffset, minuteOffset, 0); if (offsetChar == '-') { timezoneOffset = timezoneOffset.Negate(); } return (timezoneOffset); }
// // This is the lexer. Check the character at the current index, and put the found token in dtok and // some raw date/time information in raw. // private static void Lex( int dps, __DTString str, DateTimeToken dtok, DateTimeRawInfo raw, DateTimeResult result, ref DateTimeFormatInfo dtfi) { int sep; dtok.dtt = DTT_Unk; // Assume the token is unkown. // // Skip any white spaces. // if (!str.SkipWhiteSpaceComma()) { // // SkipWhiteSpaceComma() will return true when end of string is reached. // dtok.dtt = DTT_End; return; } char ch = str.GetChar(); if (Char.IsLetter(ch)) { // // This is a letter. // int month, dayOfWeek, era, timeMark; // // Check if this is a beginning of a month name. // And check if this is a day of week name. // if (raw.month == -1 && (month = GetMonthNumber(str, dtfi)) >= 1) { // // This is a month name // switch(sep=GetSeparator(str, raw, dtfi)) { case SEP_End: dtok.dtt = DTT_MonthEnd; break; case SEP_Space: dtok.dtt = DTT_MonthSpace; break; case SEP_Date: dtok.dtt = DTT_MonthDatesep; break; default: //Invalid separator after month name throw new FormatException(Environment.GetResourceString("Format_BadDateTime")); } raw.month = month; } else if (raw.dayOfWeek == -1 && (dayOfWeek = GetDayOfWeekNumber(str, dtfi)) >= 0) { // // This is a day of week name. // raw.dayOfWeek = dayOfWeek; dtok.dtt = DTT_DayOfWeek; // // Discard the separator. // GetSeparator(str, raw, dtfi); } else if (GetTimeZoneName(str)) { // // This is a timezone designator // // NOTENOTE : for now, we only support "GMT" and "Z" (for Zulu time). // dtok.dtt = DTT_TimeZone; result.timeZoneUsed = true; result.timeZoneOffset = new TimeSpan(0); } else if ((raw.era == -1) && ((era = GetEra(str, result, ref dtfi)) != -1)) { raw.era = era; dtok.dtt = DTT_Era; } else if (raw.timeMark == -1 && (timeMark = GetTimeMark(str, dtfi)) != -1) { raw.timeMark = timeMark; GetSeparator(str, raw, dtfi); } else { // // Not a month name, not a day of week name. Check if this is one of the // known date words. This is used to deal case like Spanish cultures, which // uses 'de' in their Date string. // // if (!str.MatchWords(dtfi.DateWords)) { throw new FormatException( String.Format(Environment.GetResourceString("Format_UnknowDateTimeWord"), str.Index)); } GetSeparator(str, raw, dtfi); } } else if (Char.IsDigit(ch)) { if (raw.numCount == 3) { throw new FormatException(Environment.GetResourceString("Format_BadDateTime")); } // // This is a digit. // int number = ch - '0'; int digitCount = 1; // // Collect other digits. // while (str.GetNextDigit()) { number = number * 10 + str.GetDigit(); digitCount++; } // If the previous parsing state is DS_T_NNt (like 12:01), and we got another number, // so we will have a terminal state DS_TX_NNN (like 12:01:02). // If the previous parsing state is DS_T_Nt (like 12:), and we got another number, // so we will have a terminal state DS_TX_NN (like 12:01:02). // // Look ahead to see if the following character is a decimal point or timezone offset. // This enables us to parse time in the forms of: // "11:22:33.1234" or "11:22:33-08". if (dps == DS_T_NNt || dps == DS_T_Nt) { char nextCh; if ((str.Index < str.len - 1)) { nextCh = str.Value[str.Index]; switch (nextCh) { case '.': if (dps == DS_T_NNt) { // Yes, advance to the next character. str.Index++; // Collect the second fraction. raw.fraction = ParseFraction(str); } break; case '+': case '-': if (result.timeZoneUsed) { // Should not have two timezone offsets. throw new FormatException(Environment.GetResourceString("Format_BadDateTime")); } result.timeZoneUsed = true; result.timeZoneOffset = ParseTimeZone(str, nextCh); break; } } } if (number >= 0) { dtok.num = number; if (digitCount >= 3) { if (raw.year == -1) { raw.year = number; // // If we have number which has 3 or more digits (like "001" or "0001"), // we assume this number is a year. Save the currnet raw.numCount in // raw.year. // switch (sep = GetSeparator(str, raw, dtfi)) { case SEP_End: dtok.dtt = DTT_YearEnd; break; case SEP_Am: case SEP_Pm: case SEP_Space: dtok.dtt = DTT_YearSpace; break; case SEP_Date: dtok.dtt = DTT_YearDateSep; break; case SEP_YearSuff: case SEP_MonthSuff: case SEP_DaySuff: dtok.dtt = DTT_NumDatesuff; dtok.suffix = sep; break; case SEP_HourSuff: case SEP_MinuteSuff: case SEP_SecondSuff: dtok.dtt = DTT_NumTimesuff; dtok.suffix = sep; break; default: // Invalid separator after number number. throw new FormatException(Environment.GetResourceString("Format_BadDateTime")); } // // Found the token already. Let's bail. // return; } throw new FormatException(Environment.GetResourceString("Format_BadDateTime")); } } else { // // number is overflowed. // throw new FormatException(Environment.GetResourceString("Format_BadDateTime")); } switch (sep = GetSeparator(str, raw, dtfi)) { // // Note here we check if the numCount is less than three. // When we have more than three numbers, it will be caught as error in the state machine. // case SEP_End: dtok.dtt = DTT_NumEnd; raw.num[raw.numCount++] = dtok.num; break; case SEP_Am: case SEP_Pm: dtok.dtt = DTT_NumAmpm; raw.num[raw.numCount++] = dtok.num; break; case SEP_Space: dtok.dtt = DTT_NumSpace; raw.num[raw.numCount++] = dtok.num; break; case SEP_Date: dtok.dtt = DTT_NumDatesep; raw.num[raw.numCount++] = dtok.num; break; case SEP_Time: if (!result.timeZoneUsed) { dtok.dtt = DTT_NumTimesep; raw.num[raw.numCount++] = dtok.num; } else { // If we already got timezone, there should be no // time separator again. throw new FormatException(Environment.GetResourceString("Format_BadDateTime")); } break; case SEP_YearSuff: dtok.num = dtfi.Calendar.ToFourDigitYear(number); dtok.dtt = DTT_NumDatesuff; dtok.suffix = sep; break; case SEP_MonthSuff: case SEP_DaySuff: dtok.dtt = DTT_NumDatesuff; dtok.suffix = sep; break; case SEP_HourSuff: case SEP_MinuteSuff: case SEP_SecondSuff: dtok.dtt = DTT_NumTimesuff; dtok.suffix = sep; break; case SEP_LocalTimeMark: dtok.dtt = DTT_NumLocalTimeMark; raw.num[raw.numCount++] = dtok.num; break; default: // Invalid separator after number number. throw new FormatException(Environment.GetResourceString("Format_BadDateTime")); } } else { // // Not a letter, not a digit. Just ignore it. // str.Index++; } return; }
// // Starting at str.Index, check the type of the separator. // private static int GetSeparator(__DTString str, DateTimeRawInfo raw, DateTimeFormatInfo dtfi) { int separator = SEP_Space; // Assume the separator is a space. And try to find a better one. // // Check if we found any white spaces. // if (!str.SkipWhiteSpaceComma()) { // // SkipWhiteSpaceComma() will return true when end of string is reached. // // // Return the separator as SEP_End. // return (SEP_End); } if (Char.IsLetter(str.GetChar())) { // // This is a beginning of a word. // if (raw.timeMark == -1) { // // Check if this is an AM time mark. // int timeMark; if ((timeMark = GetTimeMark(str, dtfi)) != -1) { raw.timeMark = timeMark;; return (timeMark == TM_AM ? SEP_Am: SEP_Pm); } } if (MatchWord(str, LocalTimeMark, false)) { separator = SEP_LocalTimeMark; } else if (MatchWord(str, CJKYearSuff, false) || MatchWord(str, KoreanYearSuff, false)) { separator = SEP_YearSuff; } else if (MatchWord(str, CJKMonthSuff, false) || MatchWord(str, KoreanMonthSuff, false)) { separator = SEP_MonthSuff; } else if (MatchWord(str, CJKDaySuff, false) || MatchWord(str, KoreanDaySuff, false)) { separator = SEP_DaySuff; } else if (MatchWord(str, CJKHourSuff, false) || MatchWord(str, ChineseHourSuff, false)) { separator = SEP_HourSuff; } else if (MatchWord(str, CJKMinuteSuff, false)) { separator = SEP_MinuteSuff; } else if (MatchWord(str, CJKSecondSuff, false)) { separator = SEP_SecondSuff; } } else { // // Not a letter. Check if this is a date separator. // if ((MatchWord(str, dtfi.DateSeparator, false)) || (MatchWord(str, invariantInfo.DateSeparator, false)) || (MatchWord(str, alternativeDateSeparator, false))) { // // NOTENOTE : alternativeDateSeparator is a special case because some cultures // (e.g. the invariant culture) use "/". However, in RFC format, we use "-" as the // date separator. Therefore, we should check for it. // separator = SEP_Date; } // // Check if this is a time separator. // else if ((MatchWord(str, dtfi.TimeSeparator, false)) || (MatchWord(str, invariantInfo.TimeSeparator, false))) { separator = SEP_Time; } else if (dtfi.CultureID == 0x041c) { // Special case for sq-AL (0x041c) // Its time pattern is "h:mm:ss.tt" if (str.GetChar() == '.') { if (raw.timeMark == -1) { // // Check if this is an AM time mark. // int timeMark; str.Index++; if ((timeMark = GetTimeMark(str, dtfi)) != -1) { raw.timeMark = timeMark;; return (timeMark == TM_AM ? SEP_Am: SEP_Pm); } str.Index--; } } } } return (separator); }
// Given a specified format character, parse and update the parsing result. // private static bool ParseByFormat( __DTString str, __DTString format, ParsingInfo parseInfo, DateTimeFormatInfo dtfi, bool isThrowExp, DateTimeResult result) { int tokenLen = 0; int tempYear = 0, tempMonth = 0, tempDay = 0, tempDayOfWeek = 0, tempHour = 0, tempMinute = 0, tempSecond = 0; double tempFraction = 0; int tempTimeMark = 0; char ch = format.GetChar(); switch (ch) { case 'y': tokenLen = format.GetRepeatCount(); if (tokenLen <= 2) { parseInfo.fUseTwoDigitYear = true; } if (!ParseDigits(str, tokenLen, isThrowExp, out tempYear)) { return (false); } if (!CheckNewValue(ref result.Year, tempYear, ch, isThrowExp)) { return (false); } break; case 'M': tokenLen = format.GetRepeatCount(); if (tokenLen <= 2) { if (!ParseDigits(str, tokenLen, isThrowExp, out tempMonth)) { return (false); } } else { if (tokenLen == 3) { if (!MatchAbbreviatedMonthName(str, dtfi, isThrowExp, ref tempMonth)) { return (false); } } else { if (!MatchMonthName(str, dtfi, isThrowExp, ref tempMonth)) { return (false); } } } if (!CheckNewValue(ref result.Month, tempMonth, ch, isThrowExp)) { return (false); } break; case 'd': // Day & Day of week tokenLen = format.GetRepeatCount(); if (tokenLen <= 2) { // "d" & "dd" if (!ParseDigits(str, tokenLen, isThrowExp, out tempDay)) { return (false); } if (!CheckNewValue(ref result.Day, tempDay, ch, isThrowExp)) { return (false); } } else { if (tokenLen == 3) { // "ddd" if (!MatchAbbreviatedDayName(str, dtfi, isThrowExp, ref tempDayOfWeek)) { return (false); } } else { // "dddd*" if (!MatchDayName(str, dtfi, isThrowExp, ref tempDayOfWeek)) { return (false); } } if (!CheckNewValue(ref parseInfo.dayOfWeek, tempDayOfWeek, ch, isThrowExp)) { return (false); } } break; case 'g': tokenLen = format.GetRepeatCount(); // Put the era value in result.era. if (!MatchEraName(str, dtfi, isThrowExp, ref result.era)) { return (false); } break; case 'h': parseInfo.fUseHour12 = true; tokenLen = format.GetRepeatCount(); if (!ParseDigits(str, (tokenLen < 2? 1 : 2), isThrowExp, out tempHour)) { return (false); } if (!CheckNewValue(ref result.Hour, tempHour, ch, isThrowExp)) { return (false); } break; case 'H': tokenLen = format.GetRepeatCount(); if (!ParseDigits(str, (tokenLen < 2? 1 : 2), isThrowExp, out tempHour)) { return (false); } if (!CheckNewValue(ref result.Hour, tempHour, ch, isThrowExp)) { return (false); } break; case 'm': tokenLen = format.GetRepeatCount(); if (!ParseDigits(str, (tokenLen < 2? 1 : 2), isThrowExp, out tempMinute)) { return (false); } if (!CheckNewValue(ref result.Minute, tempMinute, ch, isThrowExp)) { return (false); } break; case 's': tokenLen = format.GetRepeatCount(); if (!ParseDigits(str, (tokenLen < 2? 1 : 2), isThrowExp, out tempSecond)) { return (false); } if (!CheckNewValue(ref result.Second, tempSecond, ch, isThrowExp)) { return (false); } break; case 'f': tokenLen = format.GetRepeatCount(); if (tokenLen <= DateTimeFormat.MaxSecondsFractionDigits) { if (!ParseFractionExact(str, tokenLen, isThrowExp, ref tempFraction)) { return (false); } if (result.fraction < 0) { result.fraction = tempFraction; } else { if (tempFraction != result.fraction) { if (isThrowExp) { throw new ArgumentException( String.Format(Environment.GetResourceString("Format_RepeatDateTimePattern"), ch), "str"); } else { return (false); } } } } else { return ParseFormatError(isThrowExp, "Format_BadDateTime"); } break; case 't': // AM/PM designator tokenLen = format.GetRepeatCount(); if (tokenLen == 1) { if (!MatchAbbreviatedTimeMark(str, dtfi, isThrowExp, ref tempTimeMark)) { return (false); } } else { if (!MatchTimeMark(str, dtfi, isThrowExp, ref tempTimeMark)) { return (false); } } if (!CheckNewValue(ref parseInfo.timeMark, tempTimeMark, ch, isThrowExp)) { return (false); } break; case 'z': // timezone offset if (parseInfo.fUseTimeZone) { throw new ArgumentException(Environment.GetResourceString("Argument_TwoTimeZoneSpecifiers"), "str"); } parseInfo.fUseTimeZone = true; tokenLen = format.GetRepeatCount(); if (!ParseTimeZoneOffset(str, tokenLen, isThrowExp, ref parseInfo.timeZoneOffset)) { return (false); } break; case 'Z': if (parseInfo.fUseTimeZone) { throw new ArgumentException(Environment.GetResourceString("Argument_TwoTimeZoneSpecifiers"), "str"); } parseInfo.fUseTimeZone = true; parseInfo.timeZoneOffset = new TimeSpan(0); str.Index++; if (!GetTimeZoneName(str)) { BCLDebug.Trace("NLS", "DateTimeParse.DoStrictParse(): 'Z' or 'GMT' are expected"); return (ParseFormatError(isThrowExp, "Format_BadDateTime")); } break; case ':': if (!str.Match(dtfi.TimeSeparator)) { // A time separator is expected. BCLDebug.Trace("NLS", "DateTimeParse.DoStrictParse(): ':' is expected"); return (ParseFormatError(isThrowExp, "Format_BadDateTime")); } break; case '/': if (!str.Match(dtfi.DateSeparator)) { // A date separator is expected. BCLDebug.Trace("NLS", "DateTimeParse.DoStrictParse(): date separator is expected"); return (ParseFormatError(isThrowExp, "Format_BadDateTime")); } break; case '\"': case '\'': StringBuilder enquotedString = new StringBuilder(); try { // Use ParseQuoteString so that we can handle escape characters within the quoted string. tokenLen = DateTimeFormat.ParseQuoteString(format.Value, format.Index, enquotedString); } catch (Exception) { if (isThrowExp) { throw new FormatException(String.Format(Environment.GetResourceString("Format_BadQuote"), ch)); } else { return (false); } } format.Index += tokenLen - 1; // Some cultures uses space in the quoted string. E.g. Spanish has long date format as: // "dddd, dd' de 'MMMM' de 'yyyy". When inner spaces flag is set, we should skip whitespaces if there is space // in the quoted string. String quotedStr = enquotedString.ToString(); for (int i = 0; i < quotedStr.Length; i++) { if (quotedStr[i] == ' ' && parseInfo.fAllowInnerWhite) { str.SkipWhiteSpaces(); } else if (!str.Match(quotedStr[i])) { // Can not find the matching quoted string. BCLDebug.Trace("NLS", "DateTimeParse.DoStrictParse():Quote string doesn't match"); return (ParseFormatError(isThrowExp, "Format_BadDateTime")); } } break; case '%': // Skip this so we can get to the next pattern character. // Used in case like "%d", "%y" // Make sure the next character is not a '%' again. if (format.Index >= format.Value.Length - 1 || format.Value[format.Index + 1] == '%') { BCLDebug.Trace("NLS", "DateTimeParse.DoStrictParse():%% is not permitted"); return (ParseFormatError(isThrowExp, "Format_BadFormatSpecifier")); } break; case '\\': // Escape character. For example, "\d". // Get the next character in format, and see if we can // find a match in str. if (format.GetNext()) { if (!str.Match(format.GetChar())) { // Can not find a match for the escaped character. BCLDebug.Trace("NLS", "DateTimeParse.DoStrictParse(): Can not find a match for the escaped character"); return (ParseFormatError(isThrowExp, "Format_BadDateTime")); } } else { BCLDebug.Trace("NLS", "DateTimeParse.DoStrictParse(): \\ is at the end of the format string"); return (ParseFormatError(isThrowExp, "Format_BadFormatSpecifier")); } break; default: if (ch == ' ') { if (parseInfo.fAllowInnerWhite) { // Skip whitespaces if AllowInnerWhite. // Do nothing here. } else { if (!str.Match(ch)) { // If the space does not match, and trailing space is allowed, we do // one more step to see if the next format character can lead to // successful parsing. // This is used to deal with special case that a empty string can match // a specific pattern. // The example here is af-ZA, which has a time format like "hh:mm:ss tt". However, // its AM symbol is "" (empty string). If fAllowTrailingWhite is used, and time is in // the AM, we will trim the whitespaces at the end, which will lead to a failure // when we are trying to match the space before "tt". if (parseInfo.fAllowTrailingWhite) { if (format.GetNext()) { if (ParseByFormat(str, format, parseInfo, dtfi, isThrowExp, result)) { return (true); } } } return (ParseFormatError(isThrowExp, "Format_BadDateTime")); } // Found a macth. } } else { if (format.MatchSpecifiedWord(GMTName)) { format.Index += (GMTName.Length - 1); // Found GMT string in format. This means the DateTime string // is in GMT timezone. parseInfo.fUseTimeZone = true; if (!str.Match(GMTName)) { BCLDebug.Trace("NLS", "DateTimeParse.DoStrictParse(): GMT in format, but not in str"); return (ParseFormatError(isThrowExp, "Format_BadDateTime")); } } else if (!str.Match(ch)) { // ch is expected. BCLDebug.Trace ("NLS", "DateTimeParse.DoStrictParse(): '", ch, "' is expected"); return (ParseFormatError(isThrowExp, "Format_BadDateTime")); } } break; } // switch return (true); }
/*=================================MatchAbbreviatedTimeMark================================== **Action: Parse the abbreviated time mark (AM/PM) from string starting at str.Index. **Returns: TM_AM or TM_PM. **Arguments: str: a __DTString. The parsing will start from the ** next character after str.Index. **Exceptions: FormatException if a abbreviated time mark can not be found. ==============================================================================*/ private static bool MatchAbbreviatedTimeMark(__DTString str, DateTimeFormatInfo dtfi, bool isThrowExp, ref int result) { // NOTENOTE : the assumption here is that abbreviated time mark is the first // character of the AM/PM designator. If this invariant changes, we have to // change the code below. if (str.GetNext()) { if (str.GetChar() == dtfi.AMDesignator[0]) { result = TM_AM; return (true); } if (str.GetChar() == dtfi.PMDesignator[0]) { result = TM_PM; return (true); } } return (ParseFormatError(isThrowExp, "Format_BadDateTime")); }
internal static bool MatchHebrewDigits(ref __DTString str, int digitLen, out int number) { number = 0; HebrewNumberParsingContext hebrewNumberParsingContext = new HebrewNumberParsingContext(0); HebrewNumberParsingState hebrewNumberParsingState = HebrewNumberParsingState.ContinueParsing; while (hebrewNumberParsingState == HebrewNumberParsingState.ContinueParsing && str.GetNext()) { hebrewNumberParsingState = HebrewNumber.ParseByChar(str.GetChar(), ref hebrewNumberParsingContext); } if (hebrewNumberParsingState == HebrewNumberParsingState.FoundEndOfHebrewNumber) { number = hebrewNumberParsingContext.result; return true; } return false; }
private static bool ParseSign(ref __DTString str, ref bool result) { if (str.GetNext()) { switch (str.GetChar()) { case '+': result = true; return true; case '-': result = false; return true; } } return false; }
private static bool ParseSign(ref __DTString str, ref bool result) { if (!str.GetNext()) { return false; } char @char = str.GetChar(); if (@char == '+') { result = true; return true; } if (@char == '-') { result = false; return true; } return false; }
// // Parse the ISO8601 format string found during Parse(); // // private static bool ParseISO8601(ref DateTimeRawInfo raw, ref __DTString str, DateTimeStyles styles, ref DateTimeResult result) { if (raw.year < 0 || raw.GetNumber(0) < 0 || raw.GetNumber(1) < 0) { } str.Index--; int hour, minute; int second = 0; double partSecond = 0; str.SkipWhiteSpaces(); if (!ParseDigits(ref str, 2, out hour)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } str.SkipWhiteSpaces(); if (!str.Match(':')) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } str.SkipWhiteSpaces(); if (!ParseDigits(ref str, 2, out minute)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } str.SkipWhiteSpaces(); if (str.Match(':')) { str.SkipWhiteSpaces(); if (!ParseDigits(ref str, 2, out second)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if (str.Match('.')) { if (!ParseFraction(ref str, out partSecond)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } str.Index--; } str.SkipWhiteSpaces(); } if (str.GetNext()) { char ch = str.GetChar(); if (ch == '+' || ch == '-') { result.flags |= ParseFlags.TimeZoneUsed; if (!ParseTimeZone(ref str, ref result.timeZoneOffset)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } } else if (ch == 'Z' || ch == 'z') { result.flags |= ParseFlags.TimeZoneUsed; result.timeZoneOffset = TimeSpan.Zero; result.flags |= ParseFlags.TimeZoneUtc; } else { str.Index--; } str.SkipWhiteSpaces(); if (str.Match('#')) { if (!VerifyValidPunctuation(ref str)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } str.SkipWhiteSpaces(); } if (str.Match('\0')) { if (!VerifyValidPunctuation(ref str)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } } if (str.GetNext()) { // If this is true, there were non-white space characters remaining in the DateTime result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } } DateTime time; Calendar calendar = GregorianCalendar.GetDefaultInstance(); if (!calendar.TryToDateTime(raw.year, raw.GetNumber(0), raw.GetNumber(1), hour, minute, second, 0, result.era, out time)) { result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null); return false; } time = time.AddTicks((long)Math.Round(partSecond * Calendar.TicksPerSecond)); result.parsedDate = time; if (!DetermineTimeZoneAdjustments(ref result, styles, false)) { return false; } return true; }
private static bool ParseByFormat(ref __DTString str, ref __DTString format, ref ParsingInfo parseInfo, DateTimeFormatInfo dtfi, ref DateTimeResult result) { int num = 0; int newValue = 0; int newValue2 = 0; int newValue3 = 0; int newValue4 = 0; int newValue5 = 0; int newValue6 = 0; int newValue7 = 0; double num2 = 0.0; DateTimeParse.TM tM = DateTimeParse.TM.AM; char @char = format.GetChar(); char c = @char; if (c <= 'H') { if (c <= '\'') { if (c != '"') { switch (c) { case '%': { if (format.Index >= format.Value.Length - 1 || format.Value[format.Index + 1] == '%') { result.SetFailure(ParseFailureKind.Format, "Format_BadFormatSpecifier", null); return false; } return true; } case '&': { goto IL_991; } case '\'': { break; } default: { goto IL_991; } } } StringBuilder stringBuilder = new StringBuilder(); if (!DateTimeParse.TryParseQuoteString(format.Value, format.Index, stringBuilder, out num)) { result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadQuote", @char); return false; } format.Index += num - 1; string text = stringBuilder.ToString(); for (int i = 0; i < text.Length; i++) { if (text[i] == ' ' && parseInfo.fAllowInnerWhite) { str.SkipWhiteSpaces(); } else { if (!str.Match(text[i])) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } } } if ((result.flags & ParseFlags.CaptureOffset) == (ParseFlags)0) { return true; } if ((result.flags & ParseFlags.Rfc1123Pattern) != (ParseFlags)0 && text == "GMT") { result.flags |= ParseFlags.TimeZoneUsed; result.timeZoneOffset = TimeSpan.Zero; return true; } if ((result.flags & ParseFlags.UtcSortPattern) != (ParseFlags)0 && text == "Z") { result.flags |= ParseFlags.TimeZoneUsed; result.timeZoneOffset = TimeSpan.Zero; return true; } return true; } else { switch (c) { case '.': { if (str.Match(@char)) { return true; } if (format.GetNext() && format.Match('F')) { format.GetRepeatCount(); return true; } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } case '/': { if (!str.Match(dtfi.DateSeparator)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } return true; } default: { if (c != ':') { switch (c) { case 'F': { break; } case 'G': { goto IL_991; } case 'H': { num = format.GetRepeatCount(); if (!DateTimeParse.ParseDigits(ref str, (num < 2) ? 1 : 2, out newValue5)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if (!DateTimeParse.CheckNewValue(ref result.Hour, newValue5, @char, ref result)) { return false; } return true; } default: { goto IL_991; } } } else { if (!str.Match(dtfi.TimeSeparator)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } return true; } break; } } } } else { if (c <= 'h') { switch (c) { case 'K': { if (str.Match('Z')) { if ((result.flags & ParseFlags.TimeZoneUsed) != (ParseFlags)0 && result.timeZoneOffset != TimeSpan.Zero) { result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_RepeatDateTimePattern", 'K'); return false; } result.flags |= ParseFlags.TimeZoneUsed; result.timeZoneOffset = new TimeSpan(0L); result.flags |= ParseFlags.TimeZoneUtc; return true; } else { if (!str.Match('+') && !str.Match('-')) { return true; } str.Index--; TimeSpan timeSpan = new TimeSpan(0L); if (!DateTimeParse.ParseTimeZoneOffset(ref str, 3, ref timeSpan)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if ((result.flags & ParseFlags.TimeZoneUsed) != (ParseFlags)0 && timeSpan != result.timeZoneOffset) { result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_RepeatDateTimePattern", 'K'); return false; } result.timeZoneOffset = timeSpan; result.flags |= ParseFlags.TimeZoneUsed; return true; } break; } case 'L': { goto IL_991; } case 'M': { num = format.GetRepeatCount(); if (num <= 2) { if (!DateTimeParse.ParseDigits(ref str, num, out newValue2) && (!parseInfo.fCustomNumberParser || !parseInfo.parseNumberDelegate(ref str, num, out newValue2))) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } } else { if (num == 3) { if (!DateTimeParse.MatchAbbreviatedMonthName(ref str, dtfi, ref newValue2)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } } else { if (!DateTimeParse.MatchMonthName(ref str, dtfi, ref newValue2)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } } result.flags |= ParseFlags.ParsedMonthName; } if (!DateTimeParse.CheckNewValue(ref result.Month, newValue2, @char, ref result)) { return false; } return true; } default: { switch (c) { case 'Z': { if ((result.flags & ParseFlags.TimeZoneUsed) != (ParseFlags)0 && result.timeZoneOffset != TimeSpan.Zero) { result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_RepeatDateTimePattern", 'Z'); return false; } result.flags |= ParseFlags.TimeZoneUsed; result.timeZoneOffset = new TimeSpan(0L); result.flags |= ParseFlags.TimeZoneUtc; str.Index++; if (!DateTimeParse.GetTimeZoneName(ref str)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } str.Index--; return true; } case '[': { goto IL_991; } case '\\': { if (!format.GetNext()) { result.SetFailure(ParseFailureKind.Format, "Format_BadFormatSpecifier", null); return false; } if (!str.Match(format.GetChar())) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } return true; } default: { switch (c) { case 'd': { num = format.GetRepeatCount(); if (num <= 2) { if (!DateTimeParse.ParseDigits(ref str, num, out newValue3) && (!parseInfo.fCustomNumberParser || !parseInfo.parseNumberDelegate(ref str, num, out newValue3))) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if (!DateTimeParse.CheckNewValue(ref result.Day, newValue3, @char, ref result)) { return false; } return true; } else { if (num == 3) { if (!DateTimeParse.MatchAbbreviatedDayName(ref str, dtfi, ref newValue4)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } } else { if (!DateTimeParse.MatchDayName(ref str, dtfi, ref newValue4)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } } if (!DateTimeParse.CheckNewValue(ref parseInfo.dayOfWeek, newValue4, @char, ref result)) { return false; } return true; } break; } case 'e': { goto IL_991; } case 'f': { break; } case 'g': { num = format.GetRepeatCount(); if (!DateTimeParse.MatchEraName(ref str, dtfi, ref result.era)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } return true; } case 'h': { parseInfo.fUseHour12 = true; num = format.GetRepeatCount(); if (!DateTimeParse.ParseDigits(ref str, (num < 2) ? 1 : 2, out newValue5)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if (!DateTimeParse.CheckNewValue(ref result.Hour, newValue5, @char, ref result)) { return false; } return true; } default: { goto IL_991; } } break; } } break; } } } else { if (c != 'm') { switch (c) { case 's': { num = format.GetRepeatCount(); if (!DateTimeParse.ParseDigits(ref str, (num < 2) ? 1 : 2, out newValue7)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if (!DateTimeParse.CheckNewValue(ref result.Second, newValue7, @char, ref result)) { return false; } return true; } case 't': { num = format.GetRepeatCount(); if (num == 1) { if (!DateTimeParse.MatchAbbreviatedTimeMark(ref str, dtfi, ref tM)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } } else { if (!DateTimeParse.MatchTimeMark(ref str, dtfi, ref tM)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } } if (parseInfo.timeMark == DateTimeParse.TM.NotSet) { parseInfo.timeMark = tM; return true; } if (parseInfo.timeMark != tM) { result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_RepeatDateTimePattern", @char); return false; } return true; } default: { switch (c) { case 'y': { num = format.GetRepeatCount(); bool flag; if (dtfi.HasForceTwoDigitYears) { flag = DateTimeParse.ParseDigits(ref str, 1, 4, out newValue); } else { if (num <= 2) { parseInfo.fUseTwoDigitYear = true; } flag = DateTimeParse.ParseDigits(ref str, num, out newValue); } if (!flag && parseInfo.fCustomNumberParser) { flag = parseInfo.parseNumberDelegate(ref str, num, out newValue); } if (!flag) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if (!DateTimeParse.CheckNewValue(ref result.Year, newValue, @char, ref result)) { return false; } return true; } case 'z': { num = format.GetRepeatCount(); TimeSpan timeSpan2 = new TimeSpan(0L); if (!DateTimeParse.ParseTimeZoneOffset(ref str, num, ref timeSpan2)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if ((result.flags & ParseFlags.TimeZoneUsed) != (ParseFlags)0 && timeSpan2 != result.timeZoneOffset) { result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_RepeatDateTimePattern", 'z'); return false; } result.timeZoneOffset = timeSpan2; result.flags |= ParseFlags.TimeZoneUsed; return true; } default: { goto IL_991; } } break; } } } else { num = format.GetRepeatCount(); if (!DateTimeParse.ParseDigits(ref str, (num < 2) ? 1 : 2, out newValue6)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if (!DateTimeParse.CheckNewValue(ref result.Minute, newValue6, @char, ref result)) { return false; } return true; } } } num = format.GetRepeatCount(); if (num > 7) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if (!DateTimeParse.ParseFractionExact(ref str, num, ref num2) && @char == 'f') { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if (result.fraction < 0.0) { result.fraction = num2; return true; } if (num2 != result.fraction) { result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_RepeatDateTimePattern", @char); return false; } return true; IL_991: if (@char == ' ') { if (!parseInfo.fAllowInnerWhite && !str.Match(@char)) { if (parseInfo.fAllowTrailingWhite && format.GetNext() && DateTimeParse.ParseByFormat(ref str, ref format, ref parseInfo, dtfi, ref result)) { return true; } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } } else { if (format.MatchSpecifiedWord("GMT")) { format.Index += "GMT".Length - 1; result.flags |= ParseFlags.TimeZoneUsed; result.timeZoneOffset = TimeSpan.Zero; if (!str.Match("GMT")) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } } else { if (!str.Match(@char)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } } } return true; }
// // Parse the ISO8601 format string found during Parse(); // // private static DateTime ParseISO8601(DateTimeRawInfo raw, __DTString str, DateTimeStyles styles) { if (raw.year < 0 || raw.num[0] < 0 || raw.num[1] < 0) { } str.Index--; int hour, minute, second; bool timeZoneUsed = false; TimeSpan timeZoneOffset = new TimeSpan(); DateTime time = new DateTime(0); double partSecond = 0; str.SkipWhiteSpaces(); ParseDigits(str, 2, true, out hour); str.SkipWhiteSpaces(); if (str.Match(':')) { str.SkipWhiteSpaces(); ParseDigits(str, 2, true, out minute); str.SkipWhiteSpaces(); if (str.Match(':')) { str.SkipWhiteSpaces(); ParseDigits(str, 2, true, out second); str.SkipWhiteSpaces(); if (str.GetNext()) { char ch = str.GetChar(); if (ch == '+' || ch == '-') { timeZoneUsed = true; timeZoneOffset = ParseTimeZone(str, str.GetChar()); } else if (ch == '.') { str.Index++; //ParseFraction requires us to advance to the next character. partSecond = ParseFraction(str); } else if (ch == 'Z' || ch == 'z') { timeZoneUsed = true; } else { throw new FormatException(Environment.GetResourceString("Format_BadDateTime")); } } time =new DateTime(raw.year, raw.num[0], raw.num[1], hour, minute, second); time = time.AddTicks((long)Math.Round(partSecond * Calendar.TicksPerSecond)); if (timeZoneUsed) { time = AdjustTimeZone(time, timeZoneOffset, styles, false); } return time; } } throw new FormatException(Environment.GetResourceString("Format_BadDateTime")); }