private static Boolean GetDayOfNNY(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi) { if ((result.flags & ParseFlags.HaveDate) != 0) { // Multiple dates in the input string result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } int n1 = raw.GetNumber(0); int n2 = raw.GetNumber(1); int order; if (!GetYearMonthDayOrder(dtfi.ShortDatePattern, dtfi, out order)) { result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadDatePattern", dtfi.ShortDatePattern); return false; } if (order == ORDER_MDY || order == ORDER_YMD) { if (SetDateYMD(ref result, raw.year, n1, n2)) { result.flags |= ParseFlags.HaveDate; return true; // MD + Year } } else { if (SetDateYMD(ref result, raw.year, n2, n1)) { result.flags |= ParseFlags.HaveDate; return true; // DM + Year } } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; }
internal static bool ProcessHebrewTerminalState(DateTimeParse.DS dps, ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi) { switch (dps) { case DateTimeParse.DS.DX_MN: case DateTimeParse.DS.DX_NM: { DateTimeParse.GetDefaultYear(ref result, ref styles); if (!dtfi.YearMonthAdjustment(ref result.Year, ref raw.month, true)) { result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null); return false; } if (!DateTimeParse.GetHebrewDayOfNM(ref result, ref raw, dtfi)) { return false; } goto IL_160; } case DateTimeParse.DS.DX_MNN: { raw.year = raw.GetNumber(1); if (!dtfi.YearMonthAdjustment(ref raw.year, ref raw.month, true)) { result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null); return false; } if (!DateTimeParse.GetDayOfMNN(ref result, ref raw, dtfi)) { return false; } goto IL_160; } case DateTimeParse.DS.DX_YMN: { if (!dtfi.YearMonthAdjustment(ref raw.year, ref raw.month, true)) { result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null); return false; } if (!DateTimeParse.GetDayOfYMN(ref result, ref raw, dtfi)) { return false; } goto IL_160; } case DateTimeParse.DS.DX_YM: { if (!dtfi.YearMonthAdjustment(ref raw.year, ref raw.month, true)) { result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null); return false; } if (!DateTimeParse.GetDayOfYM(ref result, ref raw, dtfi)) { return false; } goto IL_160; } case DateTimeParse.DS.TX_N: { if (!DateTimeParse.GetTimeOfN(dtfi, ref result, ref raw)) { return false; } goto IL_160; } case DateTimeParse.DS.TX_NN: { if (!DateTimeParse.GetTimeOfNN(dtfi, ref result, ref raw)) { return false; } goto IL_160; } case DateTimeParse.DS.TX_NNN: { if (!DateTimeParse.GetTimeOfNNN(dtfi, ref result, ref raw)) { return false; } goto IL_160; } } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; IL_160: if (dps > DateTimeParse.DS.ERROR) { raw.numCount = 0; } return true; }
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); }
private static bool GetDateOfDSN(ref DateTimeResult result, ref DateTimeRawInfo raw) { if (raw.numCount != 1 || result.Day != -1) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } result.Day = raw.GetNumber(0); return true; }
private static bool GetDateOfNNDS(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi) { if ((result.flags & ParseFlags.HaveYear) != (ParseFlags)0) { if ((result.flags & ParseFlags.HaveMonth) == (ParseFlags)0 && (result.flags & ParseFlags.HaveDay) == (ParseFlags)0 && DateTimeParse.SetDateYMD(ref result, result.Year = DateTimeParse.AdjustYear(ref result, raw.year), raw.GetNumber(0), raw.GetNumber(1))) { return true; } } else { if ((result.flags & ParseFlags.HaveMonth) != (ParseFlags)0 && (result.flags & ParseFlags.HaveYear) == (ParseFlags)0 && (result.flags & ParseFlags.HaveDay) == (ParseFlags)0) { int num; if (!DateTimeParse.GetYearMonthDayOrder(dtfi.ShortDatePattern, dtfi, out num)) { result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadDatePattern", dtfi.ShortDatePattern); return false; } if (num == 0) { if (DateTimeParse.SetDateYMD(ref result, DateTimeParse.AdjustYear(ref result, raw.GetNumber(0)), result.Month, raw.GetNumber(1))) { return true; } } else { if (DateTimeParse.SetDateYMD(ref result, DateTimeParse.AdjustYear(ref result, raw.GetNumber(1)), result.Month, raw.GetNumber(0))) { return true; } } } } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; }
private static bool GetDayOfYM(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi) { if ((result.flags & ParseFlags.HaveDate) != (ParseFlags)0) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if (DateTimeParse.SetDateYMD(ref result, raw.year, raw.month, 1)) { result.flags |= ParseFlags.HaveDate; return true; } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; }
private static bool GetTimeOfN(DateTimeFormatInfo dtfi, ref DateTimeResult result, ref DateTimeRawInfo raw) { if ((result.flags & ParseFlags.HaveTime) != (ParseFlags)0) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if (raw.timeMark == DateTimeParse.TM.NotSet) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } result.Hour = raw.GetNumber(0); result.flags |= ParseFlags.HaveTime; return true; }
private static Boolean GetDateOfNNDS(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi) { // For partial CJK Dates, the only valid formats are with a specified year, followed by two numbers, which // will be the Month and Day, and with a specified Month, when the numbers are either the year and day or // day and year, depending on the short date pattern. if ((result.flags & ParseFlags.HaveYear) != 0) { if (((result.flags & ParseFlags.HaveMonth) == 0) && ((result.flags & ParseFlags.HaveDay) == 0)) { if (TryAdjustYear(ref result, raw.year, out result.Year) && SetDateYMD(ref result, result.Year, raw.GetNumber(0), raw.GetNumber(1))) { return true; } } } else if ((result.flags & ParseFlags.HaveMonth) != 0) { if (((result.flags & ParseFlags.HaveYear) == 0) && ((result.flags & ParseFlags.HaveDay) == 0)) { int order; if (!GetYearMonthDayOrder(dtfi.ShortDatePattern, dtfi, out order)) { result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadDatePattern", dtfi.ShortDatePattern); return false; } int year; if (order == ORDER_YMD) { if (TryAdjustYear(ref result, raw.GetNumber(0), out year) && SetDateYMD(ref result, year, result.Month, raw.GetNumber(1))) { return true; } } else { if (TryAdjustYear(ref result, raw.GetNumber(1), out year) && SetDateYMD(ref result, year, result.Month, raw.GetNumber(0))){ return true; } } } } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; }
// // A date suffix is found, use this method to put the number into the result. // private static bool ProcessDateTimeSuffix(ref DateTimeResult result, ref DateTimeRawInfo raw, ref DateTimeToken dtok) { switch (dtok.suffix) { case TokenType.SEP_YearSuff: if ((result.flags & ParseFlags.HaveYear) != 0) { return false; } result.flags |= ParseFlags.HaveYear; result.Year = raw.year = dtok.num; break; case TokenType.SEP_MonthSuff: if ((result.flags & ParseFlags.HaveMonth) != 0) { return false; } result.flags |= ParseFlags.HaveMonth; result.Month= raw.month = dtok.num; break; case TokenType.SEP_DaySuff: if ((result.flags & ParseFlags.HaveDay) != 0) { return false; } result.flags |= ParseFlags.HaveDay; result.Day = dtok.num; break; case TokenType.SEP_HourSuff: if ((result.flags & ParseFlags.HaveHour) != 0) { return false; } result.flags |= ParseFlags.HaveHour; result.Hour = dtok.num; break; case TokenType.SEP_MinuteSuff: if ((result.flags & ParseFlags.HaveMinute) != 0) { return false; } result.flags |= ParseFlags.HaveMinute; result.Minute = dtok.num; break; case TokenType.SEP_SecondSuff: if ((result.flags & ParseFlags.HaveSecond) != 0) { return false; } result.flags |= ParseFlags.HaveSecond; result.Second = dtok.num; break; } return true; }
private static Boolean GetTimeOfNNN(DateTimeFormatInfo dtfi, ref DateTimeResult result, ref DateTimeRawInfo raw) { if ((result.flags & ParseFlags.HaveTime) != 0) { // Multiple times in the input string result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } Contract.Assert(raw.numCount >= 3, "raw.numCount >= 3"); result.Hour = raw.GetNumber(0); result.Minute = raw.GetNumber(1); result.Second = raw.GetNumber(2); result.flags |= ParseFlags.HaveTime; return true; }
private static Boolean GetDateOfNDS(ref DateTimeResult result, ref DateTimeRawInfo raw) { if (result.Month == -1) { //Should have a month suffix result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if (result.Year != -1) { // Aleady has a year suffix result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if (!TryAdjustYear(ref result, raw.GetNumber(0), out result.Year)) { // the year value is out of range result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } result.Day = 1; return true; }
private static Boolean GetTimeOfN(DateTimeFormatInfo dtfi, ref DateTimeResult result, ref DateTimeRawInfo raw) { if ((result.flags & ParseFlags.HaveTime) != 0) { // Multiple times in the input string result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } // // In this case, we need a time mark. Check if so. // if (raw.timeMark == TM.NotSet) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } result.Hour = raw.GetNumber(0); result.flags |= ParseFlags.HaveTime; return true; }
private static void AdjustTimeMark(DateTimeFormatInfo dtfi, ref DateTimeRawInfo raw) { // Specail case for culture which uses AM as empty string. // E.g. af-ZA (0x0436) // S1159 \x0000 // S2359 nm // In this case, if we are parsing a string like "2005/09/14 12:23", we will assume this is in AM. if (raw.timeMark == TM.NotSet) { if (dtfi.AMDesignator != null && dtfi.PMDesignator != null) { if (dtfi.AMDesignator.Length == 0 && dtfi.PMDesignator.Length != 0) { raw.timeMark = TM.AM; } if (dtfi.PMDesignator.Length == 0 && dtfi.AMDesignator.Length != 0) { raw.timeMark = TM.PM; } } } }
private static Boolean GetDayOfYM(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi) { if ((result.flags & ParseFlags.HaveDate) != 0) { // Multiple dates in the input string result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if (SetDateYMD(ref result, raw.year, raw.month, 1)) { result.flags |= ParseFlags.HaveDate; return true; } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; }
private static bool GetDayOfMNN(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi) { if ((result.flags & ParseFlags.HaveDate) != (ParseFlags)0) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } int number = raw.GetNumber(0); int number2 = raw.GetNumber(1); int num; if (!DateTimeParse.GetYearMonthDayOrder(dtfi.ShortDatePattern, dtfi, out num)) { result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadDatePattern", dtfi.ShortDatePattern); return false; } if (num == 1) { int year; if (result.calendar.IsValidDay(year = DateTimeParse.AdjustYear(ref result, number2), raw.month, number, result.era)) { result.SetDate(year, raw.month, number); result.flags |= ParseFlags.HaveDate; return true; } if (result.calendar.IsValidDay(year = DateTimeParse.AdjustYear(ref result, number), raw.month, number2, result.era)) { result.SetDate(year, raw.month, number2); result.flags |= ParseFlags.HaveDate; return true; } } else { if (num == 0) { int year; if (result.calendar.IsValidDay(year = DateTimeParse.AdjustYear(ref result, number), raw.month, number2, result.era)) { result.SetDate(year, raw.month, number2); result.flags |= ParseFlags.HaveDate; return true; } if (result.calendar.IsValidDay(year = DateTimeParse.AdjustYear(ref result, number2), raw.month, number, result.era)) { result.SetDate(year, raw.month, number); result.flags |= ParseFlags.HaveDate; return true; } } else { if (num == 2) { int year; if (result.calendar.IsValidDay(year = DateTimeParse.AdjustYear(ref result, number2), raw.month, number, result.era)) { result.SetDate(year, raw.month, number); result.flags |= ParseFlags.HaveDate; return true; } if (result.calendar.IsValidDay(year = DateTimeParse.AdjustYear(ref result, number), raw.month, number2, result.era)) { result.SetDate(year, raw.month, number2); result.flags |= ParseFlags.HaveDate; return true; } } } } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; }
//////////////////////////////////////////////////////////////////////// // // Actions: // This is used by DateTime.Parse(). // Process the terminal state for the Hebrew calendar parsing. // //////////////////////////////////////////////////////////////////////// internal static Boolean ProcessHebrewTerminalState(DS dps, ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi) { // The following are accepted terminal state for Hebrew date. switch (dps) { case DS.DX_MNN: // Deal with the default long/short date format when the year number is ambigous (i.e. year < 100). raw.year = raw.GetNumber(1); if (!dtfi.YearMonthAdjustment(ref raw.year, ref raw.month, true)) { result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null); return false; } if (!GetDayOfMNN(ref result, ref raw, dtfi)) { return false; } break; case DS.DX_YMN: // Deal with the default long/short date format when the year number is NOT ambigous (i.e. year >= 100). if (!dtfi.YearMonthAdjustment(ref raw.year, ref raw.month, true)) { result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null); return false; } if (!GetDayOfYMN(ref result, ref raw, dtfi)) { return false; } break; case DS.DX_NM: case DS.DX_MN: // Deal with Month/Day pattern. GetDefaultYear(ref result, ref styles); if (!dtfi.YearMonthAdjustment(ref result.Year, ref raw.month, true)) { result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null); return false; } if (!GetHebrewDayOfNM(ref result, ref raw, dtfi)) { return false; } break; case DS.DX_YM: // Deal with Year/Month pattern. if (!dtfi.YearMonthAdjustment(ref raw.year, ref raw.month, true)) { result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null); return false; } if (!GetDayOfYM(ref result, ref raw, dtfi)) { return false; } break; case DS.TX_N: // Deal hour + AM/PM if (!GetTimeOfN(dtfi, ref result, ref raw)) { return false; } break; case DS.TX_NN: if (!GetTimeOfNN(dtfi, ref result, ref raw)) { return false; } break; case DS.TX_NNN: if (!GetTimeOfNNN(dtfi, ref result, ref raw)) { return false; } break; default: result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if (dps > DS.ERROR) { // // We have reached a terminal state. Reset the raw num count. // raw.numCount = 0; } return true; }
private static bool GetDayOfNNY(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi) { if ((result.flags & ParseFlags.HaveDate) != (ParseFlags)0) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } int number = raw.GetNumber(0); int number2 = raw.GetNumber(1); int num; if (!DateTimeParse.GetYearMonthDayOrder(dtfi.ShortDatePattern, dtfi, out num)) { result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadDatePattern", dtfi.ShortDatePattern); return false; } if (num == 1 || num == 0) { if (DateTimeParse.SetDateYMD(ref result, raw.year, number, number2)) { result.flags |= ParseFlags.HaveDate; return true; } } else { if (DateTimeParse.SetDateYMD(ref result, raw.year, number2, number)) { result.flags |= ParseFlags.HaveDate; return true; } } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; }
// // A terminal state has been reached, call the appropriate function to fill in the parsing result. // Return true if the state is a terminal state. // internal static Boolean ProcessTerminaltState(DS dps, ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi) { bool passed = true; switch (dps) { case DS.DX_NN: passed = GetDayOfNN(ref result, ref styles, ref raw, dtfi); break; case DS.DX_NNN: passed = GetDayOfNNN(ref result, ref raw, dtfi); break; case DS.DX_MN: passed = GetDayOfMN(ref result, ref styles, ref raw, dtfi); break; case DS.DX_NM: passed = GetDayOfNM(ref result, ref styles, ref raw, dtfi); break; case DS.DX_MNN: passed = GetDayOfMNN(ref result, ref raw, dtfi); break; case DS.DX_DS: // The result has got the correct value. No need to process. passed = true; break; case DS.DX_YNN: passed = GetDayOfYNN(ref result, ref raw, dtfi); break; case DS.DX_NNY: passed = GetDayOfNNY(ref result, ref raw, dtfi); break; case DS.DX_YMN: passed = GetDayOfYMN(ref result, ref raw, dtfi); break; case DS.DX_YN: passed = GetDayOfYN(ref result, ref raw, dtfi); break; case DS.DX_YM: passed = GetDayOfYM(ref result, ref raw, dtfi); break; case DS.TX_N: passed = GetTimeOfN(dtfi, ref result, ref raw); break; case DS.TX_NN: passed = GetTimeOfNN(dtfi, ref result, ref raw); break; case DS.TX_NNN: passed = GetTimeOfNNN(dtfi, ref result, ref raw); break; case DS.TX_TS: // The result has got the correct value. Nothing to do. passed = true; break; case DS.DX_DSN: passed = GetDateOfDSN(ref result, ref raw); break; case DS.DX_NDS: passed = GetDateOfNDS(ref result, ref raw); break; case DS.DX_NNDS: passed = GetDateOfNNDS(ref result, ref raw, dtfi); break; } PTSTraceExit(dps, passed); if (!passed) { return false; } if (dps > DS.ERROR) { // // We have reached a terminal state. Reset the raw num count. // raw.numCount = 0; } return true; }
private static void AdjustTimeMark(DateTimeFormatInfo dtfi, ref DateTimeRawInfo raw) { if (raw.timeMark == DateTimeParse.TM.NotSet && dtfi.AMDesignator != null && dtfi.PMDesignator != null) { if (dtfi.AMDesignator.Length == 0 && dtfi.PMDesignator.Length != 0) { raw.timeMark = DateTimeParse.TM.AM; } if (dtfi.PMDesignator.Length == 0 && dtfi.AMDesignator.Length != 0) { raw.timeMark = DateTimeParse.TM.PM; } } }
[System.Security.SecuritySafeCritical] // auto-generated internal static bool TryParse(String s, DateTimeFormatInfo dtfi, DateTimeStyles styles, ref DateTimeResult result) { if (s == null) { result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, "s"); return false; } if (s.Length == 0) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } Contract.Assert(dtfi != null, "dtfi == null"); #if _LOGGING DTFITrace(dtfi); #endif DateTime time; // // First try the predefined format. // DS dps = DS.BEGIN; // Date Parsing State. bool reachTerminalState = false; DateTimeToken dtok = new DateTimeToken(); // The buffer to store the parsing token. dtok.suffix = TokenType.SEP_Unk; DateTimeRawInfo raw = new DateTimeRawInfo(); // The buffer to store temporary parsing information. unsafe { Int32 * numberPointer = stackalloc Int32[3]; raw.Init(numberPointer); } raw.hasSameDateAndTimeSeparators = dtfi.DateSeparator.Equals(dtfi.TimeSeparator, StringComparison.Ordinal); result.calendar = dtfi.Calendar; result.era = Calendar.CurrentEra; // // The string to be parsed. Use a __DTString wrapper so that we can trace the index which // indicates the begining of next token. // __DTString str = new __DTString(s, dtfi); str.GetNext(); // // The following loop will break out when we reach the end of the str. // do { // // Call the lexer to get the next token. // // If we find a era in Lex(), the era value will be in raw.era. if (!Lex(dps, ref str, ref dtok, ref raw, ref result, ref dtfi, styles)) { TPTraceExit("0000", dps); return false; } // // If the token is not unknown, process it. // Otherwise, just discard it. // if (dtok.dtt != DTT.Unk) { // // Check if we got any CJK Date/Time suffix. // Since the Date/Time suffix tells us the number belongs to year/month/day/hour/minute/second, // store the number in the appropriate field in the result. // if (dtok.suffix != TokenType.SEP_Unk) { if (!ProcessDateTimeSuffix(ref result, ref raw, ref dtok)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); TPTraceExit("0010", dps); return false; } dtok.suffix = TokenType.SEP_Unk; // Reset suffix to SEP_Unk; } if (dtok.dtt == DTT.NumLocalTimeMark) { if (dps == DS.D_YNd || dps == DS.D_YN) { // Consider this as ISO 8601 format: // "yyyy-MM-dd'T'HH:mm:ss" 1999-10-31T02:00:00 TPTraceExit("0020", dps); return (ParseISO8601(ref raw, ref str, styles, ref result)); } else { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); TPTraceExit("0030", dps); return false; } } if (raw.hasSameDateAndTimeSeparators) { if (dtok.dtt == DTT.YearEnd || dtok.dtt == DTT.YearSpace || dtok.dtt == DTT.YearDateSep) { // When time and date separators are same and we are hitting a year number while the first parsed part of the string was recognized // as part of time (and not a date) DS.T_Nt, DS.T_NNt then change the state to be a date so we try to parse it as a date instead if (dps == DS.T_Nt) { dps = DS.D_Nd; } if (dps == DS.T_NNt) { dps = DS.D_NNd; } } bool atEnd = str.AtEnd(); if (dateParsingStates[(int)dps][(int)dtok.dtt] == DS.ERROR || atEnd) { switch (dtok.dtt) { // we have the case of Serbia have dates in forms 'd.M.yyyy.' so we can expect '.' after the date parts. // changing the token to end with space instead of Date Separator will avoid failing the parsing. case DTT.YearDateSep: dtok.dtt = atEnd ? DTT.YearEnd : DTT.YearSpace; break; case DTT.NumDatesep: dtok.dtt = atEnd ? DTT.NumEnd : DTT.NumSpace; break; case DTT.NumTimesep: dtok.dtt = atEnd ? DTT.NumEnd : DTT.NumSpace; break; case DTT.MonthDatesep: dtok.dtt = atEnd ? DTT.MonthEnd : DTT.MonthSpace; break; } } } // // Advance to the next state, and continue // dps = dateParsingStates[(int)dps][(int)dtok.dtt]; if (dps == DS.ERROR) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); TPTraceExit("0040 (invalid state transition)", dps); return false; } else if (dps > DS.ERROR) { if ((dtfi.FormatFlags & DateTimeFormatFlags.UseHebrewRule) != 0) { if (!ProcessHebrewTerminalState(dps, ref result, ref styles, ref raw, dtfi)) { TPTraceExit("0050 (ProcessHebrewTerminalState)", dps); return false; } } else { if (!ProcessTerminaltState(dps, ref result, ref styles, ref raw, dtfi)) { TPTraceExit("0060 (ProcessTerminaltState)", dps); return false; } } reachTerminalState = true; // // If we have reached a terminal state, start over from DS.BEGIN again. // For example, when we parsed "1999-12-23 13:30", we will reach a terminal state at "1999-12-23", // and we start over so we can continue to parse "12:30". // dps = DS.BEGIN; } } } while (dtok.dtt != DTT.End && dtok.dtt != DTT.NumEnd && dtok.dtt != DTT.MonthEnd); if (!reachTerminalState) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); TPTraceExit("0070 (did not reach terminal state)", dps); return false; } AdjustTimeMark(dtfi, ref raw); if (!AdjustHour(ref result.Hour, raw.timeMark)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); TPTraceExit("0080 (AdjustHour)", dps); return false; } // Check if the parased string only contains hour/minute/second values. bool bTimeOnly = (result.Year == -1 && result.Month == -1 && result.Day == -1); // // Check if any year/month/day is missing in the parsing string. // If yes, get the default value from today's date. // if (!CheckDefaultDateTime(ref result, ref result.calendar, styles)) { TPTraceExit("0090 (failed to fill in missing year/month/day defaults)", dps); return false; } if (!result.calendar.TryToDateTime(result.Year, result.Month, result.Day, result.Hour, result.Minute, result.Second, 0, result.era, out time)) { result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null); TPTraceExit("0100 (result.calendar.TryToDateTime)", dps); return false; } if (raw.fraction > 0) { time = time.AddTicks((long)Math.Round(raw.fraction * Calendar.TicksPerSecond)); } // // We have to check day of week before we adjust to the time zone. // Otherwise, the value of day of week may change after adjustting to the time zone. // if (raw.dayOfWeek != -1) { // // Check if day of week is correct. // if (raw.dayOfWeek != (int)result.calendar.GetDayOfWeek(time)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDayOfWeek", null); TPTraceExit("0110 (dayOfWeek check)", dps); return false; } } result.parsedDate = time; if (!DetermineTimeZoneAdjustments(ref result, styles, bTimeOnly)) { TPTraceExit("0120 (DetermineTimeZoneAdjustments)", dps); return false; } TPTraceExit("0130 (success)", dps); return true; }
private static bool GetTimeOfNNN(DateTimeFormatInfo dtfi, ref DateTimeResult result, ref DateTimeRawInfo raw) { if ((result.flags & ParseFlags.HaveTime) != (ParseFlags)0) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } result.Hour = raw.GetNumber(0); result.Minute = raw.GetNumber(1); result.Second = raw.GetNumber(2); result.flags |= ParseFlags.HaveTime; return true; }
// // 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 GetDateOfNDS(ref DateTimeResult result, ref DateTimeRawInfo raw) { if (result.Month == -1) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if (result.Year != -1) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } result.Year = DateTimeParse.AdjustYear(ref result, raw.GetNumber(0)); result.Day = 1; return true; }
[System.Security.SecuritySafeCritical] // auto-generated private static Boolean Lex(DS dps, ref __DTString str, ref DateTimeToken dtok, ref DateTimeRawInfo raw, ref DateTimeResult result, ref DateTimeFormatInfo dtfi, DateTimeStyles styles) { TokenType tokenType; int tokenValue; int indexBeforeSeparator; char charBeforeSeparator; TokenType sep; dtok.dtt = DTT.Unk; // Assume the token is unkown. str.GetRegularToken(out tokenType, out tokenValue, dtfi); #if _LOGGING // Builds with _LOGGING defined (x86dbg, amd64chk, etc) support tracing // Set the following internal-only/unsupported environment variables to enable DateTime tracing to the console: // // COMPlus_LogEnable=1 // COMPlus_LogToConsole=1 // COMPlus_LogLevel=9 // COMPlus_ManagedLogFacility=0x00001000 if (_tracingEnabled) { BCLDebug.Trace("DATETIME", "[DATETIME] Lex({0})\tpos:{1}({2}), {3}, DS.{4}", Hex(str.Value), str.Index, Hex(str.m_current), tokenType, dps); } #endif // _LOGGING // Look at the regular token. switch (tokenType) { case TokenType.NumberToken: case TokenType.YearNumberToken: if (raw.numCount == 3 || tokenValue == -1) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); LexTraceExit("0010", dps); return false; } // // This is a digit. // // 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). // // 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) { if ((str.Index < str.len - 1)) { char nextCh = str.Value[str.Index]; if (nextCh == '.') { // While ParseFraction can fail, it just means that there were no digits after // the dot. In this case ParseFraction just removes the dot. This is actually // valid for cultures like Albanian, that join the time marker to the time with // with a dot: e.g. "9:03.MD" ParseFraction(ref str, out raw.fraction); } } } if (dps == DS.T_NNt || dps == DS.T_Nt) { if ((str.Index < str.len - 1)) { if (false == HandleTimeZone(ref str, ref result)) { LexTraceExit("0020 (value like \"12:01\" or \"12:\" followed by a non-TZ number", dps); return false; } } } dtok.num = tokenValue; if (tokenType == TokenType.YearNumberToken) { if (raw.year == -1) { raw.year = tokenValue; // // 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 = str.GetSeparatorToken(dtfi, out indexBeforeSeparator, out charBeforeSeparator)) { case TokenType.SEP_End: dtok.dtt = DTT.YearEnd; break; case TokenType.SEP_Am: case TokenType.SEP_Pm: if (raw.timeMark == TM.NotSet) { raw.timeMark = (sep == TokenType.SEP_Am ? TM.AM : TM.PM); dtok.dtt = DTT.YearSpace; } else { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); LexTraceExit("0030 (TM.AM/TM.PM Happened more than 1x)", dps); } break; case TokenType.SEP_Space: dtok.dtt = DTT.YearSpace; break; case TokenType.SEP_Date: dtok.dtt = DTT.YearDateSep; break; case TokenType.SEP_Time: if (!raw.hasSameDateAndTimeSeparators) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); LexTraceExit("0040 (Invalid separator after number)", dps); return false; } // we have the date and time separators are same and getting a year number, then change the token to YearDateSep as // we are sure we are not parsing time. dtok.dtt = DTT.YearDateSep; break; case TokenType.SEP_DateOrOffset: // The separator is either a date separator or the start of a time zone offset. If the token will complete the date then // process just the number and roll back the index so that the outer loop can attempt to parse the time zone offset. if ((dateParsingStates[(int)dps][(int) DTT.YearDateSep] == DS.ERROR) && (dateParsingStates[(int)dps][(int) DTT.YearSpace] > DS.ERROR)) { str.Index = indexBeforeSeparator; str.m_current = charBeforeSeparator; dtok.dtt = DTT.YearSpace; } else { dtok.dtt = DTT.YearDateSep; } break; case TokenType.SEP_YearSuff: case TokenType.SEP_MonthSuff: case TokenType.SEP_DaySuff: dtok.dtt = DTT.NumDatesuff; dtok.suffix = sep; break; case TokenType.SEP_HourSuff: case TokenType.SEP_MinuteSuff: case TokenType.SEP_SecondSuff: dtok.dtt = DTT.NumTimesuff; dtok.suffix = sep; break; default: // Invalid separator after number number. result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); LexTraceExit("0040 (Invalid separator after number)", dps); return false; } // // Found the token already. Return now. // LexTraceExit("0050 (success)", dps); return true; } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); LexTraceExit("0060", dps); return false; } switch (sep = str.GetSeparatorToken(dtfi, out indexBeforeSeparator, out charBeforeSeparator)) { // // 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 TokenType.SEP_End: dtok.dtt = DTT.NumEnd; raw.AddNumber(dtok.num); break; case TokenType.SEP_Am: case TokenType.SEP_Pm: if (raw.timeMark == TM.NotSet) { raw.timeMark = (sep == TokenType.SEP_Am ? TM.AM : TM.PM); dtok.dtt = DTT.NumAmpm; // Fix AM/PM parsing case, e.g. "1/10 5 AM" if (dps == DS.D_NN #if !FEATURE_CORECLR && enableAmPmParseAdjustment #endif ) { if (!ProcessTerminaltState(DS.DX_NN, ref result, ref styles, ref raw, dtfi)) { return false; } } raw.AddNumber(dtok.num); } else { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); break; } if (dps == DS.T_NNt || dps == DS.T_Nt) { if (false == HandleTimeZone(ref str, ref result)) { LexTraceExit("0070 (HandleTimeZone returned false)", dps); return false; } } break; case TokenType.SEP_Space: dtok.dtt = DTT.NumSpace; raw.AddNumber(dtok.num); break; case TokenType.SEP_Date: dtok.dtt = DTT.NumDatesep; raw.AddNumber(dtok.num); break; case TokenType.SEP_DateOrOffset: // The separator is either a date separator or the start of a time zone offset. If the token will complete the date then // process just the number and roll back the index so that the outer loop can attempt to parse the time zone offset. if ((dateParsingStates[(int)dps][(int) DTT.NumDatesep] == DS.ERROR) && (dateParsingStates[(int)dps][(int) DTT.NumSpace] > DS.ERROR)) { str.Index = indexBeforeSeparator; str.m_current = charBeforeSeparator; dtok.dtt = DTT.NumSpace; } else { dtok.dtt = DTT.NumDatesep; } raw.AddNumber(dtok.num); break; case TokenType.SEP_Time: if (raw.hasSameDateAndTimeSeparators && (dps == DS.D_Y || dps == DS.D_YN || dps == DS.D_YNd || dps == DS.D_YM || dps == DS.D_YMd)) { // we are parsing a date and we have the time separator same as date separator, so we mark the token as date separator dtok.dtt = DTT.NumDatesep; raw.AddNumber(dtok.num); break; } dtok.dtt = DTT.NumTimesep; raw.AddNumber(dtok.num); break; case TokenType.SEP_YearSuff: try { dtok.num = dtfi.Calendar.ToFourDigitYear(tokenValue); } catch (ArgumentOutOfRangeException e) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", e); LexTraceExit("0075 (Calendar.ToFourDigitYear failed)", dps); return false; } dtok.dtt = DTT.NumDatesuff; dtok.suffix = sep; break; case TokenType.SEP_MonthSuff: case TokenType.SEP_DaySuff: dtok.dtt = DTT.NumDatesuff; dtok.suffix = sep; break; case TokenType.SEP_HourSuff: case TokenType.SEP_MinuteSuff: case TokenType.SEP_SecondSuff: dtok.dtt = DTT.NumTimesuff; dtok.suffix = sep; break; case TokenType.SEP_LocalTimeMark: dtok.dtt = DTT.NumLocalTimeMark; raw.AddNumber(dtok.num); break; default: // Invalid separator after number number. result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); LexTraceExit("0080", dps); return false; } break; case TokenType.HebrewNumber: if (tokenValue >= 100) { // This is a year number if (raw.year == -1) { raw.year = tokenValue; // // 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 = str.GetSeparatorToken(dtfi, out indexBeforeSeparator, out charBeforeSeparator)) { case TokenType.SEP_End: dtok.dtt = DTT.YearEnd; break; case TokenType.SEP_Space: dtok.dtt = DTT.YearSpace; break; case TokenType.SEP_DateOrOffset: // The separator is either a date separator or the start of a time zone offset. If the token will complete the date then // process just the number and roll back the index so that the outer loop can attempt to parse the time zone offset. if (dateParsingStates[(int)dps][(int) DTT.YearSpace] > DS.ERROR) { str.Index = indexBeforeSeparator; str.m_current = charBeforeSeparator; dtok.dtt = DTT.YearSpace; break; } goto default; default: // Invalid separator after number number. result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); LexTraceExit("0090", dps); return false; } } else { // Invalid separator after number number. result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); LexTraceExit("0100", dps); return false; } } else { // This is a day number dtok.num = tokenValue; raw.AddNumber(dtok.num); switch (sep = str.GetSeparatorToken(dtfi, out indexBeforeSeparator, out charBeforeSeparator)) { // // 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 TokenType.SEP_End: dtok.dtt = DTT.NumEnd; break; case TokenType.SEP_Space: case TokenType.SEP_Date: dtok.dtt = DTT.NumDatesep; break; case TokenType.SEP_DateOrOffset: // The separator is either a date separator or the start of a time zone offset. If the token will complete the date then // process just the number and roll back the index so that the outer loop can attempt to parse the time zone offset. if ((dateParsingStates[(int)dps][(int) DTT.NumDatesep] == DS.ERROR) && (dateParsingStates[(int)dps][(int) DTT.NumSpace] > DS.ERROR)) { str.Index = indexBeforeSeparator; str.m_current = charBeforeSeparator; dtok.dtt = DTT.NumSpace; } else { dtok.dtt = DTT.NumDatesep; } break; default: // Invalid separator after number number. result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); LexTraceExit("0110", dps); return false; } } break; case TokenType.DayOfWeekToken: if (raw.dayOfWeek == -1) { // // This is a day of week name. // raw.dayOfWeek = tokenValue; dtok.dtt = DTT.DayOfWeek; } else { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); LexTraceExit("0120 (DayOfWeek seen more than 1x)", dps); return false; } break; case TokenType.MonthToken: if (raw.month == -1) { // // This is a month name // switch(sep=str.GetSeparatorToken(dtfi, out indexBeforeSeparator, out charBeforeSeparator)) { case TokenType.SEP_End: dtok.dtt = DTT.MonthEnd; break; case TokenType.SEP_Space: dtok.dtt = DTT.MonthSpace; break; case TokenType.SEP_Date: dtok.dtt = DTT.MonthDatesep; break; case TokenType.SEP_Time: if (!raw.hasSameDateAndTimeSeparators) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); LexTraceExit("0130 (Invalid separator after month name)", dps); return false; } // we have the date and time separators are same and getting a Month name, then change the token to MonthDatesep as // we are sure we are not parsing time. dtok.dtt = DTT.MonthDatesep; break; case TokenType.SEP_DateOrOffset: // The separator is either a date separator or the start of a time zone offset. If the token will complete the date then // process just the number and roll back the index so that the outer loop can attempt to parse the time zone offset. if ((dateParsingStates[(int)dps][(int) DTT.MonthDatesep] == DS.ERROR) && (dateParsingStates[(int)dps][(int) DTT.MonthSpace] > DS.ERROR)) { str.Index = indexBeforeSeparator; str.m_current = charBeforeSeparator; dtok.dtt = DTT.MonthSpace; } else { dtok.dtt = DTT.MonthDatesep; } break; default: //Invalid separator after month name result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); LexTraceExit("0130 (Invalid separator after month name)", dps); return false; } raw.month = tokenValue; } else { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); LexTraceExit("0140 (MonthToken seen more than 1x)", dps); return false; } break; case TokenType.EraToken: if (result.era != -1) { result.era = tokenValue; dtok.dtt = DTT.Era; } else { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); LexTraceExit("0150 (EraToken seen when result.era already set)", dps); return false; } break; case TokenType.JapaneseEraToken: // Special case for Japanese. We allow Japanese era name to be used even if the calendar is not Japanese Calendar. result.calendar = JapaneseCalendar.GetDefaultInstance(); dtfi = DateTimeFormatInfo.GetJapaneseCalendarDTFI(); if (result.era != -1) { result.era = tokenValue; dtok.dtt = DTT.Era; } else { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); LexTraceExit("0160 (JapaneseEraToken seen when result.era already set)", dps); return false; } break; case TokenType.TEraToken: result.calendar = TaiwanCalendar.GetDefaultInstance(); dtfi = DateTimeFormatInfo.GetTaiwanCalendarDTFI(); if (result.era != -1) { result.era = tokenValue; dtok.dtt = DTT.Era; } else { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); LexTraceExit("0170 (TEraToken seen when result.era already set)", dps); return false; } break; case TokenType.TimeZoneToken: // // This is a timezone designator // // NOTENOTE : for now, we only support "GMT" and "Z" (for Zulu time). // if ((result.flags & ParseFlags.TimeZoneUsed) != 0) { // Should not have two timezone offsets. result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); LexTraceExit("0180 (seen GMT or Z more than 1x)", dps); return false; } dtok.dtt = DTT.TimeZone; result.flags |= ParseFlags.TimeZoneUsed; result.timeZoneOffset = new TimeSpan(0); result.flags |= ParseFlags.TimeZoneUtc; break; case TokenType.EndOfString: dtok.dtt = DTT.End; break; case TokenType.DateWordToken: case TokenType.IgnorableSymbol: // Date words and ignorable symbols can just be skipped over break; case TokenType.Am: case TokenType.Pm: if (raw.timeMark == TM.NotSet) { raw.timeMark = (TM)tokenValue; } else { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); LexTraceExit("0190 (AM/PM timeMark already set)", dps); return false; } break; case TokenType.UnknownToken: if (Char.IsLetter(str.m_current)) { result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_UnknowDateTimeWord", str.Index); LexTraceExit("0200", dps); return (false); } #if !FEATURE_CORECLR // If DateTimeParseIgnorePunctuation is defined, we want to have the V1.1 behavior of just // ignoring any unrecognized punctuation and moving on to the next character if (Environment.GetCompatibilityFlag(CompatibilityFlag.DateTimeParseIgnorePunctuation) && ((result.flags & ParseFlags.CaptureOffset) == 0)) { str.GetNext(); LexTraceExit("0210 (success)", dps); return true; } #endif // FEATURE_CORECLR if ((str.m_current == '-' || str.m_current == '+') && ((result.flags & ParseFlags.TimeZoneUsed) == 0)) { Int32 originalIndex = str.Index; if (ParseTimeZone(ref str, ref result.timeZoneOffset)) { result.flags |= ParseFlags.TimeZoneUsed; LexTraceExit("0220 (success)", dps); return true; } else { // Time zone parse attempt failed. Fall through to punctuation handling. str.Index = originalIndex; } } // Visual Basic implements string to date conversions on top of DateTime.Parse: // CDate("#10/10/95#") // if (VerifyValidPunctuation(ref str)) { LexTraceExit("0230 (success)", dps); return true; } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); LexTraceExit("0240", dps); return false; } LexTraceExit("0250 (success)", dps); return true; }
private static bool ProcessDateTimeSuffix(ref DateTimeResult result, ref DateTimeRawInfo raw, ref DateTimeToken dtok) { TokenType suffix = dtok.suffix; if (suffix <= TokenType.SEP_DaySuff) { if (suffix != TokenType.SEP_YearSuff) { if (suffix != TokenType.SEP_MonthSuff) { if (suffix == TokenType.SEP_DaySuff) { if ((result.flags & ParseFlags.HaveDay) != (ParseFlags)0) { return false; } result.flags |= ParseFlags.HaveDay; result.Day = dtok.num; } } else { if ((result.flags & ParseFlags.HaveMonth) != (ParseFlags)0) { return false; } result.flags |= ParseFlags.HaveMonth; result.Month = (raw.month = dtok.num); } } else { if ((result.flags & ParseFlags.HaveYear) != (ParseFlags)0) { return false; } result.flags |= ParseFlags.HaveYear; result.Year = (raw.year = dtok.num); } } else { if (suffix != TokenType.SEP_HourSuff) { if (suffix != TokenType.SEP_MinuteSuff) { if (suffix == TokenType.SEP_SecondSuff) { if ((result.flags & ParseFlags.HaveSecond) != (ParseFlags)0) { return false; } result.flags |= ParseFlags.HaveSecond; result.Second = dtok.num; } } else { if ((result.flags & ParseFlags.HaveMinute) != (ParseFlags)0) { return false; } result.flags |= ParseFlags.HaveMinute; result.Minute = dtok.num; } } else { if ((result.flags & ParseFlags.HaveHour) != (ParseFlags)0) { return false; } result.flags |= ParseFlags.HaveHour; result.Hour = dtok.num; } } return true; }
private static bool GetHebrewDayOfNM(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi) { int num; if (!DateTimeParse.GetMonthDayOrder(dtfi.MonthDayPattern, dtfi, out num)) { result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadDatePattern", dtfi.MonthDayPattern); return false; } result.Month = raw.month; if ((num == 7 || num == 6) && result.calendar.IsValidDay(result.Year, result.Month, raw.GetNumber(0), result.era)) { result.Day = raw.GetNumber(0); return true; } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; }
internal static bool ProcessTerminaltState(DateTimeParse.DS dps, ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi) { bool flag = true; switch (dps) { case DateTimeParse.DS.DX_NN: { flag = DateTimeParse.GetDayOfNN(ref result, ref styles, ref raw, dtfi); break; } case DateTimeParse.DS.DX_NNN: { flag = DateTimeParse.GetDayOfNNN(ref result, ref raw, dtfi); break; } case DateTimeParse.DS.DX_MN: { flag = DateTimeParse.GetDayOfMN(ref result, ref styles, ref raw, dtfi); break; } case DateTimeParse.DS.DX_NM: { flag = DateTimeParse.GetDayOfNM(ref result, ref styles, ref raw, dtfi); break; } case DateTimeParse.DS.DX_MNN: { flag = DateTimeParse.GetDayOfMNN(ref result, ref raw, dtfi); break; } case DateTimeParse.DS.DX_DS: { flag = true; break; } case DateTimeParse.DS.DX_DSN: { flag = DateTimeParse.GetDateOfDSN(ref result, ref raw); break; } case DateTimeParse.DS.DX_NDS: { flag = DateTimeParse.GetDateOfNDS(ref result, ref raw); break; } case DateTimeParse.DS.DX_NNDS: { flag = DateTimeParse.GetDateOfNNDS(ref result, ref raw, dtfi); break; } case DateTimeParse.DS.DX_YNN: { flag = DateTimeParse.GetDayOfYNN(ref result, ref raw, dtfi); break; } case DateTimeParse.DS.DX_YMN: { flag = DateTimeParse.GetDayOfYMN(ref result, ref raw, dtfi); break; } case DateTimeParse.DS.DX_YN: { flag = DateTimeParse.GetDayOfYN(ref result, ref raw, dtfi); break; } case DateTimeParse.DS.DX_YM: { flag = DateTimeParse.GetDayOfYM(ref result, ref raw, dtfi); break; } case DateTimeParse.DS.TX_N: { flag = DateTimeParse.GetTimeOfN(dtfi, ref result, ref raw); break; } case DateTimeParse.DS.TX_NN: { flag = DateTimeParse.GetTimeOfNN(dtfi, ref result, ref raw); break; } case DateTimeParse.DS.TX_NNN: { flag = DateTimeParse.GetTimeOfNNN(dtfi, ref result, ref raw); break; } case DateTimeParse.DS.TX_TS: { flag = true; break; } case DateTimeParse.DS.DX_NNY: { flag = DateTimeParse.GetDayOfNNY(ref result, ref raw, dtfi); break; } } if (!flag) { return false; } if (dps > DateTimeParse.DS.ERROR) { raw.numCount = 0; } return true; }
private static bool GetDayOfNM(ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi) { if ((result.flags & ParseFlags.HaveDate) != (ParseFlags)0) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } int num; if (!DateTimeParse.GetMonthDayOrder(dtfi.MonthDayPattern, dtfi, out num)) { result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadDatePattern", dtfi.MonthDayPattern); return false; } if (num == 6) { int num2; if (!DateTimeParse.GetYearMonthOrder(dtfi.YearMonthPattern, dtfi, out num2)) { result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadDatePattern", dtfi.YearMonthPattern); return false; } if (num2 == 4) { if (!DateTimeParse.SetDateYMD(ref result, DateTimeParse.AdjustYear(ref result, raw.GetNumber(0)), raw.month, 1)) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } return true; } } DateTimeParse.GetDefaultYear(ref result, ref styles); if (!DateTimeParse.SetDateYMD(ref result, result.Year, raw.month, raw.GetNumber(0))) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } return true; }
private static bool Lex(DateTimeParse.DS dps, ref __DTString str, ref DateTimeToken dtok, ref DateTimeRawInfo raw, ref DateTimeResult result, ref DateTimeFormatInfo dtfi) { dtok.dtt = DateTimeParse.DTT.Unk; TokenType tokenType; int num; str.GetRegularToken(out tokenType, out num, dtfi); switch (tokenType) { case TokenType.NumberToken: case TokenType.YearNumberToken: { if (raw.numCount == 3 || num == -1) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if (dps == DateTimeParse.DS.T_NNt && str.Index < str.len - 1) { char c = str.Value[str.Index]; if (c == '.') { DateTimeParse.ParseFraction(ref str, out raw.fraction); } } if ((dps == DateTimeParse.DS.T_NNt || dps == DateTimeParse.DS.T_Nt) && str.Index < str.len - 1 && !DateTimeParse.HandleTimeZone(ref str, ref result)) { return false; } dtok.num = num; if (tokenType != TokenType.YearNumberToken) { int index; char current; TokenType separatorToken; TokenType tokenType2 = separatorToken = str.GetSeparatorToken(dtfi, out index, out current); if (separatorToken > TokenType.SEP_YearSuff) { if (separatorToken <= TokenType.SEP_HourSuff) { if (separatorToken == TokenType.SEP_MonthSuff || separatorToken == TokenType.SEP_DaySuff) { dtok.dtt = DateTimeParse.DTT.NumDatesuff; dtok.suffix = tokenType2; break; } if (separatorToken != TokenType.SEP_HourSuff) { goto IL_52A; } } else { if (separatorToken <= TokenType.SEP_SecondSuff) { if (separatorToken != TokenType.SEP_MinuteSuff && separatorToken != TokenType.SEP_SecondSuff) { goto IL_52A; } } else { if (separatorToken == TokenType.SEP_LocalTimeMark) { dtok.dtt = DateTimeParse.DTT.NumLocalTimeMark; raw.AddNumber(dtok.num); break; } if (separatorToken != TokenType.SEP_DateOrOffset) { goto IL_52A; } if (DateTimeParse.dateParsingStates[(int)dps][4] == DateTimeParse.DS.ERROR && DateTimeParse.dateParsingStates[(int)dps][3] > DateTimeParse.DS.ERROR) { str.Index = index; str.m_current = current; dtok.dtt = DateTimeParse.DTT.NumSpace; } else { dtok.dtt = DateTimeParse.DTT.NumDatesep; } raw.AddNumber(dtok.num); break; } } dtok.dtt = DateTimeParse.DTT.NumTimesuff; dtok.suffix = tokenType2; break; } if (separatorToken <= TokenType.SEP_Am) { if (separatorToken == TokenType.SEP_End) { dtok.dtt = DateTimeParse.DTT.NumEnd; raw.AddNumber(dtok.num); break; } if (separatorToken == TokenType.SEP_Space) { dtok.dtt = DateTimeParse.DTT.NumSpace; raw.AddNumber(dtok.num); break; } if (separatorToken != TokenType.SEP_Am) { goto IL_52A; } } else { if (separatorToken <= TokenType.SEP_Date) { if (separatorToken != TokenType.SEP_Pm) { if (separatorToken != TokenType.SEP_Date) { goto IL_52A; } dtok.dtt = DateTimeParse.DTT.NumDatesep; raw.AddNumber(dtok.num); break; } } else { if (separatorToken == TokenType.SEP_Time) { dtok.dtt = DateTimeParse.DTT.NumTimesep; raw.AddNumber(dtok.num); break; } if (separatorToken != TokenType.SEP_YearSuff) { goto IL_52A; } dtok.num = dtfi.Calendar.ToFourDigitYear(num); dtok.dtt = DateTimeParse.DTT.NumDatesuff; dtok.suffix = tokenType2; break; } } if (raw.timeMark != DateTimeParse.TM.NotSet) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); break; } raw.timeMark = ((tokenType2 == TokenType.SEP_Am) ? DateTimeParse.TM.AM : DateTimeParse.TM.PM); dtok.dtt = DateTimeParse.DTT.NumAmpm; raw.AddNumber(dtok.num); if ((dps == DateTimeParse.DS.T_NNt || dps == DateTimeParse.DS.T_Nt) && !DateTimeParse.HandleTimeZone(ref str, ref result)) { return false; } break; IL_52A: result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if (raw.year == -1) { raw.year = num; int index; char current; TokenType separatorToken2; TokenType tokenType2 = separatorToken2 = str.GetSeparatorToken(dtfi, out index, out current); if (separatorToken2 > TokenType.SEP_YearSuff) { if (separatorToken2 <= TokenType.SEP_HourSuff) { if (separatorToken2 == TokenType.SEP_MonthSuff || separatorToken2 == TokenType.SEP_DaySuff) { goto IL_26A; } if (separatorToken2 != TokenType.SEP_HourSuff) { goto IL_28E; } } else { if (separatorToken2 != TokenType.SEP_MinuteSuff && separatorToken2 != TokenType.SEP_SecondSuff) { if (separatorToken2 != TokenType.SEP_DateOrOffset) { goto IL_28E; } if (DateTimeParse.dateParsingStates[(int)dps][13] == DateTimeParse.DS.ERROR && DateTimeParse.dateParsingStates[(int)dps][12] > DateTimeParse.DS.ERROR) { str.Index = index; str.m_current = current; dtok.dtt = DateTimeParse.DTT.YearSpace; return true; } dtok.dtt = DateTimeParse.DTT.YearDateSep; return true; } } dtok.dtt = DateTimeParse.DTT.NumTimesuff; dtok.suffix = tokenType2; return true; } if (separatorToken2 <= TokenType.SEP_Am) { if (separatorToken2 == TokenType.SEP_End) { dtok.dtt = DateTimeParse.DTT.YearEnd; return true; } if (separatorToken2 == TokenType.SEP_Space) { dtok.dtt = DateTimeParse.DTT.YearSpace; return true; } if (separatorToken2 != TokenType.SEP_Am) { goto IL_28E; } } else { if (separatorToken2 != TokenType.SEP_Pm) { if (separatorToken2 == TokenType.SEP_Date) { dtok.dtt = DateTimeParse.DTT.YearDateSep; return true; } if (separatorToken2 != TokenType.SEP_YearSuff) { goto IL_28E; } goto IL_26A; } } if (raw.timeMark == DateTimeParse.TM.NotSet) { raw.timeMark = ((tokenType2 == TokenType.SEP_Am) ? DateTimeParse.TM.AM : DateTimeParse.TM.PM); dtok.dtt = DateTimeParse.DTT.YearSpace; return true; } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return true; IL_26A: dtok.dtt = DateTimeParse.DTT.NumDatesuff; dtok.suffix = tokenType2; return true; IL_28E: result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } case TokenType.Am: case TokenType.Pm: { if (raw.timeMark != DateTimeParse.TM.NotSet) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } raw.timeMark = (DateTimeParse.TM)num; break; } case TokenType.MonthToken: { if (raw.month != -1) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } int index; char current; TokenType separatorToken3 = str.GetSeparatorToken(dtfi, out index, out current); if (separatorToken3 <= TokenType.SEP_Space) { if (separatorToken3 == TokenType.SEP_End) { dtok.dtt = DateTimeParse.DTT.MonthEnd; goto IL_786; } if (separatorToken3 == TokenType.SEP_Space) { dtok.dtt = DateTimeParse.DTT.MonthSpace; goto IL_786; } } else { if (separatorToken3 == TokenType.SEP_Date) { dtok.dtt = DateTimeParse.DTT.MonthDatesep; goto IL_786; } if (separatorToken3 == TokenType.SEP_DateOrOffset) { if (DateTimeParse.dateParsingStates[(int)dps][8] == DateTimeParse.DS.ERROR && DateTimeParse.dateParsingStates[(int)dps][7] > DateTimeParse.DS.ERROR) { str.Index = index; str.m_current = current; dtok.dtt = DateTimeParse.DTT.MonthSpace; goto IL_786; } dtok.dtt = DateTimeParse.DTT.MonthDatesep; goto IL_786; } } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; IL_786: raw.month = num; break; } case TokenType.EndOfString: { dtok.dtt = DateTimeParse.DTT.End; break; } case TokenType.DayOfWeekToken: { if (raw.dayOfWeek != -1) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } raw.dayOfWeek = num; dtok.dtt = DateTimeParse.DTT.DayOfWeek; break; } case TokenType.TimeZoneToken: { if ((result.flags & ParseFlags.TimeZoneUsed) != (ParseFlags)0) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } dtok.dtt = DateTimeParse.DTT.TimeZone; result.flags |= ParseFlags.TimeZoneUsed; result.timeZoneOffset = new TimeSpan(0L); result.flags |= ParseFlags.TimeZoneUtc; break; } case TokenType.EraToken: { if (result.era == -1) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } result.era = num; dtok.dtt = DateTimeParse.DTT.Era; break; } case TokenType.UnknownToken: { if (char.IsLetter(str.m_current)) { result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_UnknowDateTimeWord", str.Index); return false; } if (Environment.GetCompatibilityFlag(CompatibilityFlag.DateTimeParseIgnorePunctuation) && (result.flags & ParseFlags.CaptureOffset) == (ParseFlags)0) { str.GetNext(); return true; } if ((str.m_current == '-' || str.m_current == '+') && (result.flags & ParseFlags.TimeZoneUsed) == (ParseFlags)0) { int index2 = str.Index; if (DateTimeParse.ParseTimeZone(ref str, ref result.timeZoneOffset)) { result.flags |= ParseFlags.TimeZoneUsed; return true; } str.Index = index2; } if (DateTimeParse.VerifyValidPunctuation(ref str)) { return true; } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } case TokenType.HebrewNumber: { int index; char current; if (num < 100) { dtok.num = num; raw.AddNumber(dtok.num); TokenType separatorToken4 = str.GetSeparatorToken(dtfi, out index, out current); if (separatorToken4 <= TokenType.SEP_Space) { if (separatorToken4 == TokenType.SEP_End) { dtok.dtt = DateTimeParse.DTT.NumEnd; break; } if (separatorToken4 != TokenType.SEP_Space) { goto IL_695; } } else { if (separatorToken4 != TokenType.SEP_Date) { if (separatorToken4 != TokenType.SEP_DateOrOffset) { goto IL_695; } if (DateTimeParse.dateParsingStates[(int)dps][4] == DateTimeParse.DS.ERROR && DateTimeParse.dateParsingStates[(int)dps][3] > DateTimeParse.DS.ERROR) { str.Index = index; str.m_current = current; dtok.dtt = DateTimeParse.DTT.NumSpace; break; } dtok.dtt = DateTimeParse.DTT.NumDatesep; break; } } dtok.dtt = DateTimeParse.DTT.NumDatesep; break; IL_695: result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } if (raw.year != -1) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } raw.year = num; TokenType separatorToken5 = str.GetSeparatorToken(dtfi, out index, out current); if (separatorToken5 != TokenType.SEP_End) { if (separatorToken5 != TokenType.SEP_Space) { if (separatorToken5 == TokenType.SEP_DateOrOffset) { if (DateTimeParse.dateParsingStates[(int)dps][12] > DateTimeParse.DS.ERROR) { str.Index = index; str.m_current = current; dtok.dtt = DateTimeParse.DTT.YearSpace; break; } } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } dtok.dtt = DateTimeParse.DTT.YearSpace; } else { dtok.dtt = DateTimeParse.DTT.YearEnd; } break; } case TokenType.JapaneseEraToken: { result.calendar = JapaneseCalendar.GetDefaultInstance(); dtfi = DateTimeFormatInfo.GetJapaneseCalendarDTFI(); if (result.era == -1) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } result.era = num; dtok.dtt = DateTimeParse.DTT.Era; break; } case TokenType.TEraToken: { result.calendar = TaiwanCalendar.GetDefaultInstance(); dtfi = DateTimeFormatInfo.GetTaiwanCalendarDTFI(); if (result.era == -1) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } result.era = num; dtok.dtt = DateTimeParse.DTT.Era; break; } } return true; }
private static Boolean GetDayOfYNN(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi) { if ((result.flags & ParseFlags.HaveDate) != 0) { // Multiple dates in the input string result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } int n1 = raw.GetNumber(0); int n2 = raw.GetNumber(1); String pattern = dtfi.ShortDatePattern; // For compatibility, don't throw if we can't determine the order, but default to YMD instead int order; if (GetYearMonthDayOrder(pattern, dtfi, out order) && order == ORDER_YDM) { if (SetDateYMD(ref result, raw.year, n2, n1)) { result.flags |= ParseFlags.HaveDate; return true; // Year + DM } } else { if (SetDateYMD(ref result, raw.year, n1, n2)) { result.flags |= ParseFlags.HaveDate; return true; // Year + MD } } result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; }