From 64451083d5bb7204aa6ea46f04c7d0faaf40a260 Mon Sep 17 00:00:00 2001 From: Tarek Mahmoud Sayed Date: Wed, 12 Aug 2015 12:50:14 -0700 Subject: [PATCH] Port the DateTime parser fix from the Desktop This change is fixing the DateTime parser in cases of date/time strings for cultures which has the date and time separators are same. This happen with Norway, Serbia and Finland cultures [tfs-changeset: 1513801] --- .../src/System/Globalization/DateTimeParse.cs | 56 ++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/mscorlib/src/System/Globalization/DateTimeParse.cs b/src/mscorlib/src/System/Globalization/DateTimeParse.cs index bbece12..2c644a9 100644 --- a/src/mscorlib/src/System/Globalization/DateTimeParse.cs +++ b/src/mscorlib/src/System/Globalization/DateTimeParse.cs @@ -691,6 +691,18 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR, 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. @@ -796,6 +808,14 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR, 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; @@ -941,6 +961,18 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR, 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. @@ -2315,6 +2347,8 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR, 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; @@ -2376,6 +2410,27 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR, } } + if (raw.hasSameDateAndTimeSeparators && (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; + + // we have the case of Serbia have dates in forms 'd.M.yyyy.' so we can expect '.' after the year number. + // changing the token to YearSpace instead of YearDateSep will make the parsing not failing this case. + if (dtok.dtt == DTT.YearDateSep) + { + dtok.dtt = DTT.YearSpace; + } + } + } + // // Advance to the next state, and continue // @@ -4812,6 +4867,7 @@ Start: internal int era; internal DateTimeParse.TM timeMark; internal double fraction; + internal bool hasSameDateAndTimeSeparators; // internal bool timeZone; -- 2.7.4