/*=================================DoStrictParse================================== **Action: Do DateTime parsing using the format in formatParam. **Returns: The parsed DateTime. **Arguments: **Exceptions: ** **Notes: ** When the following general formats are used, InvariantInfo is used in dtfi: ** 'r', 'R', 's'. ** When the following general formats are used, the time is assumed to be in Universal time. ** **Limitations: ** Only GregarianCalendar is supported for now. ** Only support GMT timezone. ==============================================================================*/ private static bool DoStrictParse( String s, String formatParam, DateTimeStyles styles, DateTimeFormatInfo dtfi, ref DateTimeResult result) { ParsingInfo parseInfo = new ParsingInfo(); parseInfo.Init(); parseInfo.calendar = dtfi.Calendar; parseInfo.fAllowInnerWhite = ((styles & DateTimeStyles.AllowInnerWhite) != 0); parseInfo.fAllowTrailingWhite = ((styles & DateTimeStyles.AllowTrailingWhite) != 0); // We need the original values of the following two below. String originalFormat = formatParam; if (formatParam.Length == 1) { if (((result.flags & ParseFlags.CaptureOffset) != 0) && formatParam[0] == 'U') { // The 'U' format is not allowed for DateTimeOffset result.SetFailure(ParseFailureKind.Format, "Format_BadFormatSpecifier", null); return false; } formatParam = ExpandPredefinedFormat(formatParam, ref dtfi, ref parseInfo, ref result); } bool bTimeOnly = false; result.calendar = parseInfo.calendar; if (parseInfo.calendar.ID == Calendar.CAL_HEBREW) { parseInfo.parseNumberDelegate = m_hebrewNumberParser; parseInfo.fCustomNumberParser = true; } // Reset these values to negative one so that we could throw exception // if we have parsed every item twice. result.Hour = result.Minute = result.Second = -1; __DTString format = new __DTString(formatParam, dtfi, false); __DTString str = new __DTString(s, dtfi, false); if (parseInfo.fAllowTrailingWhite) { // Trim trailing spaces if AllowTrailingWhite. format.TrimTail(); format.RemoveTrailingInQuoteSpaces(); str.TrimTail(); } if ((styles & DateTimeStyles.AllowLeadingWhite) != 0) { format.SkipWhiteSpaces(); format.RemoveLeadingInQuoteSpaces(); str.SkipWhiteSpaces(); } // // Scan every character in format and match the pattern in str. // while (format.GetNext()) { // We trim inner spaces here, so that we will not eat trailing spaces when // AllowTrailingWhite is not used. if (parseInfo.fAllowInnerWhite) { str.SkipWhiteSpaces(); } if (!ParseByFormat(ref str, ref format, ref parseInfo, dtfi, ref result)) { return (false); } } if (str.Index < str.Value.Length - 1) { // There are still remaining character in str. result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if (parseInfo.fUseTwoDigitYear && ((dtfi.FormatFlags & DateTimeFormatFlags.UseHebrewRule) == 0)) { // A two digit year value is expected. Check if the parsed year value is valid. if (result.Year >= 100) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } try { result.Year = parseInfo.calendar.ToFourDigitYear(result.Year); } catch (ArgumentOutOfRangeException e) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", e); return false; } } if (parseInfo.fUseHour12) { if (parseInfo.timeMark == TM.NotSet) { // hh is used, but no AM/PM designator is specified. // Assume the time is AM. // Don't throw exceptions in here becasue it is very confusing for the caller. // I always got confused myself when I use "hh:mm:ss" to parse a time string, // and ParseExact() throws on me (because I didn't use the 24-hour clock 'HH'). parseInfo.timeMark = TM.AM; } if (result.Hour > 12) { // AM/PM is used, but the value for HH is too big. result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if (parseInfo.timeMark == TM.AM) { if (result.Hour == 12) { result.Hour = 0; } } else { result.Hour = (result.Hour == 12) ? 12 : result.Hour + 12; } } else { // Military (24-hour time) mode // // AM cannot be set with a 24-hour time like 17:15. // PM cannot be set with a 24-hour time like 03:15. if ( (parseInfo.timeMark == TM.AM && result.Hour >= 12) ||(parseInfo.timeMark == TM.PM && result.Hour < 12)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } } // Check if the parased string only contains hour/minute/second values. bTimeOnly = (result.Year == -1 && result.Month == -1 && result.Day == -1); if (!CheckDefaultDateTime(ref result, ref parseInfo.calendar, styles)) { return false; } if (!bTimeOnly && dtfi.HasYearMonthAdjustment) { if (!dtfi.YearMonthAdjustment(ref result.Year, ref result.Month, ((result.flags & ParseFlags.ParsedMonthName) != 0))) { result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null); return false; } } if (!parseInfo.calendar.TryToDateTime(result.Year, result.Month, result.Day, result.Hour, result.Minute, result.Second, 0, result.era, out result.parsedDate)) { result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null); return false; } if (result.fraction > 0) { result.parsedDate = result.parsedDate.AddTicks((long)Math.Round(result.fraction * Calendar.TicksPerSecond)); } // // We have to check day of week before we adjust to the time zone. // It is because the value of day of week may change after adjusting // to the time zone. // if (parseInfo.dayOfWeek != -1) { // // Check if day of week is correct. // if (parseInfo.dayOfWeek != (int)parseInfo.calendar.GetDayOfWeek(result.parsedDate)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDayOfWeek", null); return false; } } if (!DetermineTimeZoneAdjustments(ref result, styles, bTimeOnly)) { return false; } return true; }
private static bool DoStrictParse(string s, string formatParam, DateTimeStyles styles, DateTimeFormatInfo dtfi, ref DateTimeResult result) { bool bTimeOnly = false; ParsingInfo parseInfo = new ParsingInfo(); parseInfo.Init(); parseInfo.calendar = dtfi.Calendar; parseInfo.fAllowInnerWhite = (styles & DateTimeStyles.AllowInnerWhite) != DateTimeStyles.None; parseInfo.fAllowTrailingWhite = (styles & DateTimeStyles.AllowTrailingWhite) != DateTimeStyles.None; if (formatParam.Length == 1) { if (((result.flags & ParseFlags.CaptureOffset) != 0) && (formatParam[0] == 'U')) { result.SetFailure(ParseFailureKind.Format, "Format_BadFormatSpecifier", null); return false; } formatParam = ExpandPredefinedFormat(formatParam, ref dtfi, ref parseInfo, ref result); } result.calendar = parseInfo.calendar; if (parseInfo.calendar.ID == 8) { parseInfo.parseNumberDelegate = m_hebrewNumberParser; parseInfo.fCustomNumberParser = true; } result.Hour = result.Minute = result.Second = -1; __DTString format = new __DTString(formatParam, dtfi, false); __DTString str = new __DTString(s, dtfi, false); if (parseInfo.fAllowTrailingWhite) { format.TrimTail(); format.RemoveTrailingInQuoteSpaces(); str.TrimTail(); } if ((styles & DateTimeStyles.AllowLeadingWhite) != DateTimeStyles.None) { format.SkipWhiteSpaces(); format.RemoveLeadingInQuoteSpaces(); str.SkipWhiteSpaces(); } while (format.GetNext()) { if (parseInfo.fAllowInnerWhite) { str.SkipWhiteSpaces(); } if (!ParseByFormat(ref str, ref format, ref parseInfo, dtfi, ref result)) { return false; } } if (str.Index < (str.Value.Length - 1)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if (parseInfo.fUseTwoDigitYear && ((dtfi.FormatFlags & DateTimeFormatFlags.UseHebrewRule) == DateTimeFormatFlags.None)) { if (result.Year >= 100) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } result.Year = parseInfo.calendar.ToFourDigitYear(result.Year); } if (parseInfo.fUseHour12) { if (parseInfo.timeMark == TM.NotSet) { parseInfo.timeMark = TM.AM; } if (result.Hour > 12) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if (parseInfo.timeMark == TM.AM) { if (result.Hour == 12) { result.Hour = 0; } } else { result.Hour = (result.Hour == 12) ? 12 : (result.Hour + 12); } } bTimeOnly = ((result.Year == -1) && (result.Month == -1)) && (result.Day == -1); if (!CheckDefaultDateTime(ref result, ref parseInfo.calendar, styles)) { return false; } if ((!bTimeOnly && dtfi.HasYearMonthAdjustment) && !dtfi.YearMonthAdjustment(ref result.Year, ref result.Month, (result.flags & ParseFlags.ParsedMonthName) != 0)) { result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null); return false; } if (!parseInfo.calendar.TryToDateTime(result.Year, result.Month, result.Day, result.Hour, result.Minute, result.Second, 0, result.era, out result.parsedDate)) { result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null); return false; } if (result.fraction > 0.0) { result.parsedDate = result.parsedDate.AddTicks((long) Math.Round((double) (result.fraction * 10000000.0))); } if ((parseInfo.dayOfWeek != -1) && (parseInfo.dayOfWeek != parseInfo.calendar.GetDayOfWeek(result.parsedDate))) { result.SetFailure(ParseFailureKind.Format, "Format_BadDayOfWeek", null); return false; } if (!DetermineTimeZoneAdjustments(ref result, styles, bTimeOnly)) { return false; } return true; }