internal static MatchNumberDelegate m_hebrewNumberParser = new MatchNumberDelegate(DateTimeParse.MatchHebrewDigits);
- internal static DateTime ParseExact(ReadOnlySpan<char> s, String format, DateTimeFormatInfo dtfi, DateTimeStyles style)
+ internal static DateTime ParseExact(ReadOnlySpan<char> s, ReadOnlySpan<char> format, DateTimeFormatInfo dtfi, DateTimeStyles style)
{
DateTimeResult result = new DateTimeResult(); // The buffer to store the parsing result.
- result.Init();
+ result.Init(s);
if (TryParseExact(s, format, dtfi, style, ref result))
{
return result.parsedDate;
}
}
- internal static DateTime ParseExact(ReadOnlySpan<char> s, String format, DateTimeFormatInfo dtfi, DateTimeStyles style, out TimeSpan offset)
+ internal static DateTime ParseExact(ReadOnlySpan<char> s, ReadOnlySpan<char> format, DateTimeFormatInfo dtfi, DateTimeStyles style, out TimeSpan offset)
{
DateTimeResult result = new DateTimeResult(); // The buffer to store the parsing result.
offset = TimeSpan.Zero;
- result.Init();
+ result.Init(s);
result.flags |= ParseFlags.CaptureOffset;
if (TryParseExact(s, format, dtfi, style, ref result))
{
}
}
- internal static bool TryParseExact(ReadOnlySpan<char> s, String format, DateTimeFormatInfo dtfi, DateTimeStyles style, out DateTime result)
+ internal static bool TryParseExact(ReadOnlySpan<char> s, ReadOnlySpan<char> format, DateTimeFormatInfo dtfi, DateTimeStyles style, out DateTime result)
{
result = DateTime.MinValue;
DateTimeResult resultData = new DateTimeResult(); // The buffer to store the parsing result.
- resultData.Init();
+ resultData.Init(s);
if (TryParseExact(s, format, dtfi, style, ref resultData))
{
result = resultData.parsedDate;
return false;
}
- internal static bool TryParseExact(ReadOnlySpan<char> s, String format, DateTimeFormatInfo dtfi, DateTimeStyles style, out DateTime result, out TimeSpan offset)
+ internal static bool TryParseExact(ReadOnlySpan<char> s, ReadOnlySpan<char> format, DateTimeFormatInfo dtfi, DateTimeStyles style, out DateTime result, out TimeSpan offset)
{
result = DateTime.MinValue;
offset = TimeSpan.Zero;
DateTimeResult resultData = new DateTimeResult(); // The buffer to store the parsing result.
- resultData.Init();
+ resultData.Init(s);
resultData.flags |= ParseFlags.CaptureOffset;
if (TryParseExact(s, format, dtfi, style, ref resultData))
{
return false;
}
- internal static bool TryParseExact(ReadOnlySpan<char> s, String format, DateTimeFormatInfo dtfi, DateTimeStyles style, ref DateTimeResult result)
+ internal static bool TryParseExact(ReadOnlySpan<char> s, ReadOnlySpan<char> format, DateTimeFormatInfo dtfi, DateTimeStyles style, ref DateTimeResult result)
{
- if (format == null)
- {
- result.SetFailure(ParseFailureKind.ArgumentNull, nameof(SR.ArgumentNull_String), null, nameof(format));
- return false;
- }
if (s.Length == 0)
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_BadDateTime));
return false;
}
if (format.Length == 0)
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadFormatSpecifier), null);
+ result.SetBadFormatSpecifierFailure();
return false;
}
DateTimeFormatInfo dtfi, DateTimeStyles style)
{
DateTimeResult result = new DateTimeResult(); // The buffer to store the parsing result.
- result.Init();
+ result.Init(s);
if (TryParseExactMultiple(s, formats, dtfi, style, ref result))
{
return result.parsedDate;
{
DateTimeResult result = new DateTimeResult(); // The buffer to store the parsing result.
offset = TimeSpan.Zero;
- result.Init();
+ result.Init(s);
result.flags |= ParseFlags.CaptureOffset;
if (TryParseExactMultiple(s, formats, dtfi, style, ref result))
{
result = DateTime.MinValue;
offset = TimeSpan.Zero;
DateTimeResult resultData = new DateTimeResult(); // The buffer to store the parsing result.
- resultData.Init();
+ resultData.Init(s);
resultData.flags |= ParseFlags.CaptureOffset;
if (TryParseExactMultiple(s, formats, dtfi, style, ref resultData))
{
{
result = DateTime.MinValue;
DateTimeResult resultData = new DateTimeResult(); // The buffer to store the parsing result.
- resultData.Init();
+ resultData.Init(s);
if (TryParseExactMultiple(s, formats, dtfi, style, ref resultData))
{
result = resultData.parsedDate;
if (s.Length == 0)
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_BadDateTime));
return false;
}
if (formats.Length == 0)
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadFormatSpecifier), null);
+ result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_NoFormatSpecifier));
return false;
}
{
if (formats[i] == null || formats[i].Length == 0)
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadFormatSpecifier), null);
+ result.SetBadFormatSpecifierFailure();
return false;
}
// Create a new result each time to ensure the runs are independent. Carry through
// flags from the caller and return the result.
DateTimeResult innerResult = new DateTimeResult(); // The buffer to store the parsing result.
- innerResult.Init();
+ innerResult.Init(s);
innerResult.flags = result.flags;
if (TryParseExact(s, formats[i], dtfi, style, ref innerResult))
{
return (true);
}
}
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return (false);
}
//
////////////////////////////////////////////////////////////////////////////
- // End NumEnd NumAmPm NumSpace NumDaySep NumTimesep MonthEnd MonthSpace MonthDSep NumDateSuff NumTimeSuff DayOfWeek YearSpace YearDateSep YearEnd TimeZone Era UTCTimeMark
+ // End NumEnd NumAmPm NumSpace NumDaySep NumTimesep MonthEnd MonthSpace MonthDSep NumDateSuff NumTimeSuff DayOfWeek YearSpace YearDateSep YearEnd TimeZone Era UTCTimeMark
private static DS[][] dateParsingStates = {
// DS.BEGIN // DS.BEGIN
new DS[] { DS.BEGIN, DS.ERROR, DS.TX_N, DS.N, DS.D_Nd, DS.T_Nt, DS.ERROR, DS.D_M, DS.D_M, DS.D_S, DS.T_S, DS.BEGIN, DS.D_Y, DS.D_Y, DS.ERROR, DS.BEGIN, DS.BEGIN, DS.ERROR},
if ((result.flags & ParseFlags.TimeZoneUsed) != 0)
{
// Should not have two timezone offsets.
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
result.flags |= ParseFlags.TimeZoneUsed;
if (!ParseTimeZone(ref str, ref result.timeZoneOffset))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
}
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);
+ Trace($"Lex({Hex(str.Value)})\tpos:{str.Index}({Hex(str.m_current)}), {tokenType}, DS.{dps}");
}
#endif // _LOGGING
case TokenType.YearNumberToken:
if (raw.numCount == 3 || tokenValue == -1)
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
LexTraceExit("0010", dps);
return false;
}
}
else
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
LexTraceExit("0030 (TM.AM/TM.PM Happened more than 1x)", dps);
}
break;
case TokenType.SEP_Time:
if (!raw.hasSameDateAndTimeSeparators)
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
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 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;
break;
default:
// Invalid separator after number number.
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
LexTraceExit("0040 (Invalid separator after number)", dps);
return false;
}
LexTraceExit("0050 (success)", dps);
return true;
}
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
LexTraceExit("0060", dps);
return false;
}
// Fix AM/PM parsing case, e.g. "1/10 5 AM"
if (dps == DS.D_NN)
{
- if (!ProcessTerminaltState(DS.DX_NN, ref result, ref styles, ref raw, dtfi))
+ if (!ProcessTerminalState(DS.DX_NN, ref str, ref result, ref styles, ref raw, dtfi))
{
return false;
}
}
else
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
break;
}
if (dps == DS.T_NNt || dps == DS.T_Nt)
{
dtok.num = dtfi.Calendar.ToFourDigitYear(tokenValue);
}
- catch (ArgumentOutOfRangeException e)
+ catch (ArgumentOutOfRangeException)
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), e);
+ result.SetBadDateTimeFailure();
LexTraceExit("0075 (Calendar.ToFourDigitYear failed)", dps);
return false;
}
break;
default:
// Invalid separator after number number.
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
LexTraceExit("0080", dps);
return false;
}
goto default;
default:
// Invalid separator after number number.
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
LexTraceExit("0090", dps);
return false;
}
else
{
// Invalid separator after number number.
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
LexTraceExit("0100", dps);
return false;
}
break;
default:
// Invalid separator after number number.
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
LexTraceExit("0110", dps);
return false;
}
}
else
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
LexTraceExit("0120 (DayOfWeek seen more than 1x)", dps);
return false;
}
case TokenType.SEP_Time:
if (!raw.hasSameDateAndTimeSeparators)
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
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 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;
break;
default:
//Invalid separator after month name
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
LexTraceExit("0130 (Invalid separator after month name)", dps);
return false;
}
}
else
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
LexTraceExit("0140 (MonthToken seen more than 1x)", dps);
return false;
}
}
else
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
LexTraceExit("0150 (EraToken seen when result.era already set)", dps);
return false;
}
}
else
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
LexTraceExit("0160 (JapaneseEraToken seen when result.era already set)", dps);
return false;
}
}
else
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
LexTraceExit("0170 (TEraToken seen when result.era already set)", dps);
return false;
}
if ((result.flags & ParseFlags.TimeZoneUsed) != 0)
{
// Should not have two timezone offsets.
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
LexTraceExit("0180 (seen GMT or Z more than 1x)", dps);
return false;
}
}
else
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
LexTraceExit("0190 (AM/PM timeMark already set)", dps);
return false;
}
case TokenType.UnknownToken:
if (Char.IsLetter(str.m_current))
{
- result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_UnknowDateTimeWord), str.Index);
+ result.SetFailure(ParseFailureKind.FormatWithOriginalDateTimeAndParameter, nameof(SR.Format_UnknownDateTimeWord), str.Index);
LexTraceExit("0200", dps);
return (false);
}
return true;
}
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
LexTraceExit("0240", dps);
return false;
}
}
else if ((!Char.IsWhiteSpace(ch)))
{
- // Anthyhing other than whitespace outside hashes is invalid
+ // Anything other than whitespace outside hashes is invalid
if (!foundStart || foundEnd)
{
return false;
// The has was un-paired
return false;
}
- // Valid Hash usage: eat the hash and continue.
+ // Valid Hash usage: eat the hash and continue.
str.GetNext();
return true;
}
if ((result.flags & ParseFlags.HaveDate) != 0)
{
// Multiple dates in the input string
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
return true;
}
}
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
if ((result.flags & ParseFlags.HaveDate) != 0)
{
// Multiple dates in the input string
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
return true;
}
}
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
if ((result.flags & ParseFlags.HaveDate) != 0)
{
// Multiple dates in the input string
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
int year;
if (!TryAdjustYear(ref result, raw.GetNumber(0), out year) || !SetDateYMD(ref result, year, raw.month, 1))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
return true;
GetDefaultYear(ref result, ref styles);
if (!SetDateYMD(ref result, result.Year, raw.month, raw.GetNumber(0)))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
return true;
return true;
}
}
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
if ((result.flags & ParseFlags.HaveDate) != 0)
{
// Multiple dates in the input string
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
int year;
if (!TryAdjustYear(ref result, raw.GetNumber(0), out year) || !SetDateYMD(ref result, year, raw.month, 1))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
return true;
GetDefaultYear(ref result, ref styles);
if (!SetDateYMD(ref result, result.Year, raw.month, raw.GetNumber(0)))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
return true;
if ((result.flags & ParseFlags.HaveDate) != 0)
{
// Multiple dates in the input string
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
}
}
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
if ((result.flags & ParseFlags.HaveDate) != 0)
{
// Multiple dates in the input string
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
return true; // Year + MD
}
}
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
if ((result.flags & ParseFlags.HaveDate) != 0)
{
// Multiple dates in the input string
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
return true; // DM + Year
}
}
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
- private static Boolean GetDayOfYMN(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ private static Boolean GetDayOfYMN(ref DateTimeResult result, ref DateTimeRawInfo raw)
{
if ((result.flags & ParseFlags.HaveDate) != 0)
{
// Multiple dates in the input string
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
result.flags |= ParseFlags.HaveDate;
return true;
}
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
- private static Boolean GetDayOfYN(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ private static Boolean GetDayOfYN(ref DateTimeResult result, ref DateTimeRawInfo raw)
{
if ((result.flags & ParseFlags.HaveDate) != 0)
{
// Multiple dates in the input string
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
result.flags |= ParseFlags.HaveDate;
return true;
}
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
- private static Boolean GetDayOfYM(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ private static Boolean GetDayOfYM(ref DateTimeResult result, ref DateTimeRawInfo raw)
{
if ((result.flags & ParseFlags.HaveDate) != 0)
{
// Multiple dates in the input string
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
result.flags |= ParseFlags.HaveDate;
return true;
}
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
return true;
}
- private static Boolean GetTimeOfN(DateTimeFormatInfo dtfi, ref DateTimeResult result, ref DateTimeRawInfo raw)
+ private static Boolean GetTimeOfN(ref DateTimeResult result, ref DateTimeRawInfo raw)
{
if ((result.flags & ParseFlags.HaveTime) != 0)
{
// Multiple times in the input string
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
//
//
if (raw.timeMark == TM.NotSet)
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
result.Hour = raw.GetNumber(0);
return true;
}
- private static Boolean GetTimeOfNN(DateTimeFormatInfo dtfi, ref DateTimeResult result, ref DateTimeRawInfo raw)
+ private static Boolean GetTimeOfNN(ref DateTimeResult result, ref DateTimeRawInfo raw)
{
Debug.Assert(raw.numCount >= 2, "raw.numCount >= 2");
if ((result.flags & ParseFlags.HaveTime) != 0)
{
// Multiple times in the input string
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
return true;
}
- private static Boolean GetTimeOfNNN(DateTimeFormatInfo dtfi, ref DateTimeResult result, ref DateTimeRawInfo raw)
+ private static Boolean GetTimeOfNNN(ref DateTimeResult result, ref DateTimeRawInfo raw)
{
if ((result.flags & ParseFlags.HaveTime) != 0)
{
// Multiple times in the input string
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
Debug.Assert(raw.numCount >= 3, "raw.numCount >= 3");
{
if (raw.numCount != 1 || result.Day != -1)
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
result.Day = raw.GetNumber(0);
if (result.Month == -1)
{
//Should have a month suffix
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
if (result.Year != -1)
{
- // Aleady has a year suffix
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ // Already has a year suffix
+ result.SetBadDateTimeFailure();
return false;
}
if (!TryAdjustYear(ref result, raw.GetNumber(0), out result.Year))
{
// the year value is out of range
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
result.Day = 1;
}
}
}
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
//
////////////////////////////////////////////////////////////////////////
- internal static Boolean ProcessHebrewTerminalState(DS dps, ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ internal static Boolean ProcessHebrewTerminalState(DS dps, ref __DTString str, ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
{
// The following are accepted terminal state for Hebrew date.
switch (dps)
raw.year = raw.GetNumber(1);
if (!dtfi.YearMonthAdjustment(ref raw.year, ref raw.month, true))
{
- result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar), null);
+ result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar));
return false;
}
if (!GetDayOfMNN(ref result, ref raw, dtfi))
// 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, nameof(SR.Format_BadDateTimeCalendar), null);
+ result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar));
return false;
}
- if (!GetDayOfYMN(ref result, ref raw, dtfi))
+ if (!GetDayOfYMN(ref result, ref raw))
{
return false;
}
}
if (!dtfi.YearMonthAdjustment(ref result.Year, ref raw.month, true))
{
- result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar), null);
+ result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar));
return false;
}
break;
GetDefaultYear(ref result, ref styles);
if (!dtfi.YearMonthAdjustment(ref result.Year, ref raw.month, true))
{
- result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar), null);
+ result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar));
return false;
}
if (!GetHebrewDayOfNM(ref result, ref raw, dtfi))
// Deal with Year/Month pattern.
if (!dtfi.YearMonthAdjustment(ref raw.year, ref raw.month, true))
{
- result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar), null);
+ result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar));
return false;
}
- if (!GetDayOfYM(ref result, ref raw, dtfi))
+ if (!GetDayOfYM(ref result, ref raw))
{
return false;
}
break;
case DS.TX_N:
// Deal hour + AM/PM
- if (!GetTimeOfN(dtfi, ref result, ref raw))
+ if (!GetTimeOfN(ref result, ref raw))
{
return false;
}
break;
case DS.TX_NN:
- if (!GetTimeOfNN(dtfi, ref result, ref raw))
+ if (!GetTimeOfNN(ref result, ref raw))
{
return false;
}
break;
case DS.TX_NNN:
- if (!GetTimeOfNNN(dtfi, ref result, ref raw))
+ if (!GetTimeOfNNN(ref result, ref raw))
{
return false;
}
break;
default:
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
if (dps > DS.ERROR)
// 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)
+ internal static Boolean ProcessTerminalState(DS dps, ref __DTString str, ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
{
bool passed = true;
switch (dps)
passed = GetDayOfNNY(ref result, ref raw, dtfi);
break;
case DS.DX_YMN:
- passed = GetDayOfYMN(ref result, ref raw, dtfi);
+ passed = GetDayOfYMN(ref result, ref raw);
break;
case DS.DX_YN:
- passed = GetDayOfYN(ref result, ref raw, dtfi);
+ passed = GetDayOfYN(ref result, ref raw);
break;
case DS.DX_YM:
- passed = GetDayOfYM(ref result, ref raw, dtfi);
+ passed = GetDayOfYM(ref result, ref raw);
break;
case DS.TX_N:
- passed = GetTimeOfN(dtfi, ref result, ref raw);
+ passed = GetTimeOfN(ref result, ref raw);
break;
case DS.TX_NN:
- passed = GetTimeOfNN(dtfi, ref result, ref raw);
+ passed = GetTimeOfNN(ref result, ref raw);
break;
case DS.TX_NNN:
- passed = GetTimeOfNNN(dtfi, ref result, ref raw);
+ passed = GetTimeOfNNN(ref result, ref raw);
break;
case DS.TX_TS:
// The result has got the correct value. Nothing to do.
internal static DateTime Parse(ReadOnlySpan<char> s, DateTimeFormatInfo dtfi, DateTimeStyles styles)
{
DateTimeResult result = new DateTimeResult(); // The buffer to store the parsing result.
- result.Init();
+ result.Init(s);
if (TryParse(s, dtfi, styles, ref result))
{
return result.parsedDate;
internal static DateTime Parse(ReadOnlySpan<char> s, DateTimeFormatInfo dtfi, DateTimeStyles styles, out TimeSpan offset)
{
DateTimeResult result = new DateTimeResult(); // The buffer to store the parsing result.
- result.Init();
+ result.Init(s);
result.flags |= ParseFlags.CaptureOffset;
if (TryParse(s, dtfi, styles, ref result))
{
{
result = DateTime.MinValue;
DateTimeResult resultData = new DateTimeResult(); // The buffer to store the parsing result.
- resultData.Init();
+ resultData.Init(s);
if (TryParse(s, dtfi, styles, ref resultData))
{
result = resultData.parsedDate;
result = DateTime.MinValue;
offset = TimeSpan.Zero;
DateTimeResult parseResult = new DateTimeResult(); // The buffer to store the parsing result.
- parseResult.Init();
+ parseResult.Init(s);
parseResult.flags |= ParseFlags.CaptureOffset;
if (TryParse(s, dtfi, styles, ref parseResult))
{
{
if (s.Length == 0)
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_BadDateTime));
return false;
}
{
if (!ProcessDateTimeSuffix(ref result, ref raw, ref dtok))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
TPTraceExit("0010", dps);
return false;
}
}
else
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
TPTraceExit("0030", dps);
return false;
}
{
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
+ // 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)
{
{
switch (dtok.dtt)
{
- // we have the case of Serbia have dates in forms 'd.M.yyyy.' so we can expect '.' after the date parts.
+ // 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;
if (dps == DS.ERROR)
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
TPTraceExit("0040 (invalid state transition)", dps);
return false;
}
{
if ((dtfi.FormatFlags & DateTimeFormatFlags.UseHebrewRule) != 0)
{
- if (!ProcessHebrewTerminalState(dps, ref result, ref styles, ref raw, dtfi))
+ if (!ProcessHebrewTerminalState(dps, ref str, ref result, ref styles, ref raw, dtfi))
{
TPTraceExit("0050 (ProcessHebrewTerminalState)", dps);
return false;
}
else
{
- if (!ProcessTerminaltState(dps, ref result, ref styles, ref raw, dtfi))
+ if (!ProcessTerminalState(dps, ref str, ref result, ref styles, ref raw, dtfi))
{
TPTraceExit("0060 (ProcessTerminaltState)", dps);
return false;
if (!reachTerminalState)
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
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, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
TPTraceExit("0080 (AdjustHour)", 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, nameof(SR.Format_BadDateTimeCalendar), null);
+ result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar));
TPTraceExit("0100 (result.calendar.TryToDateTime)", dps);
return false;
}
//
// 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.
+ // Otherwise, the value of day of week may change after adjusting to the time zone.
//
if (raw.dayOfWeek != -1)
{
//
if (raw.dayOfWeek != (int)result.calendar.GetDayOfWeek(time))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDayOfWeek), null);
+ result.SetFailure(ParseFailureKind.FormatWithOriginalDateTime, nameof(SR.Format_BadDayOfWeek));
TPTraceExit("0110 (dayOfWeek check)", dps);
return false;
}
result.parsedDate = time;
- if (!DetermineTimeZoneAdjustments(ref result, styles, bTimeOnly))
+ if (!DetermineTimeZoneAdjustments(ref str, ref result, styles, bTimeOnly))
{
TPTraceExit("0120 (DetermineTimeZoneAdjustments)", dps);
return false;
// Handles time zone adjustments and sets DateTimeKind values as required by the styles
- private static Boolean DetermineTimeZoneAdjustments(ref DateTimeResult result, DateTimeStyles styles, Boolean bTimeOnly)
+ private static Boolean DetermineTimeZoneAdjustments(ref __DTString str, ref DateTimeResult result, DateTimeStyles styles, Boolean bTimeOnly)
{
if ((result.flags & ParseFlags.CaptureOffset) != 0)
{
- // This is a DateTimeOffset parse, so the offset will actually be captured directly, and
+ // This is a DateTimeOffset parse, so the offset will actually be captured directly, and
// no adjustment is required in most cases
- return DateTimeOffsetTimeZonePostProcessing(ref result, styles);
+ return DateTimeOffsetTimeZonePostProcessing(ref str, ref result, styles);
}
else
{
// the DateTime offset must be within +- 14:00 hours.
if (offsetTicks < DateTimeOffset.MinOffset || offsetTicks > DateTimeOffset.MaxOffset)
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_OffsetOutOfRange), null);
+ result.SetFailure(ParseFailureKind.FormatWithOriginalDateTime, nameof(SR.Format_OffsetOutOfRange));
return false;
}
}
}
// Apply validation and adjustments specific to DateTimeOffset
- private static Boolean DateTimeOffsetTimeZonePostProcessing(ref DateTimeResult result, DateTimeStyles styles)
+ private static Boolean DateTimeOffsetTimeZonePostProcessing(ref __DTString str, ref DateTimeResult result, DateTimeStyles styles)
{
- // For DateTimeOffset, default to the Utc or Local offset when an offset was not specified by
+ // For DateTimeOffset, default to the Utc or Local offset when an offset was not specified by
// the input string.
if ((result.flags & ParseFlags.TimeZoneUsed) == 0)
{
Int64 utcTicks = result.parsedDate.Ticks - offsetTicks;
// For DateTimeOffset, both the parsed time and the corresponding UTC value must be within the boundaries
- // of a DateTime instance.
+ // of a DateTime instance.
if (utcTicks < DateTime.MinTicks || utcTicks > DateTime.MaxTicks)
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_UTCOutOfRange), null);
+ result.SetFailure(ParseFailureKind.FormatWithOriginalDateTime, nameof(SR.Format_UTCOutOfRange));
return false;
}
// the offset must be within +- 14:00 hours.
if (offsetTicks < DateTimeOffset.MinOffset || offsetTicks > DateTimeOffset.MaxOffset)
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_OffsetOutOfRange), null);
+ result.SetFailure(ParseFailureKind.FormatWithOriginalDateTime, nameof(SR.Format_OffsetOutOfRange));
return false;
}
}
// The constructor should always succeed because of the range check earlier in the function
- // Althought it is UTC, internally DateTimeOffset does not use this flag
+ // Although it is UTC, internally DateTimeOffset does not use this flag
result.parsedDate = new DateTime(utcTicks, DateTimeKind.Utc);
result.timeZoneOffset = TimeSpan.Zero;
}
if (resultTicks < DateTime.MinTicks || resultTicks > DateTime.MaxTicks)
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_DateOutOfRange), null);
+ result.SetFailure(ParseFailureKind.FormatWithOriginalDateTime, nameof(SR.Format_DateOutOfRange));
return false;
}
result.parsedDate = new DateTime(resultTicks, DateTimeKind.Utc);
if (resultTicks < DateTime.MinTicks || resultTicks > DateTime.MaxTicks)
{
result.parsedDate = DateTime.MinValue;
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_DateOutOfRange), null);
+ result.SetFailure(ParseFailureKind.FormatWithOriginalDateTime, nameof(SR.Format_DateOutOfRange));
return false;
}
result.parsedDate = new DateTime(resultTicks, DateTimeKind.Local, isAmbiguousLocalDst);
str.SkipWhiteSpaces();
if (!ParseDigits(ref str, 2, out hour))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
str.SkipWhiteSpaces();
if (!str.Match(':'))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
str.SkipWhiteSpaces();
if (!ParseDigits(ref str, 2, out minute))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
str.SkipWhiteSpaces();
str.SkipWhiteSpaces();
if (!ParseDigits(ref str, 2, out second))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
if (str.Match('.'))
{
if (!ParseFraction(ref str, out partSecond))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
str.Index--;
result.flags |= ParseFlags.TimeZoneUsed;
if (!ParseTimeZone(ref str, ref result.timeZoneOffset))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
}
{
if (!VerifyValidPunctuation(ref str))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
str.SkipWhiteSpaces();
{
if (!VerifyValidPunctuation(ref str))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
}
if (str.GetNext())
{
// If this is true, there were non-white space characters remaining in the DateTime
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
}
if (!calendar.TryToDateTime(raw.year, raw.GetNumber(0), raw.GetNumber(1),
hour, minute, second, 0, result.era, out time))
{
- result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar), null);
+ result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar));
return false;
}
time = time.AddTicks((long)Math.Round(partSecond * Calendar.TicksPerSecond));
result.parsedDate = time;
- if (!DetermineTimeZoneAdjustments(ref result, styles, false))
+ if (!DetermineTimeZoneAdjustments(ref str, ref result, styles, false))
{
return false;
}
// change the code below.
if (str.GetNext())
{
- if (str.GetChar() == dtfi.AMDesignator[0])
+ string amDesignator = dtfi.AMDesignator;
+ if (amDesignator.Length > 0 && str.GetChar() == amDesignator[0])
{
result = TM.AM;
- return (true);
+ return true;
}
- if (str.GetChar() == dtfi.PMDesignator[0])
+
+ string pmDesignator = dtfi.PMDesignator;
+ if (pmDesignator.Length > 0 && str.GetChar() == pmDesignator[0])
{
result = TM.PM;
- return (true);
+ return true;
}
}
return false;
}
}
- // assume the offset is Local
+ // assume the offset is Local
return DateTime.Now;
}
if (((result.Month != -1) || (result.Day != -1))
&& ((result.Year == -1 || ((result.flags & ParseFlags.YearDefault) != 0)) && (result.flags & ParseFlags.TimeZoneUsed) != 0))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_MissingIncompleteDate), null);
+ result.SetFailure(ParseFailureKind.FormatWithOriginalDateTime, nameof(SR.Format_MissingIncompleteDate));
return false;
}
}
// This method also set the dtfi according/parseInfo to some special pre-defined
// formats.
//
- private static String ExpandPredefinedFormat(String format, ref DateTimeFormatInfo dtfi, ref ParsingInfo parseInfo, ref DateTimeResult result)
+ private static String ExpandPredefinedFormat(ReadOnlySpan<char> format, ref DateTimeFormatInfo dtfi, ref ParsingInfo parseInfo, ref DateTimeResult result)
{
//
// Check the format to see if we need to override the dtfi to be InvariantInfo,
}
if (!parseResult)
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return (false);
}
if (!CheckNewValue(ref result.Year, tempYear, ch, ref result))
if (!parseInfo.fCustomNumberParser ||
!parseInfo.parseNumberDelegate(ref str, tokenLen, out tempMonth))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return (false);
}
}
{
if (!MatchAbbreviatedMonthName(ref str, dtfi, ref tempMonth))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return (false);
}
}
{
if (!MatchMonthName(ref str, dtfi, ref tempMonth))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return (false);
}
}
if (!parseInfo.fCustomNumberParser ||
!parseInfo.parseNumberDelegate(ref str, tokenLen, out tempDay))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return (false);
}
}
// "ddd"
if (!MatchAbbreviatedDayName(ref str, dtfi, ref tempDayOfWeek))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return (false);
}
}
// "dddd*"
if (!MatchDayName(ref str, dtfi, ref tempDayOfWeek))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return (false);
}
}
// Put the era value in result.era.
if (!MatchEraName(ref str, dtfi, ref result.era))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return (false);
}
break;
tokenLen = format.GetRepeatCount();
if (!ParseDigits(ref str, (tokenLen < 2 ? 1 : 2), out tempHour))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return (false);
}
if (!CheckNewValue(ref result.Hour, tempHour, ch, ref result))
tokenLen = format.GetRepeatCount();
if (!ParseDigits(ref str, (tokenLen < 2 ? 1 : 2), out tempHour))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return (false);
}
if (!CheckNewValue(ref result.Hour, tempHour, ch, ref result))
tokenLen = format.GetRepeatCount();
if (!ParseDigits(ref str, (tokenLen < 2 ? 1 : 2), out tempMinute))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return (false);
}
if (!CheckNewValue(ref result.Minute, tempMinute, ch, ref result))
tokenLen = format.GetRepeatCount();
if (!ParseDigits(ref str, (tokenLen < 2 ? 1 : 2), out tempSecond))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return (false);
}
if (!CheckNewValue(ref result.Second, tempSecond, ch, ref result))
{
if (ch == 'f')
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return (false);
}
}
}
else
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return (false);
}
break;
{
if (!MatchAbbreviatedTimeMark(ref str, dtfi, ref tempTimeMark))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return (false);
}
}
{
if (!MatchTimeMark(ref str, dtfi, ref tempTimeMark))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return (false);
}
}
TimeSpan tempTimeZoneOffset = new TimeSpan(0);
if (!ParseTimeZoneOffset(ref str, tokenLen, ref tempTimeZoneOffset))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return (false);
}
if ((result.flags & ParseFlags.TimeZoneUsed) != 0 && tempTimeZoneOffset != result.timeZoneOffset)
str.Index++;
if (!GetTimeZoneName(ref str))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
str.Index--;
TimeSpan tempTimeZoneOffset = new TimeSpan(0);
if (!ParseTimeZoneOffset(ref str, 3, ref tempTimeZoneOffset))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return (false);
}
if ((result.flags & ParseFlags.TimeZoneUsed) != 0 && tempTimeZoneOffset != result.timeZoneOffset)
!str.Match(dtfi.TimeSeparator))
{
// A time separator is expected.
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
break;
!str.Match(dtfi.DateSeparator))
{
// A date separator is expected.
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
break;
else if (!str.Match(quotedStr[i]))
{
// Can not find the matching quoted string.
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
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
+ // 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)
// 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, nameof(SR.Format_BadFormatSpecifier), null);
+ result.SetBadFormatSpecifierFailure(format.Value);
return false;
}
break;
if (!str.Match(format.GetChar()))
{
// Can not find a match for the escaped character.
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
}
else
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadFormatSpecifier), null);
+ result.SetBadFormatSpecifierFailure(format.Value);
return false;
}
break;
break;
}
}
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
break;
}
}
}
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
// Found a macth.
result.timeZoneOffset = TimeSpan.Zero;
if (!str.Match(GMTName))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
}
else if (!str.Match(ch))
{
// ch is expected.
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
}
private static bool DoStrictParse(
ReadOnlySpan<char> s,
- String formatParam,
+ ReadOnlySpan<char> formatParam,
DateTimeStyles styles,
DateTimeFormatInfo dtfi,
ref DateTimeResult result)
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, nameof(SR.Format_BadFormatSpecifier), null);
+ result.SetBadFormatSpecifierFailure(formatParam);
return false;
}
formatParam = ExpandPredefinedFormat(formatParam, ref dtfi, ref parseInfo, ref result);
// if we have parsed every item twice.
result.Hour = result.Minute = result.Second = -1;
- __DTString format = new __DTString(formatParam.AsReadOnlySpan(), dtfi, false);
+ __DTString format = new __DTString(formatParam, dtfi, false);
__DTString str = new __DTString(s, dtfi, false);
if (parseInfo.fAllowTrailingWhite)
if (str.Index < str.Value.Length - 1)
{
// There are still remaining character in str.
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
// A two digit year value is expected. Check if the parsed year value is valid.
if (result.Year >= 100)
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
try
{
result.Year = parseInfo.calendar.ToFourDigitYear(result.Year);
}
- catch (ArgumentOutOfRangeException e)
+ catch (ArgumentOutOfRangeException)
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), e);
+ result.SetBadDateTimeFailure();
return false;
}
}
if (result.Hour > 12)
{
// AM/PM is used, but the value for HH is too big.
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
if (parseInfo.timeMark == TM.AM)
if ((parseInfo.timeMark == TM.AM && result.Hour >= 12)
|| (parseInfo.timeMark == TM.PM && result.Hour < 12))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDateTime), null);
+ result.SetBadDateTimeFailure();
return false;
}
}
{
if (!dtfi.YearMonthAdjustment(ref result.Year, ref result.Month, ((result.flags & ParseFlags.ParsedMonthName) != 0)))
{
- result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar), null);
+ result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar));
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, nameof(SR.Format_BadDateTimeCalendar), null);
+ result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar));
return false;
}
if (result.fraction > 0)
//
if (parseInfo.dayOfWeek != (int)parseInfo.calendar.GetDayOfWeek(result.parsedDate))
{
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadDayOfWeek), null);
+ result.SetFailure(ParseFailureKind.FormatWithOriginalDateTime, nameof(SR.Format_BadDayOfWeek));
return false;
}
}
- if (!DetermineTimeZoneAdjustments(ref result, styles, bTimeOnly))
+ if (!DetermineTimeZoneAdjustments(ref str, ref result, styles, bTimeOnly))
{
return false;
}
case ParseFailureKind.FormatWithParameter:
return new FormatException(SR.Format(SR.GetResourceString(result.failureMessageID), result.failureMessageFormatArgument));
case ParseFailureKind.FormatBadDateTimeCalendar:
- return new FormatException(SR.Format(SR.GetResourceString(result.failureMessageID), result.calendar));
+ return new FormatException(SR.Format(SR.GetResourceString(result.failureMessageID), new string(result.originalDateTimeString), result.calendar));
+ case ParseFailureKind.FormatWithOriginalDateTime:
+ return new FormatException(SR.Format(SR.GetResourceString(result.failureMessageID), new string(result.originalDateTimeString)));
+ case ParseFailureKind.FormatWithFormatSpecifier:
+ return new FormatException(SR.Format(SR.GetResourceString(result.failureMessageID), new string(result.failedFormatSpecifier)));
+ case ParseFailureKind.FormatWithOriginalDateTimeAndParameter:
+ return new FormatException(SR.Format(SR.GetResourceString(result.failureMessageID), new string(result.originalDateTimeString), result.failureMessageFormatArgument));
default:
- Debug.Fail("Unkown DateTimeParseFailure: " + result);
+ Debug.Fail("Unknown DateTimeParseFailure: " + result.failure.ToString());
return null;
}
}
- // 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
[Conditional("_LOGGING")]
- internal static void LexTraceExit(string message, DS dps)
+ private static void LexTraceExit(string message, DS dps)
{
#if _LOGGING
if (!_tracingEnabled)
return;
- BCLDebug.Trace("DATETIME", "[DATETIME] Lex return {0}, DS.{1}", message, dps);
+ Trace($"Lex return {message}, DS.{dps}");
#endif // _LOGGING
}
[Conditional("_LOGGING")]
- internal static void PTSTraceExit(DS dps, bool passed)
+ private static void PTSTraceExit(DS dps, bool passed)
{
#if _LOGGING
if (!_tracingEnabled)
return;
- BCLDebug.Trace("DATETIME", "[DATETIME] ProcessTerminalState {0} @ DS.{1}", passed ? "passed" : "failed", dps);
+ Trace($"ProcessTerminalState {(passed ? "passed" : "failed")} @ DS.{dps}");
#endif // _LOGGING
}
[Conditional("_LOGGING")]
- internal static void TPTraceExit(string message, DS dps)
+ private static void TPTraceExit(string message, DS dps)
{
#if _LOGGING
if (!_tracingEnabled)
return;
- BCLDebug.Trace("DATETIME", "[DATETIME] TryParse return {0}, DS.{1}", message, dps);
+ Trace($"TryParse return {message}, DS.{dps}");
#endif // _LOGGING
}
[Conditional("_LOGGING")]
- internal static void DTFITrace(DateTimeFormatInfo dtfi)
+ private static void DTFITrace(DateTimeFormatInfo dtfi)
{
#if _LOGGING
if (!_tracingEnabled)
return;
- BCLDebug.Trace("DATETIME", "[DATETIME] DateTimeFormatInfo Properties");
+ Trace("DateTimeFormatInfo Properties");
#if !FEATURE_COREFX_GLOBALIZATION
- BCLDebug.Trace("DATETIME", " NativeCalendarName {0}", Hex(dtfi.NativeCalendarName));
+ Trace($" NativeCalendarName {Hex(dtfi.NativeCalendarName)}");
#endif
- BCLDebug.Trace("DATETIME", " AMDesignator {0}", Hex(dtfi.AMDesignator));
- BCLDebug.Trace("DATETIME", " PMDesignator {0}", Hex(dtfi.PMDesignator));
- BCLDebug.Trace("DATETIME", " TimeSeparator {0}", Hex(dtfi.TimeSeparator));
- BCLDebug.Trace("DATETIME", " AbbrvDayNames {0}", Hex(dtfi.AbbreviatedDayNames));
- BCLDebug.Trace("DATETIME", " ShortestDayNames {0}", Hex(dtfi.ShortestDayNames));
- BCLDebug.Trace("DATETIME", " DayNames {0}", Hex(dtfi.DayNames));
- BCLDebug.Trace("DATETIME", " AbbrvMonthNames {0}", Hex(dtfi.AbbreviatedMonthNames));
- BCLDebug.Trace("DATETIME", " MonthNames {0}", Hex(dtfi.MonthNames));
- BCLDebug.Trace("DATETIME", " AbbrvMonthGenNames {0}", Hex(dtfi.AbbreviatedMonthGenitiveNames));
- BCLDebug.Trace("DATETIME", " MonthGenNames {0}", Hex(dtfi.MonthGenitiveNames));
+ Trace($" AMDesignator {Hex(dtfi.AMDesignator)}");
+ Trace($" PMDesignator {Hex(dtfi.PMDesignator)}");
+ Trace($" TimeSeparator {Hex(dtfi.TimeSeparator)}");
+ Trace($" AbbrvDayNames {Hex(dtfi.AbbreviatedDayNames)}");
+ Trace($" ShortestDayNames {Hex(dtfi.ShortestDayNames)}");
+ Trace($" DayNames {Hex(dtfi.DayNames)}");
+ Trace($" AbbrvMonthNames {Hex(dtfi.AbbreviatedMonthNames)}");
+ Trace($" MonthNames {Hex(dtfi.MonthNames)}");
+ Trace($" AbbrvMonthGenNames {Hex(dtfi.AbbreviatedMonthGenitiveNames)}");
+ Trace($" MonthGenNames {Hex(dtfi.MonthGenitiveNames)}");
#endif // _LOGGING
}
#if _LOGGING
// return a string in the form: "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
- internal static string Hex(string[] strs)
+ private static string Hex(string[] strs)
{
if (strs == null || strs.Length == 0)
return String.Empty;
return buffer.ToString();
}
// return a string in the form: "Sun"
- internal static string Hex(string str) => Hex(str.AsReadOnlySpan());
- internal static string Hex(ReadOnlySpan<char> str)
+ private static string Hex(string str) => Hex((ReadOnlySpan<char>)str);
+ private static string Hex(ReadOnlySpan<char> str)
{
StringBuilder buffer = new StringBuilder();
buffer.Append("\"");
return buffer.ToString();
}
// return an unicode escaped string form of char c
- internal static String Hex(char c)
+ private static String Hex(char c)
{
if (c <= '\x007f')
return c.ToString(CultureInfo.InvariantCulture);
return "\\u" + ((int)c).ToString("x4", CultureInfo.InvariantCulture);
}
- internal static bool _tracingEnabled = BCLDebug.CheckEnabled("DATETIME");
+ private static void Trace(string s)
+ {
+ // Internal.Console.WriteLine(s);
+ }
+
+ private static bool _tracingEnabled = false;
#endif // _LOGGING
}
{
return false;
}
- if (m_info.Compare(Value.Slice(thisPosition, segmentLength), target.AsReadOnlySpan().Slice(targetPosition, segmentLength), CompareOptions.IgnoreCase) != 0)
+ if (m_info.CompareOptionIgnoreCase(Value.Slice(thisPosition, segmentLength), target.AsSpan(targetPosition, segmentLength)) != 0)
{
return false;
}
{
return false;
}
- if (m_info.Compare(Value.Slice(thisPosition, segmentLength), target.AsReadOnlySpan().Slice(targetPosition, segmentLength), CompareOptions.IgnoreCase) != 0)
+ if (m_info.CompareOptionIgnoreCase(Value.Slice(thisPosition, segmentLength), target.AsSpan(targetPosition, segmentLength)) != 0)
{
return false;
}
// Check if the last character is a quote.
if (ch == '\'' || ch == '\"')
{
- if (Char.IsWhiteSpace(Value[i - 1]))
+ if (char.IsWhiteSpace(Value[i - 1]))
{
i--;
- while (i >= 1 && Char.IsWhiteSpace(Value[i - 1]))
+ while (i >= 1 && char.IsWhiteSpace(Value[i - 1]))
{
i--;
}
- Value = Value.Remove(i, Value.Length - 1 - i);
+ Span<char> result = new char[i + 1];
+ result[i] = ch;
+ Value.Slice(0, i).CopyTo(result);
+ Value = result;
}
}
}
// Check if the last character is a quote.
if (ch == '\'' || ch == '\"')
{
- while ((i + 1) < Length && Char.IsWhiteSpace(Value[i + 1]))
+ while ((i + 1) < Length && char.IsWhiteSpace(Value[i + 1]))
{
i++;
}
if (i != 0)
{
- Value = Value.Remove(1, i);
+ Span<char> result = new char[Value.Length - i];
+ result[0] = ch;
+ Value.Slice(i + 1).CopyTo(result.Slice(1));
+ Value = result;
}
}
}
ArgumentNull = 1,
Format = 2,
FormatWithParameter = 3,
- FormatBadDateTimeCalendar = 4, // FormatException when ArgumentOutOfRange is thrown by a Calendar.TryToDateTime().
+ FormatWithOriginalDateTime = 4,
+ FormatWithFormatSpecifier = 5,
+ FormatWithOriginalDateTimeAndParameter = 6,
+ FormatBadDateTimeCalendar = 7, // FormatException when ArgumentOutOfRange is thrown by a Calendar.TryToDateTime().
};
[Flags]
// used to construct a DateTime instance.
//
internal
- struct DateTimeResult
+ ref struct DateTimeResult
{
internal int Year;
internal int Month;
internal string failureMessageID;
internal object failureMessageFormatArgument;
internal string failureArgumentName;
+ internal ReadOnlySpan<char> originalDateTimeString;
+ internal ReadOnlySpan<char> failedFormatSpecifier;
- internal void Init()
+ internal void Init(ReadOnlySpan<char> originalDateTimeString)
{
+ this.originalDateTimeString = originalDateTimeString;
Year = -1;
Month = -1;
Day = -1;
Month = month;
Day = day;
}
+
+ internal void SetBadFormatSpecifierFailure()
+ {
+ SetBadFormatSpecifierFailure(ReadOnlySpan<char>.Empty);
+ }
+
+ internal void SetBadFormatSpecifierFailure(ReadOnlySpan<char> failedFormatSpecifier)
+ {
+ this.failure = ParseFailureKind.FormatWithFormatSpecifier;
+ this.failureMessageID = nameof(SR.Format_BadFormatSpecifier);
+ this.failedFormatSpecifier = failedFormatSpecifier;
+ }
+
+ internal void SetBadDateTimeFailure()
+ {
+ this.failure = ParseFailureKind.FormatWithOriginalDateTime;
+ this.failureMessageID = nameof(SR.Format_BadDateTime);
+ this.failureMessageFormatArgument = null;
+ }
+
+ internal void SetFailure(ParseFailureKind failure, string failureMessageID)
+ {
+ this.failure = failure;
+ this.failureMessageID = failureMessageID;
+ this.failureMessageFormatArgument = null;
+ }
+
internal void SetFailure(ParseFailureKind failure, string failureMessageID, object failureMessageFormatArgument)
{
this.failure = failure;