DateTime.ToString() Fast Track for RFC1123 (dotnet/coreclr#7891)
authorPeter Marcu <Peter.Marcu@Microsoft.com>
Mon, 31 Oct 2016 05:28:45 +0000 (22:28 -0700)
committerGitHub <noreply@github.com>
Mon, 31 Oct 2016 05:28:45 +0000 (22:28 -0700)
* DateTime.ToString() Fast Track for RFC1123

Commit migrated from https://github.com/dotnet/coreclr/commit/5c0d01c19842049b2389ec9bee2885be918b9597

src/coreclr/src/mscorlib/src/System/Globalization/DateTimeFormat.cs

index c05ba97..918aecb 100644 (file)
@@ -139,8 +139,13 @@ namespace System {
         internal const String RoundtripFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffffffK";
         internal const String RoundtripDateTimeUnfixed = "yyyy'-'MM'-'ddTHH':'mm':'ss zzz";
     
-        private const int DEFAULT_ALL_DATETIMES_SIZE = 132; 
-        
+        private const int DEFAULT_ALL_DATETIMES_SIZE = 132;
+
+        internal static readonly DateTimeFormatInfo InvariantFormatInfo = CultureInfo.InvariantCulture.DateTimeFormat;
+        internal static readonly string[] InvariantAbbreviatedMonthNames = InvariantFormatInfo.AbbreviatedMonthNames;
+        internal static readonly string[] InvariantAbbreviatedDayNames = InvariantFormatInfo.AbbreviatedDayNames;
+        internal const string Gmt = "GMT";
+
         internal static String[] fixedNumberFormats = new String[] {
             "0",
             "00",
@@ -739,7 +744,7 @@ namespace System {
                     // 'zzz*' or longer format e.g "-07:30"
                     result.AppendFormat(CultureInfo.InvariantCulture, ":{0:00}", offset.Minutes);
                 }
-            }        
+            }
         }
 
         // output the 'K' format, which is for round-tripping the data
@@ -959,8 +964,14 @@ namespace System {
             }
 
             if (format.Length == 1) {
-                if (format[0] == 'o' || format[0] == 'O') {
+                switch (format[0])
+                {
+                    case 'O':
+                    case 'o':
                         return FastFormatRoundtrip(dateTime, offset);
+                    case 'R':
+                    case 'r':
+                        return FastFormatRfc1123(dateTime, offset, dtfi);
                 }
 
                 format = ExpandPredefinedFormat(format, ref dateTime, ref dtfi, ref offset);
@@ -969,9 +980,39 @@ namespace System {
             return (FormatCustomized(dateTime, format, dtfi, offset));
         }
 
+        internal static string FastFormatRfc1123(DateTime dateTime, TimeSpan offset, DateTimeFormatInfo dtfi)
+        {
+            // ddd, dd MMM yyyy HH:mm:ss GMT
+            const int Rfc1123FormatLength = 29;
+            StringBuilder result = StringBuilderCache.Acquire(Rfc1123FormatLength);
+
+            if (offset != NullOffset)
+            {
+                // Convert to UTC invariants
+                dateTime = dateTime - offset;
+            }
+
+            result.Append(InvariantAbbreviatedDayNames[(int)dateTime.DayOfWeek]);
+            result.Append(',');
+            result.Append(' ');
+            AppendNumber(result, dateTime.Day, 2);
+            result.Append(' ');
+            result.Append(InvariantAbbreviatedMonthNames[dateTime.Month - 1]);
+            result.Append(' ');
+            AppendNumber(result, dateTime.Year, 4);
+            result.Append(' ');
+            AppendHHmmssTimeOfDay(result, dateTime);
+            result.Append(' ');
+            result.Append(Gmt);
+
+            return StringBuilderCache.GetStringAndRelease(result);
+        }
+
         internal static string FastFormatRoundtrip(DateTime dateTime, TimeSpan offset)
         {
-            StringBuilder result = StringBuilderCache.Acquire();
+            // yyyy-MM-ddTHH:mm:ss.fffffffK
+            const int roundTrimFormatLength = 28;
+            StringBuilder result = StringBuilderCache.Acquire(roundTrimFormatLength);
 
             AppendNumber(result, dateTime.Year, 4);
             result.Append('-');
@@ -979,11 +1020,7 @@ namespace System {
             result.Append('-');
             AppendNumber(result, dateTime.Day, 2);
             result.Append('T');
-            AppendNumber(result, dateTime.Hour, 2);
-            result.Append(':');
-            AppendNumber(result, dateTime.Minute, 2);
-            result.Append(':');
-            AppendNumber(result, dateTime.Second, 2);
+            AppendHHmmssTimeOfDay(result, dateTime);
             result.Append('.');
 
             long fraction = dateTime.Ticks % TimeSpan.TicksPerSecond;
@@ -993,7 +1030,17 @@ namespace System {
 
             return StringBuilderCache.GetStringAndRelease(result);
         }
-        
+
+        private static void AppendHHmmssTimeOfDay(StringBuilder result, DateTime dateTime)
+        {
+            // HH:mm:ss
+            AppendNumber(result, dateTime.Hour, 2);
+            result.Append(':');
+            AppendNumber(result, dateTime.Minute, 2);
+            result.Append(':');
+            AppendNumber(result, dateTime.Second, 2);
+        }
+
         internal static void AppendNumber(StringBuilder builder, long val, int digits)
         {
             for (int i = 0; i < digits; i++)