File: src\libraries\Common\src\System\Net\HttpDateParser.cs
Web Access
Project: src\src\libraries\System.Net.Requests\src\System.Net.Requests.csproj (System.Net.Requests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Globalization;
 
namespace System.Net
{
    internal static class HttpDateParser
    {
        private static readonly string[] s_dateFormats = new string[] {
            // "r", // RFC 1123, required output format but too strict for input
            "ddd, d MMM yyyy H:m:s 'GMT'", // RFC 1123 (r, except it allows both 1 and 01 for date and time)
            "ddd, d MMM yyyy H:m:s 'UTC'", // RFC 1123, UTC
            "ddd, d MMM yyyy H:m:s", // RFC 1123, no zone - assume GMT
            "d MMM yyyy H:m:s 'GMT'", // RFC 1123, no day-of-week
            "d MMM yyyy H:m:s 'UTC'", // RFC 1123, UTC, no day-of-week
            "d MMM yyyy H:m:s", // RFC 1123, no day-of-week, no zone
            "ddd, d MMM yy H:m:s 'GMT'", // RFC 1123, short year
            "ddd, d MMM yy H:m:s 'UTC'", // RFC 1123, UTC, short year
            "ddd, d MMM yy H:m:s", // RFC 1123, short year, no zone
            "d MMM yy H:m:s 'GMT'", // RFC 1123, no day-of-week, short year
            "d MMM yy H:m:s 'UTC'", // RFC 1123, UTC, no day-of-week, short year
            "d MMM yy H:m:s", // RFC 1123, no day-of-week, short year, no zone
 
            "dddd, d'-'MMM'-'yy H:m:s 'GMT'", // RFC 850
            "dddd, d'-'MMM'-'yy H:m:s 'UTC'", // RFC 850, UTC
            "dddd, d'-'MMM'-'yy H:m:s zzz", // RFC 850, offset
            "dddd, d'-'MMM'-'yy H:m:s", // RFC 850 no zone
            "ddd MMM d H:m:s yyyy", // ANSI C's asctime() format
 
            "ddd, d MMM yyyy H:m:s zzz", // RFC 5322
            "ddd, d MMM yyyy H:m:s", // RFC 5322 no zone
            "d MMM yyyy H:m:s zzz", // RFC 5322 no day-of-week
            "d MMM yyyy H:m:s", // RFC 5322 no day-of-week, no zone
        };
 
        internal static bool TryParse(ReadOnlySpan<char> input, out DateTimeOffset result)
        {
            // None of the relevant patterns have whitespace at the beginning or end, so trim the input of
            // any whitespace.  We can then use strict "r" matching, or if we have to fall back to trying
            // lots of patterns, only allow inner whitespace rather than leading or trailing whitespace.
            input = input.Trim();
 
            // First try strict parsing for "r" with no options, as it's an order of magnitude faster than general parsing for
            // any individual format in s_dateFormats, allocation-free, and also likely to succeed.  If it doesn't, then
            // fall back to trying each of the various date formats listed earlier, in order, to be accomodating and
            // accept a wide variety of old formats.
            return
                DateTimeOffset.TryParseExact(input, "r", DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None, out result) ||
                DateTimeOffset.TryParseExact(input, s_dateFormats, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AllowInnerWhite | DateTimeStyles.AssumeUniversal, out result);
        }
    }
}