public override bool TryParseValue(string value, object storeValue, ref int index, out object parsedValue) { parsedValue = null; // Some headers support empty/null values. This one doesn't. if (string.IsNullOrEmpty(value) || (index == value.Length)) { return(false); } ReadOnlySpan <char> dateString = value; if (index > 0) { dateString = value.AsSpan(index); } DateTimeOffset date; if (!HttpDateParser.TryStringToDate(dateString, out date)) { return(false); } index = value.Length; parsedValue = date; return(true); }
private static bool TryReadDate(string input, ref int current, out DateTimeOffset?date) { date = null; // Make sure we have at least one whitespace between <text> and <date> (if we have <date>) int whitespaceLength = HttpRuleParser.GetWhitespaceLength(input, current); current = current + whitespaceLength; // Read <date> in '<code> <agent> <text> ["<date>"]' if ((current < input.Length) && (input[current] == '"')) { if (whitespaceLength == 0) { return(false); // we have characters after <text> but they were not separated by a whitespace } current++; // skip opening '"' // Find the closing '"' int dateStartIndex = current; while (current < input.Length) { if (input[current] == '"') { break; } current++; } if ((current == input.Length) || (current == dateStartIndex)) { return(false); // we couldn't find the closing '"' or we have an empty quoted string. } DateTimeOffset temp; if (!HttpDateParser.TryStringToDate(input.Substring(dateStartIndex, current - dateStartIndex), out temp)) { return(false); } date = temp; current++; // skip closing '"' current = current + HttpRuleParser.GetWhitespaceLength(input, current); } return(true); }
private DateTimeOffset?GetDate(string parameter) { NameValueHeaderValue valueHeaderValue = NameValueHeaderValue.Find(this._parameters, parameter); if (valueHeaderValue != null) { ReadOnlySpan <char> input = (ReadOnlySpan <char>)valueHeaderValue.Value; if (ContentDispositionHeaderValue.IsQuoted(input)) { input = input.Slice(1, input.Length - 2); } DateTimeOffset result; if (HttpDateParser.TryStringToDate(input, out result)) { return(new DateTimeOffset?(result)); } } return(new DateTimeOffset?()); }
// Gets a parameter of the given name and attempts to extract a date. // Returns null if the parameter is not present or the format is incorrect. private DateTimeOffset?GetDate(string parameter) { NameValueHeaderValue dateParameter = NameValueHeaderValue.Find(_parameters, parameter); DateTimeOffset date; if (dateParameter != null) { ReadOnlySpan <char> dateString = dateParameter.Value; // Should have quotes, remove them. if (IsQuoted(dateString)) { dateString = dateString.Slice(1, dateString.Length - 2); } if (HttpDateParser.TryStringToDate(dateString, out date)) { return(date); } } return(null); }
internal static int GetRangeConditionLength(string input, int startIndex, out object parsedValue) { Debug.Assert(startIndex >= 0); parsedValue = null; // Make sure we have at least 2 characters if (string.IsNullOrEmpty(input) || (startIndex + 1 >= input.Length)) { return(0); } int current = startIndex; // Caller must remove leading whitespace. DateTimeOffset date = DateTimeOffset.MinValue; EntityTagHeaderValue entityTag = null; // Entity tags are quoted strings optionally preceded by "W/". By looking at the first two character we // can determine whether the string is en entity tag or a date. char firstChar = input[current]; char secondChar = input[current + 1]; if ((firstChar == '\"') || (((firstChar == 'w') || (firstChar == 'W')) && (secondChar == '/'))) { // trailing whitespace is removed by GetEntityTagLength() int entityTagLength = EntityTagHeaderValue.GetEntityTagLength(input, current, out entityTag); if (entityTagLength == 0) { return(0); } current = current + entityTagLength; // RangeConditionHeaderValue only allows 1 value. There must be no delimiter/other chars after an // entity tag. if (current != input.Length) { return(0); } } else { if (!HttpDateParser.TryStringToDate(input.AsSpan(current), out date)) { return(0); } // If we got a valid date, then the parser consumed the whole string (incl. trailing whitespace). current = input.Length; } RangeConditionHeaderValue result = new RangeConditionHeaderValue(); if (entityTag == null) { result._date = date; } else { result._entityTag = entityTag; } parsedValue = result; return(current - startIndex); }
internal static int GetRetryConditionLength(string input, int startIndex, out object parsedValue) { Debug.Assert(startIndex >= 0); parsedValue = null; if (string.IsNullOrEmpty(input) || (startIndex >= input.Length)) { return(0); } int current = startIndex; // Caller must remove leading whitespace. DateTimeOffset date = DateTimeOffset.MinValue; int deltaSeconds = -1; // use -1 to indicate that the value was not set. 'delta' values are always >=0 // We either have a timespan or a date/time value. Determine which one we have by looking at the first char. // If it is a number, we have a timespan, otherwise we assume we have a date. char firstChar = input[current]; if ((firstChar >= '0') && (firstChar <= '9')) { int deltaStartIndex = current; int deltaLength = HttpRuleParser.GetNumberLength(input, current, false); // The value must be in the range 0..2^31 if ((deltaLength == 0) || (deltaLength > HttpRuleParser.MaxInt32Digits)) { return(0); } current = current + deltaLength; current = current + HttpRuleParser.GetWhitespaceLength(input, current); // RetryConditionHeaderValue only allows 1 value. There must be no delimiter/other chars after 'delta' if (current != input.Length) { return(0); } if (!HeaderUtilities.TryParseInt32(input, deltaStartIndex, deltaLength, out deltaSeconds)) { return(0); // int.TryParse() may return 'false' if the value has 10 digits and is > Int32.MaxValue. } } else { if (!HttpDateParser.TryStringToDate(input.Substring(current), out date)) { return(0); } // If we got a valid date, then the parser consumed the whole string (incl. trailing whitespace). current = input.Length; } RetryConditionHeaderValue result = new RetryConditionHeaderValue(); if (deltaSeconds == -1) // we didn't change delta, so we must have found a date. { result._date = date; } else { result._delta = new TimeSpan(0, 0, deltaSeconds); } parsedValue = result; return(current - startIndex); }
public static void TryStringToDate_UseInvalidDateTimeString(string invalid) { Assert.False(HttpDateParser.TryStringToDate(",Sun, 06 Nov 1994 08:49:37 GMT", out var result)); }
// We don't need extensive tests, since we let DateTimeOffset do the parsing. This test is just // to validate that we use the correct parameters when calling into DateTimeOffset.ToString(). public static void TryStringToDate_UseOfValidDateTimeStringsInDifferentFormats_ParsedCorrectly(string input, DateTimeOffset expected) { Assert.True(HttpDateParser.TryStringToDate(input, out var result)); Assert.Equal(expected, result); }
public static void TryStringToDate_UseInvalidDateTimeString(string invalid) { Assert.False(HttpDateParser.TryStringToDate(invalid, out var result)); Assert.Equal(default, result);