Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/System.Private.CoreLib/shared/System/Globalization/DateTimeParse.cs')
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/DateTimeParse.cs690
1 files changed, 558 insertions, 132 deletions
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/DateTimeParse.cs b/src/System.Private.CoreLib/shared/System/Globalization/DateTimeParse.cs
index 5b285eb5d..8d703ea98 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/DateTimeParse.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/DateTimeParse.cs
@@ -11,7 +11,7 @@ namespace System
{
internal static class DateTimeParse
{
- internal const Int32 MaxDateTimeNumberDigits = 8;
+ internal const int MaxDateTimeNumberDigits = 8;
internal delegate bool MatchNumberDelegate(ref __DTString str, int digitLen, out int result);
@@ -96,7 +96,7 @@ namespace System
return DoStrictParse(s, format, style, dtfi, ref result);
}
- internal static DateTime ParseExactMultiple(ReadOnlySpan<char> s, String[] formats,
+ internal static DateTime ParseExactMultiple(ReadOnlySpan<char> s, string[] formats,
DateTimeFormatInfo dtfi, DateTimeStyles style)
{
DateTimeResult result = new DateTimeResult(); // The buffer to store the parsing result.
@@ -112,7 +112,7 @@ namespace System
}
- internal static DateTime ParseExactMultiple(ReadOnlySpan<char> s, String[] formats,
+ internal static DateTime ParseExactMultiple(ReadOnlySpan<char> s, string[] formats,
DateTimeFormatInfo dtfi, DateTimeStyles style, out TimeSpan offset)
{
DateTimeResult result = new DateTimeResult(); // The buffer to store the parsing result.
@@ -130,7 +130,7 @@ namespace System
}
}
- internal static bool TryParseExactMultiple(ReadOnlySpan<char> s, String[] formats,
+ internal static bool TryParseExactMultiple(ReadOnlySpan<char> s, string[] formats,
DateTimeFormatInfo dtfi, DateTimeStyles style, out DateTime result, out TimeSpan offset)
{
result = DateTime.MinValue;
@@ -148,7 +148,7 @@ namespace System
}
- internal static bool TryParseExactMultiple(ReadOnlySpan<char> s, String[] formats,
+ internal static bool TryParseExactMultiple(ReadOnlySpan<char> s, string[] formats,
DateTimeFormatInfo dtfi, DateTimeStyles style, out DateTime result)
{
result = DateTime.MinValue;
@@ -162,7 +162,7 @@ namespace System
return false;
}
- internal static bool TryParseExactMultiple(ReadOnlySpan<char> s, String[] formats,
+ internal static bool TryParseExactMultiple(ReadOnlySpan<char> s, string[] formats,
DateTimeFormatInfo dtfi, DateTimeStyles style, ref DateTimeResult result)
{
if (formats == null)
@@ -331,7 +331,7 @@ namespace System
//
////////////////////////////////////////////////////////////////////////////
- // 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},
@@ -395,13 +395,13 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
};
// End NumEnd NumAmPm NumSpace NumDaySep NumTimesep MonthEnd MonthSpace MonthDSep NumDateSuff NumTimeSuff DayOfWeek YearSpace YearDateSep YearEnd TimeZone Era UTCMark
- internal const String GMTName = "GMT";
- internal const String ZuluName = "Z";
+ internal const string GMTName = "GMT";
+ internal const string ZuluName = "Z";
//
// Search from the index of str at str.Index to see if the target string exists in the str.
//
- private static bool MatchWord(ref __DTString str, String target)
+ private static bool MatchWord(ref __DTString str, string target)
{
if (target.Length > (str.Value.Length - str.Index))
{
@@ -418,7 +418,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if (nextCharIndex < str.Value.Length)
{
char nextCh = str.Value[nextCharIndex];
- if (Char.IsLetter(nextCh))
+ if (char.IsLetter(nextCh))
{
return (false);
}
@@ -573,7 +573,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
char nextCh = str.Value[str.Index];
// Skip whitespace, but don't update the index unless we find a time zone marker
int whitespaceCount = 0;
- while (Char.IsWhiteSpace(nextCh) && str.Index + whitespaceCount < str.Length - 1)
+ while (char.IsWhiteSpace(nextCh) && str.Index + whitespaceCount < str.Length - 1)
{
whitespaceCount++;
nextCh = str.Value[str.Index + whitespaceCount];
@@ -602,7 +602,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// This is the lexer. Check the character at the current index, and put the found token in dtok and
// some raw date/time information in raw.
//
- private static Boolean Lex(DS dps, ref __DTString str, ref DateTimeToken dtok, ref DateTimeRawInfo raw, ref DateTimeResult result, ref DateTimeFormatInfo dtfi, DateTimeStyles styles)
+ private static bool Lex(DS dps, ref __DTString str, ref DateTimeToken dtok, ref DateTimeRawInfo raw, ref DateTimeResult result, ref DateTimeFormatInfo dtfi, DateTimeStyles styles)
{
TokenType tokenType;
int tokenValue;
@@ -713,7 +713,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
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;
@@ -1002,7 +1002,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
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;
@@ -1119,7 +1119,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
break;
case TokenType.UnknownToken:
- if (Char.IsLetter(str.m_current))
+ if (char.IsLetter(str.m_current))
{
result.SetFailure(ParseFailureKind.FormatWithOriginalDateTimeAndParameter, nameof(SR.Format_UnknownDateTimeWord), str.Index);
LexTraceExit("0200", dps);
@@ -1128,7 +1128,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if ((str.m_current == '-' || str.m_current == '+') && ((result.flags & ParseFlags.TimeZoneUsed) == 0))
{
- Int32 originalIndex = str.Index;
+ int originalIndex = str.Index;
if (ParseTimeZone(ref str, ref result.timeZoneOffset))
{
result.flags |= ParseFlags.TimeZoneUsed;
@@ -1160,10 +1160,10 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return true;
}
- private static Boolean VerifyValidPunctuation(ref __DTString str)
+ private static bool VerifyValidPunctuation(ref __DTString str)
{
// Compatability Behavior. Allow trailing nulls and surrounding hashes
- Char ch = str.Value[str.Index];
+ char ch = str.Value[str.Index];
if (ch == '#')
{
bool foundStart = false;
@@ -1198,7 +1198,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return false;
}
}
- else if ((!Char.IsWhiteSpace(ch)))
+ else if ((!char.IsWhiteSpace(ch)))
{
// Anything other than whitespace outside hashes is invalid
if (!foundStart || foundEnd)
@@ -1212,7 +1212,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// 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;
}
@@ -1247,7 +1247,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
//
// Return 0 for YMD, 1 for MDY, 2 for DMY, otherwise -1.
//
- private static Boolean GetYearMonthDayOrder(String datePattern, DateTimeFormatInfo dtfi, out int order)
+ private static bool GetYearMonthDayOrder(string datePattern, DateTimeFormatInfo dtfi, out int order)
{
int yearOrder = -1;
int monthOrder = -1;
@@ -1345,7 +1345,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
//
// Return 0 for YM, 1 for MY, otherwise -1.
//
- private static Boolean GetYearMonthOrder(String pattern, DateTimeFormatInfo dtfi, out int order)
+ private static bool GetYearMonthOrder(string pattern, DateTimeFormatInfo dtfi, out int order)
{
int yearOrder = -1;
int monthOrder = -1;
@@ -1411,7 +1411,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
//
// Return 0 for MD, 1 for DM, otherwise -1.
//
- private static Boolean GetMonthDayOrder(String pattern, DateTimeFormatInfo dtfi, out int order)
+ private static bool GetMonthDayOrder(string pattern, DateTimeFormatInfo dtfi, out int order)
{
int monthOrder = -1;
int dayOrder = -1;
@@ -1539,7 +1539,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
// Processing teriminal case: DS.DX_NN
- private static Boolean GetDayOfNN(ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ private static bool GetDayOfNN(ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
{
if ((result.flags & ParseFlags.HaveDate) != 0)
{
@@ -1582,7 +1582,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
// Processing teriminal case: DS.DX_NNN
- private static Boolean GetDayOfNNN(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ private static bool GetDayOfNNN(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
{
if ((result.flags & ParseFlags.HaveDate) != 0)
{
@@ -1639,7 +1639,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return false;
}
- private static Boolean GetDayOfMN(ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ private static bool GetDayOfMN(ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
{
if ((result.flags & ParseFlags.HaveDate) != 0)
{
@@ -1701,7 +1701,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
//
////////////////////////////////////////////////////////////////////////
- private static Boolean GetHebrewDayOfNM(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ private static bool GetHebrewDayOfNM(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
{
int monthDayOrder;
if (!GetMonthDayOrder(dtfi.MonthDayPattern, dtfi, out monthDayOrder))
@@ -1722,7 +1722,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return false;
}
- private static Boolean GetDayOfNM(ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ private static bool GetDayOfNM(ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
{
if ((result.flags & ParseFlags.HaveDate) != 0)
{
@@ -1778,7 +1778,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return true;
}
- private static Boolean GetDayOfMNN(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ private static bool GetDayOfMNN(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
{
if ((result.flags & ParseFlags.HaveDate) != 0)
{
@@ -1848,7 +1848,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return false;
}
- private static Boolean GetDayOfYNN(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ private static bool GetDayOfYNN(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
{
if ((result.flags & ParseFlags.HaveDate) != 0)
{
@@ -1859,7 +1859,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
int n1 = raw.GetNumber(0);
int n2 = raw.GetNumber(1);
- String pattern = dtfi.ShortDatePattern;
+ string pattern = dtfi.ShortDatePattern;
// For compatibility, don't throw if we can't determine the order, but default to YMD instead
int order;
@@ -1883,7 +1883,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return false;
}
- private static Boolean GetDayOfNNY(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ private static bool GetDayOfNNY(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
{
if ((result.flags & ParseFlags.HaveDate) != 0)
{
@@ -1923,7 +1923,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
- private static Boolean GetDayOfYMN(ref DateTimeResult result, ref DateTimeRawInfo raw)
+ private static bool GetDayOfYMN(ref DateTimeResult result, ref DateTimeRawInfo raw)
{
if ((result.flags & ParseFlags.HaveDate) != 0)
{
@@ -1941,7 +1941,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return false;
}
- private static Boolean GetDayOfYN(ref DateTimeResult result, ref DateTimeRawInfo raw)
+ private static bool GetDayOfYN(ref DateTimeResult result, ref DateTimeRawInfo raw)
{
if ((result.flags & ParseFlags.HaveDate) != 0)
{
@@ -1959,7 +1959,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return false;
}
- private static Boolean GetDayOfYM(ref DateTimeResult result, ref DateTimeRawInfo raw)
+ private static bool GetDayOfYM(ref DateTimeResult result, ref DateTimeRawInfo raw)
{
if ((result.flags & ParseFlags.HaveDate) != 0)
{
@@ -2004,7 +2004,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
//
// Adjust hour according to the time mark.
//
- private static Boolean AdjustHour(ref int hour, TM timeMark)
+ private static bool AdjustHour(ref int hour, TM timeMark)
{
if (timeMark != TM.NotSet)
{
@@ -2031,7 +2031,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return true;
}
- private static Boolean GetTimeOfN(ref DateTimeResult result, ref DateTimeRawInfo raw)
+ private static bool GetTimeOfN(ref DateTimeResult result, ref DateTimeRawInfo raw)
{
if ((result.flags & ParseFlags.HaveTime) != 0)
{
@@ -2052,7 +2052,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return true;
}
- private static Boolean GetTimeOfNN(ref DateTimeResult result, ref DateTimeRawInfo raw)
+ private static bool GetTimeOfNN(ref DateTimeResult result, ref DateTimeRawInfo raw)
{
Debug.Assert(raw.numCount >= 2, "raw.numCount >= 2");
if ((result.flags & ParseFlags.HaveTime) != 0)
@@ -2068,7 +2068,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return true;
}
- private static Boolean GetTimeOfNNN(ref DateTimeResult result, ref DateTimeRawInfo raw)
+ private static bool GetTimeOfNNN(ref DateTimeResult result, ref DateTimeRawInfo raw)
{
if ((result.flags & ParseFlags.HaveTime) != 0)
{
@@ -2087,7 +2087,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
//
// Processing terminal state: A Date suffix followed by one number.
//
- private static Boolean GetDateOfDSN(ref DateTimeResult result, ref DateTimeRawInfo raw)
+ private static bool GetDateOfDSN(ref DateTimeResult result, ref DateTimeRawInfo raw)
{
if (raw.numCount != 1 || result.Day != -1)
{
@@ -2098,7 +2098,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return true;
}
- private static Boolean GetDateOfNDS(ref DateTimeResult result, ref DateTimeRawInfo raw)
+ private static bool GetDateOfNDS(ref DateTimeResult result, ref DateTimeRawInfo raw)
{
if (result.Month == -1)
{
@@ -2122,7 +2122,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return true;
}
- private static Boolean GetDateOfNNDS(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ private static bool 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
@@ -2236,7 +2236,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
//
////////////////////////////////////////////////////////////////////////
- internal static Boolean ProcessHebrewTerminalState(DS dps, ref __DTString str, ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ internal static bool 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)
@@ -2346,7 +2346,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, 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 ProcessTerminalState(DS dps, ref __DTString str, ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ internal static bool ProcessTerminalState(DS dps, ref __DTString str, ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
{
bool passed = true;
switch (dps)
@@ -2516,7 +2516,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
DateTimeRawInfo raw = new DateTimeRawInfo(); // The buffer to store temporary parsing information.
unsafe
{
- Int32* numberPointer = stackalloc Int32[3];
+ int* numberPointer = stackalloc int[3];
raw.Init(numberPointer);
}
raw.hasSameDateAndTimeSeparators = dtfi.DateSeparator.Equals(dtfi.TimeSeparator, StringComparison.Ordinal);
@@ -2591,7 +2591,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
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)
{
@@ -2608,7 +2608,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
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;
@@ -2719,7 +2719,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
result.parsedDate = time;
- if (!DetermineTimeZoneAdjustments(ref str, ref result, styles, bTimeOnly))
+ if (!DetermineTimeZoneAdjustments(ref result, styles, bTimeOnly))
{
TPTraceExit("0120 (DetermineTimeZoneAdjustments)", dps);
return false;
@@ -2730,17 +2730,17 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// Handles time zone adjustments and sets DateTimeKind values as required by the styles
- private static Boolean DetermineTimeZoneAdjustments(ref __DTString str, ref DateTimeResult result, DateTimeStyles styles, Boolean bTimeOnly)
+ private static bool DetermineTimeZoneAdjustments(ref DateTimeResult result, DateTimeStyles styles, bool 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 str, ref result, styles);
+ return DateTimeOffsetTimeZonePostProcessing(ref result, styles);
}
else
{
- Int64 offsetTicks = result.timeZoneOffset.Ticks;
+ long offsetTicks = result.timeZoneOffset.Ticks;
// the DateTime offset must be within +- 14:00 hours.
if (offsetTicks < DateTimeOffset.MinOffset || offsetTicks > DateTimeOffset.MaxOffset)
@@ -2808,9 +2808,9 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
// Apply validation and adjustments specific to DateTimeOffset
- private static Boolean DateTimeOffsetTimeZonePostProcessing(ref __DTString str, ref DateTimeResult result, DateTimeStyles styles)
+ private static bool DateTimeOffsetTimeZonePostProcessing(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)
{
@@ -2826,14 +2826,14 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
}
- Int64 offsetTicks = result.timeZoneOffset.Ticks;
+ long offsetTicks = result.timeZoneOffset.Ticks;
// there should be no overflow, because the offset can be no more than -+100 hours and the date already
// fits within a DateTime.
- Int64 utcTicks = result.parsedDate.Ticks - offsetTicks;
+ long 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.FormatWithOriginalDateTime, nameof(SR.Format_UTCOutOfRange));
@@ -2854,7 +2854,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if (((result.flags & ParseFlags.TimeZoneUsed) == 0) && ((styles & DateTimeStyles.AssumeUniversal) == 0))
{
// Handle the special case where the timeZoneOffset was defaulted to Local
- Boolean toUtcResult = AdjustTimeZoneToUniversal(ref result);
+ bool toUtcResult = AdjustTimeZoneToUniversal(ref result);
result.timeZoneOffset = TimeSpan.Zero;
return toUtcResult;
}
@@ -2875,7 +2875,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// the time is 2001/06/08 14:00, and timeZoneOffset = -07:00.
// The result will be "2001/06/08 21:00"
//
- private static Boolean AdjustTimeZoneToUniversal(ref DateTimeResult result)
+ private static bool AdjustTimeZoneToUniversal(ref DateTimeResult result)
{
long resultTicks = result.parsedDate.Ticks;
resultTicks -= result.timeZoneOffset.Ticks;
@@ -2900,12 +2900,12 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// the time is 2001/06/08 14:00, and timeZoneOffset = -05:00.
// The result will be "2001/06/08 11:00"
//
- private static Boolean AdjustTimeZoneToLocal(ref DateTimeResult result, bool bTimeOnly)
+ private static bool AdjustTimeZoneToLocal(ref DateTimeResult result, bool bTimeOnly)
{
long resultTicks = result.parsedDate.Ticks;
// Convert to local ticks
TimeZoneInfo tz = TimeZoneInfo.Local;
- Boolean isAmbiguousLocalDst = false;
+ bool isAmbiguousLocalDst = false;
if (resultTicks < Calendar.TicksPerDay)
{
//
@@ -2936,7 +2936,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
// Convert the GMT time to local time.
DateTime utcDt = new DateTime(resultTicks, DateTimeKind.Utc);
- Boolean isDaylightSavings = false;
+ bool isDaylightSavings = false;
resultTicks += TimeZoneInfo.GetUtcOffsetFromUtc(utcDt, TimeZoneInfo.Local, out isDaylightSavings, out isAmbiguousLocalDst).Ticks;
}
}
@@ -3061,7 +3061,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
time = time.AddTicks((long)Math.Round(partSecond * Calendar.TicksPerSecond));
result.parsedDate = time;
- if (!DetermineTimeZoneAdjustments(ref str, ref result, styles, false))
+ if (!DetermineTimeZoneAdjustments(ref result, styles, false))
{
return false;
}
@@ -3315,7 +3315,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
int monthsInYear = (dtfi.GetMonthName(13).Length == 0 ? 12 : 13);
for (int i = 1; i <= monthsInYear; i++)
{
- String searchStr = dtfi.GetAbbreviatedMonthName(i);
+ string searchStr = dtfi.GetAbbreviatedMonthName(i);
int matchStrLen = searchStr.Length;
if (dtfi.HasSpacesInMonthNames
? str.MatchSpecifiedWords(searchStr, false, ref matchStrLen)
@@ -3373,7 +3373,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
int monthsInYear = (dtfi.GetMonthName(13).Length == 0 ? 12 : 13);
for (int i = 1; i <= monthsInYear; i++)
{
- String searchStr = dtfi.GetMonthName(i);
+ string searchStr = dtfi.GetMonthName(i);
int matchStrLen = searchStr.Length;
if (dtfi.HasSpacesInMonthNames
? str.MatchSpecifiedWords(searchStr, false, ref matchStrLen)
@@ -3438,7 +3438,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
for (DayOfWeek i = DayOfWeek.Sunday; i <= DayOfWeek.Saturday; i++)
{
- String searchStr = dtfi.GetAbbreviatedDayName(i);
+ string searchStr = dtfi.GetAbbreviatedDayName(i);
int matchStrLen = searchStr.Length;
if (dtfi.HasSpacesInDayNames
? str.MatchSpecifiedWords(searchStr, false, ref matchStrLen)
@@ -3477,7 +3477,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
for (DayOfWeek i = DayOfWeek.Sunday; i <= DayOfWeek.Saturday; i++)
{
- String searchStr = dtfi.GetDayName(i);
+ string searchStr = dtfi.GetDayName(i);
int matchStrLen = searchStr.Length;
if (dtfi.HasSpacesInDayNames
? str.MatchSpecifiedWords(searchStr, false, ref matchStrLen)
@@ -3517,7 +3517,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
for (int i = 0; i < eras.Length; i++)
{
- String searchStr = dtfi.GetEraName(eras[i]);
+ string searchStr = dtfi.GetEraName(eras[i]);
if (str.MatchSpecifiedWord(searchStr))
{
str.Index += (searchStr.Length - 1);
@@ -3560,7 +3560,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if (str.GetNext())
{
- String searchStr = dtfi.AMDesignator;
+ string searchStr = dtfi.AMDesignator;
if (searchStr.Length > 0)
{
if (str.MatchSpecifiedWord(searchStr))
@@ -3668,7 +3668,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
}
- // assume the offset is Local
+ // assume the offset is Local
return DateTime.Now;
}
@@ -3774,7 +3774,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// This method also set the dtfi according/parseInfo to some special pre-defined
// formats.
//
- private static String ExpandPredefinedFormat(ReadOnlySpan<char> 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,
@@ -3782,24 +3782,14 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
//
switch (format[0])
{
+ case 's': // Sortable format (in local time)
case 'o':
case 'O': // Round Trip Format
- parseInfo.calendar = GregorianCalendar.GetDefaultInstance();
- dtfi = DateTimeFormatInfo.InvariantInfo;
+ ConfigureFormatOS(ref dtfi, ref parseInfo);
break;
case 'r':
case 'R': // RFC 1123 Standard. (in Universal time)
- parseInfo.calendar = GregorianCalendar.GetDefaultInstance();
- dtfi = DateTimeFormatInfo.InvariantInfo;
-
- if ((result.flags & ParseFlags.CaptureOffset) != 0)
- {
- result.flags |= ParseFlags.Rfc1123Pattern;
- }
- break;
- case 's': // Sortable format (in local time)
- dtfi = DateTimeFormatInfo.InvariantInfo;
- parseInfo.calendar = GregorianCalendar.GetDefaultInstance();
+ ConfigureFormatR(ref dtfi, ref parseInfo, ref result);
break;
case 'u': // Universal time format in sortable format.
parseInfo.calendar = GregorianCalendar.GetDefaultInstance();
@@ -3829,9 +3819,21 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return (DateTimeFormat.GetRealFormat(format, dtfi));
}
+ private static void ConfigureFormatR(ref DateTimeFormatInfo dtfi, ref ParsingInfo parseInfo, ref DateTimeResult result)
+ {
+ parseInfo.calendar = GregorianCalendar.GetDefaultInstance();
+ dtfi = DateTimeFormatInfo.InvariantInfo;
+ if ((result.flags & ParseFlags.CaptureOffset) != 0)
+ {
+ result.flags |= ParseFlags.Rfc1123Pattern;
+ }
+ }
-
-
+ private static void ConfigureFormatOS(ref DateTimeFormatInfo dtfi, ref ParsingInfo parseInfo)
+ {
+ parseInfo.calendar = GregorianCalendar.GetDefaultInstance();
+ dtfi = DateTimeFormatInfo.InvariantInfo;
+ }
// Given a specified format character, parse and update the parsing result.
//
@@ -4201,7 +4203,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// Some cultures uses space in the quoted string. E.g. Spanish has long date format as:
// "dddd, dd' de 'MMMM' de 'yyyy". When inner spaces flag is set, we should skip whitespaces if there is space
// in the quoted string.
- String quotedStr = StringBuilderCache.GetStringAndRelease(enquotedString);
+ string quotedStr = StringBuilderCache.GetStringAndRelease(enquotedString);
for (int i = 0; i < quotedStr.Length; i++)
{
@@ -4218,7 +4220,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
// 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)
@@ -4443,12 +4445,32 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if (formatParam.Length == 1)
{
- if (((result.flags & ParseFlags.CaptureOffset) != 0) && formatParam[0] == 'U')
+ char formatParamChar = formatParam[0];
+
+ // Fast-paths for common and important formats/configurations.
+ if (styles == DateTimeStyles.None)
+ {
+ switch (formatParamChar)
+ {
+ case 'R':
+ case 'r':
+ ConfigureFormatR(ref dtfi, ref parseInfo, ref result);
+ return ParseFormatR(s, ref parseInfo, ref result);
+
+ case 'O':
+ case 'o':
+ ConfigureFormatOS(ref dtfi, ref parseInfo);
+ return ParseFormatO(s, ref parseInfo, ref result);
+ }
+ }
+
+ if (((result.flags & ParseFlags.CaptureOffset) != 0) && formatParamChar == 'U')
{
// The 'U' format is not allowed for DateTimeOffset
result.SetBadFormatSpecifierFailure(formatParam);
return false;
}
+
formatParam = ExpandPredefinedFormat(formatParam, ref dtfi, ref parseInfo, ref result);
}
@@ -4614,13 +4636,417 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
- if (!DetermineTimeZoneAdjustments(ref str, ref result, styles, bTimeOnly))
+ if (!DetermineTimeZoneAdjustments(ref result, styles, bTimeOnly))
{
return false;
}
return true;
}
+ private static bool ParseFormatR(ReadOnlySpan<char> source, ref ParsingInfo parseInfo, ref DateTimeResult result)
+ {
+ // Example:
+ // Tue, 03 Jan 2017 08:08:05 GMT
+
+ // The format is exactly 29 characters.
+ if ((uint)source.Length != 29)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ // Parse the three-letter day of week. Any casing is valid.
+ DayOfWeek dayOfWeek;
+ {
+ uint dow0 = source[0], dow1 = source[1], dow2 = source[2], comma = source[3];
+
+ if ((dow0 | dow1 | dow2 | comma) > 0x7F)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ uint dowString = (dow0 << 24) | (dow1 << 16) | (dow2 << 8) | comma | 0x20202000;
+ switch (dowString)
+ {
+ case 0x73756E2c /* 'sun,' */: dayOfWeek = DayOfWeek.Sunday; break;
+ case 0x6d6f6e2c /* 'mon,' */: dayOfWeek = DayOfWeek.Monday; break;
+ case 0x7475652c /* 'tue,' */: dayOfWeek = DayOfWeek.Tuesday; break;
+ case 0x7765642c /* 'wed,' */: dayOfWeek = DayOfWeek.Wednesday; break;
+ case 0x7468752c /* 'thu,' */: dayOfWeek = DayOfWeek.Thursday; break;
+ case 0x6672692c /* 'fri,' */: dayOfWeek = DayOfWeek.Friday; break;
+ case 0x7361742c /* 'sat,' */: dayOfWeek = DayOfWeek.Saturday; break;
+ default:
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+ }
+
+ if (source[4] != ' ')
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ // Parse the two digit day.
+ int day;
+ {
+ uint digit1 = (uint)(source[5] - '0'), digit2 = (uint)(source[6] - '0');
+
+ if (digit1 > 9 || digit2 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ day = (int)(digit1*10 + digit2);
+ }
+
+ if (source[7] != ' ')
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ // Parse the three letter month (followed by a space). Any casing is valid.
+ int month;
+ {
+ uint m0 = source[8], m1 = source[9], m2 = source[10], space = source[11];
+
+ if ((m0 | m1 | m2 | space) > 0x7F)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ switch ((m0 << 24) | (m1 << 16) | (m2 << 8) | space | 0x20202000)
+ {
+ case 0x6a616e20 /* 'jan ' */ : month = 1; break;
+ case 0x66656220 /* 'feb ' */ : month = 2; break;
+ case 0x6d617220 /* 'mar ' */ : month = 3; break;
+ case 0x61707220 /* 'apr ' */ : month = 4; break;
+ case 0x6d617920 /* 'may ' */ : month = 5; break;
+ case 0x6a756e20 /* 'jun ' */ : month = 6; break;
+ case 0x6a756c20 /* 'jul ' */ : month = 7; break;
+ case 0x61756720 /* 'aug ' */ : month = 8; break;
+ case 0x73657020 /* 'sep ' */ : month = 9; break;
+ case 0x6f637420 /* 'oct ' */ : month = 10; break;
+ case 0x6e6f7620 /* 'nov ' */ : month = 11; break;
+ case 0x64656320 /* 'dec ' */ : month = 12; break;
+ default:
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+ }
+
+ // Parse the four-digit year.
+ int year;
+ {
+ uint y1 = (uint)(source[12] - '0'), y2 = (uint)(source[13] - '0'), y3 = (uint)(source[14] - '0'), y4 = (uint)(source[15] - '0');
+
+ if (y1 > 9 || y2 > 9 || y3 > 9 || y4 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ year = (int)(y1*1000 + y2*100 + y3*10 + y4);
+ }
+
+ if (source[16] != ' ')
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ // Parse the two digit hour.
+ int hour;
+ {
+ uint h1 = (uint)(source[17] - '0'), h2 = (uint)(source[18] - '0');
+
+ if (h1 > 9 || h2 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ hour = (int)(h1*10 + h2);
+ }
+
+ if (source[19] != ':')
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ // Parse the two-digit minute.
+ int minute;
+ {
+ uint m1 = (uint)(source[20] - '0');
+ uint m2 = (uint)(source[21] - '0');
+
+ if (m1 > 9 || m2 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ minute = (int)(m1*10 + m2);
+ }
+
+ if (source[22] != ':')
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ // Parse the two-digit second.
+ int second;
+ {
+ uint s1 = (uint)(source[23] - '0'), s2 = (uint)(source[24] - '0');
+
+ if (s1 > 9 || s2 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ second = (int)(s1*10 + s2);
+ }
+
+ // Parse " GMT". It must be upper case.
+ if (source[25] != ' ' || source[26] != 'G' || source[27] != 'M' || source[28] != 'T')
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ // Validate that the parsed date is valid according to the calendar.
+ if (!parseInfo.calendar.TryToDateTime(year, month, day, hour, minute, second, 0, 0, out result.parsedDate))
+ {
+ result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar));
+ return false;
+ }
+
+ // And validate that the parsed day of week matches what the calendar said it should be.
+ if (dayOfWeek != result.parsedDate.DayOfWeek)
+ {
+ result.SetFailure(ParseFailureKind.FormatWithOriginalDateTime, nameof(SR.Format_BadDayOfWeek));
+ return false;
+ }
+
+ return true;
+ }
+
+ private static bool ParseFormatO(ReadOnlySpan<char> source, ref ParsingInfo parseInfo, ref DateTimeResult result)
+ {
+ // Examples:
+ // 2017-06-12T05:30:45.7680000 (interpreted as local time wrt to current time zone)
+ // 2017-06-12T05:30:45.7680000Z (Z is short for "+00:00" but also distinguishes DateTimeKind.Utc from DateTimeKind.Local)
+ // 2017-06-12T05:30:45.7680000-7:00 (special-case of one-digit offset hour)
+ // 2017-06-12T05:30:45.7680000-07:00
+
+ if ((uint)source.Length < 27 ||
+ source[4] != '-' ||
+ source[7] != '-' ||
+ source[10] != 'T' ||
+ source[13] != ':' ||
+ source[16] != ':' ||
+ source[19] != '.')
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ int year;
+ {
+ uint y1 = (uint)(source[0] - '0'), y2 = (uint)(source[1] - '0'), y3 = (uint)(source[2] - '0'), y4 = (uint)(source[3] - '0');
+
+ if (y1 > 9 || y2 > 9 || y3 > 9 || y4 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ year = (int)(y1*1000 + y2*100 + y3*10 + y4);
+ }
+
+ int month;
+ {
+ uint m1 = (uint)(source[5] - '0'), m2 = (uint)(source[6] - '0');
+
+ if (m1 > 9 || m2 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ month = (int)(m1*10 + m2);
+ }
+
+ int day;
+ {
+ uint d1 = (uint)(source[8] - '0'), d2 = (uint)(source[9] - '0');
+
+ if (d1 > 9 || d2 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ day = (int)(d1*10 + d2);
+ }
+
+ int hour;
+ {
+ uint h1 = (uint)(source[11] - '0'), h2 = (uint)(source[12] - '0');
+
+ if (h1 > 9 || h2 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ hour = (int)(h1*10 + h2);
+ }
+
+ int minute;
+ {
+ uint m1 = (uint)(source[14] - '0'), m2 = (uint)(source[15] - '0');
+
+ if (m1 > 9 || m2 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ minute = (int)(m1*10 + m2);
+ }
+
+ int second;
+ {
+ uint s1 = (uint)(source[17] - '0'), s2 = (uint)(source[18] - '0');
+
+ if (s1 > 9 || s2 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ second = (int)(s1*10 + s2);
+ }
+
+ double fraction;
+ {
+ uint f1 = (uint)(source[20] - '0');
+ uint f2 = (uint)(source[21] - '0');
+ uint f3 = (uint)(source[22] - '0');
+ uint f4 = (uint)(source[23] - '0');
+ uint f5 = (uint)(source[24] - '0');
+ uint f6 = (uint)(source[25] - '0');
+ uint f7 = (uint)(source[26] - '0');
+
+ if (f1 > 9 || f2 > 9 || f3 > 9 || f4 > 9 || f5 > 9 || f6 > 9 || f7 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ fraction = (f1*1000000 + f2*100000 + f3*10000 + f4*1000 + f5*100 + f6*10 + f7) / 10000000.0;
+ }
+
+ if (!DateTime.TryCreate(year, month, day, hour, minute, second, 0, out DateTime dateTime))
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+ result.parsedDate = dateTime.AddTicks((long)Math.Round(fraction * Calendar.TicksPerSecond));
+
+ if ((uint)source.Length > 27)
+ {
+ char offsetChar = source[27];
+ switch (offsetChar)
+ {
+ case 'Z':
+ if (source.Length != 28)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+ result.flags |= ParseFlags.TimeZoneUsed | ParseFlags.TimeZoneUtc;
+ break;
+
+ case '+':
+ case '-':
+ int offsetHours, colonIndex;
+
+ if ((uint)source.Length == 33)
+ {
+ uint oh1 = (uint)(source[28] - '0'), oh2 = (uint)(source[29] - '0');
+
+ if (oh1 > 9 || oh2 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ offsetHours = (int)(oh1 * 10 + oh2);
+ colonIndex = 30;
+ }
+ else if ((uint)source.Length == 32) // special-case allowed for compat: only one offset hour digit
+ {
+ offsetHours = source[28] - '0';
+
+ if ((uint)offsetHours > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ colonIndex = 29;
+ }
+ else
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ if (source[colonIndex] != ':')
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ int offsetMinutes;
+ {
+ uint om1 = (uint)(source[colonIndex + 1] - '0'), om2 = (uint)(source[colonIndex + 2] - '0');
+
+ if (om1 > 9 || om2 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ offsetMinutes = (int)(om1*10 + om2);
+ }
+
+ result.flags |= ParseFlags.TimeZoneUsed;
+ result.timeZoneOffset = new TimeSpan(offsetHours, offsetMinutes, 0);
+ if (offsetChar == '-')
+ {
+ result.timeZoneOffset = result.timeZoneOffset.Negate();
+ }
+ break;
+
+ default:
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+ }
+
+ return DetermineTimeZoneAdjustments(ref result, DateTimeStyles.None, bTimeOnly: false);
+ }
+
private static Exception GetDateTimeParseException(ref DateTimeResult result)
{
switch (result.failure)
@@ -4700,7 +5126,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
private static string Hex(string[] strs)
{
if (strs == null || strs.Length == 0)
- return String.Empty;
+ return string.Empty;
if (strs.Length == 1)
return Hex(strs[0]);
@@ -4713,7 +5139,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
StringBuilder buffer = new StringBuilder();
buffer.Append(Hex(strs[0]));
curLineLength = buffer.Length;
- String s;
+ string s;
for (int i = 1; i < strs.Length - 1; i++)
{
@@ -4766,7 +5192,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return buffer.ToString();
}
// return an unicode escaped string form of char c
- private static String Hex(char c)
+ private static string Hex(char c)
{
if (c <= '\x007f')
return c.ToString(CultureInfo.InvariantCulture);
@@ -4819,20 +5245,14 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
internal __DTString(ReadOnlySpan<char> str, DateTimeFormatInfo dtfi)
{
+ Debug.Assert(dtfi != null, "Expected non-null DateTimeFormatInfo");
+
Index = -1;
Value = str;
m_current = '\0';
- if (dtfi != null)
- {
- m_info = dtfi.CompareInfo;
- m_checkDigitToken = ((dtfi.FormatFlags & DateTimeFormatFlags.UseDigitPrefixInTokens) != 0);
- }
- else
- {
- m_info = CultureInfo.CurrentCulture.CompareInfo;
- m_checkDigitToken = false;
- }
+ m_info = dtfi.CompareInfo;
+ m_checkDigitToken = ((dtfi.FormatFlags & DateTimeFormatFlags.UseDigitPrefixInTokens) != 0);
}
internal CompareInfo CompareInfo
@@ -4954,13 +5374,13 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
}
}
- else if (Char.IsWhiteSpace(m_current))
+ else if (char.IsWhiteSpace(m_current))
{
// Just skip to the next character.
while (++Index < Length)
{
m_current = Value[Index];
- if (!(Char.IsWhiteSpace(m_current)))
+ if (!(char.IsWhiteSpace(m_current)))
{
goto Start;
}
@@ -5004,13 +5424,13 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal bool MatchSpecifiedWord(String target) =>
+ internal bool MatchSpecifiedWord(string target) =>
Index + target.Length <= Length &&
m_info.Compare(Value.Slice(Index, target.Length), target, CompareOptions.IgnoreCase) == 0;
- private static readonly Char[] WhiteSpaceChecks = new Char[] { ' ', '\u00A0' };
+ private static readonly char[] WhiteSpaceChecks = new char[] { ' ', '\u00A0' };
- internal bool MatchSpecifiedWords(String target, bool checkWordBoundary, ref int matchLength)
+ internal bool MatchSpecifiedWords(string target, bool checkWordBoundary, ref int matchLength)
{
int valueRemaining = Value.Length - Index;
matchLength = target.Length;
@@ -5041,11 +5461,11 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
else
{
// Make sure we also have whitespace in the input string
- if (!Char.IsWhiteSpace(Value[thisPosition + segmentLength]))
+ if (!char.IsWhiteSpace(Value[thisPosition + segmentLength]))
{
return false;
}
- if (m_info.Compare(Value.Slice(thisPosition, segmentLength), target.AsSpan().Slice(targetPosition, segmentLength), CompareOptions.IgnoreCase) != 0)
+ if (m_info.CompareOptionIgnoreCase(Value.Slice(thisPosition, segmentLength), target.AsSpan(targetPosition, segmentLength)) != 0)
{
return false;
}
@@ -5057,7 +5477,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// Skip past multiple whitespace
- while (thisPosition < Value.Length && Char.IsWhiteSpace(Value[thisPosition]))
+ while (thisPosition < Value.Length && char.IsWhiteSpace(Value[thisPosition]))
{
thisPosition++;
matchLength++;
@@ -5071,7 +5491,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
return false;
}
- if (m_info.Compare(Value.Slice(thisPosition, segmentLength), target.AsSpan().Slice(targetPosition, segmentLength), CompareOptions.IgnoreCase) != 0)
+ if (m_info.CompareOptionIgnoreCase(Value.Slice(thisPosition, segmentLength), target.AsSpan(targetPosition, segmentLength)) != 0)
{
return false;
}
@@ -5083,7 +5503,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
int nextCharIndex = Index + matchLength;
if (nextCharIndex < Value.Length)
{
- if (Char.IsLetter(Value[nextCharIndex]))
+ if (char.IsLetter(Value[nextCharIndex]))
{
return (false);
}
@@ -5098,7 +5518,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// If a match is found, true value is returned and Index is updated to the next character to be parsed.
// Otherwise, Index is unchanged.
//
- internal bool Match(String str)
+ internal bool Match(string str)
{
if (++Index >= Length)
{
@@ -5147,12 +5567,12 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// maxMatchStrLen [in/out] the initailized maximum length. This parameter can be used to
// find the longest match in two string arrays.
//
- internal int MatchLongestWords(String[] words, ref int maxMatchStrLen)
+ internal int MatchLongestWords(string[] words, ref int maxMatchStrLen)
{
int result = -1;
for (int i = 0; i < words.Length; i++)
{
- String word = words[i];
+ string word = words[i];
int matchLength = word.Length;
if (MatchSpecifiedWords(word, false, ref matchLength))
{
@@ -5225,7 +5645,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
while (Index + 1 < Length)
{
char ch = Value[Index + 1];
- if (!Char.IsWhiteSpace(ch))
+ if (!char.IsWhiteSpace(ch))
{
return;
}
@@ -5246,7 +5666,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return (false);
}
- if (!Char.IsWhiteSpace(m_current))
+ if (!char.IsWhiteSpace(m_current))
{
return (true);
}
@@ -5254,7 +5674,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
while (++Index < Length)
{
m_current = Value[Index];
- if (!Char.IsWhiteSpace(m_current))
+ if (!char.IsWhiteSpace(m_current))
{
return (true);
}
@@ -5266,7 +5686,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
internal void TrimTail()
{
int i = Length - 1;
- while (i >= 0 && Char.IsWhiteSpace(Value[i]))
+ while (i >= 0 && char.IsWhiteSpace(Value[i]))
{
i--;
}
@@ -5286,14 +5706,17 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// 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;
}
}
}
@@ -5311,13 +5734,16 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// 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;
}
}
}
@@ -5330,7 +5756,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
while (Index + sub.length < Length)
{
DTSubStringType currentType;
- Char ch = Value[Index + sub.length];
+ char ch = Value[Index + sub.length];
if (ch >= '0' && ch <= '9')
{
currentType = DTSubStringType.Number;
@@ -5406,12 +5832,12 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
internal ref struct DTSubString
{
internal ReadOnlySpan<char> s;
- internal Int32 index;
- internal Int32 length;
+ internal int index;
+ internal int length;
internal DTSubStringType type;
- internal Int32 value;
+ internal int value;
- internal Char this[Int32 relativeIndex]
+ internal char this[int relativeIndex]
{
get
{
@@ -5510,7 +5936,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
internal int Month;
internal int Day;
//
- // Set time defualt to 00:00:00.
+ // Set time default to 00:00:00.
//
internal int Hour;
internal int Minute;