Skip to content

Instantly share code, notes, and snippets.

@Guiorgy
Last active November 20, 2023 13:42
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Guiorgy/0fd0cffdaca2d78fdd910491511467cb to your computer and use it in GitHub Desktop.
Save Guiorgy/0fd0cffdaca2d78fdd910491511467cb to your computer and use it in GitHub Desktop.
Convert a DateTime object to and from an ISO string faster than the builtin methods
namespace DateTimeIso;
public static class DateTimeIsoExtensions
{
/// <summary>
/// Converts <see cref="DateTime"/> into an ISO 8601:2004 string (<c>yyyy-MM-dd HH:mm:ss.fff</c>) faster than <see cref="DateTime.ToString"/>.
/// </summary>
/// <param name="dateTime">the <see cref="DateTime"/> to be converted.</param>
/// <param name="milliseconds">if <see langword="false"/>, milliseconds won't be shown (<c>yyyy-MM-dd HH:mm:ss</c>).</param>
/// <param name="strictDateTimeDelimiter">if <see langword="true"/>, <c>'T'</c> will be used as the delimiter between date and time as per ISO 8601-1:2019 (<c>yyyy-MM-ddTHH:mm:ss.fff</c>).</param>
/// <param name="omitDelimiters">if <see langword="true"/>, delimiters will be omited, except for <c>'T'</c> between date and time when
/// <paramref name="strictDateTimeDelimiter"/> is <see langword="true"/> (<c>yyyyMMddHHmmssfff</c>, <c>yyyyMMddTHHmmssfff</c>).</param>
/// <returns>The <see cref="DateTime"/> in the ISO 8601:2004 format.</returns>
public static string ToIsoString(this DateTime dateTime, bool milliseconds = false, bool strictDateTimeDelimiter = false, bool omitDelimiters = false)
{
static char DigitToAsciiChar(int digit) => (char)('0' + digit);
static void Write2Digits(Span<char> chars, int offset, int value)
{
int firstDigit = value / 10;
int secondDigit = value - (firstDigit * 10);
chars[offset] = DigitToAsciiChar(firstDigit);
chars[offset + 1] = DigitToAsciiChar(secondDigit);
}
static void Write2DigitsAndPostfix(Span<char> chars, int offset, int value, char postfix)
{
Write2Digits(chars, offset, value);
chars[offset + 2] = postfix;
}
static void Write3Digits(Span<char> chars, int offset, int value)
{
int firstDigit = value / 100;
value -= firstDigit * 100;
int secondDigit = value / 10;
int thirdDigit = value - (secondDigit * 10);
chars[offset] = DigitToAsciiChar(firstDigit);
chars[offset + 1] = DigitToAsciiChar(secondDigit);
chars[offset + 2] = DigitToAsciiChar(thirdDigit);
}
/*static void Write3DigitsAndPostrfix(Span<char> chars, int offset, int value, char postfix)
{
Write3Digits(chars, offset, value);
chars[offset + 3] = postfix;
}*/
static void Write4Digits(Span<char> chars, int offset, int value)
{
int firstDigit = value / 1000;
value -= firstDigit * 1000;
int secondDigit = value / 100;
value -= secondDigit * 100;
int thirdDigit = value / 10;
int fourthDigit = value - (thirdDigit * 10);
chars[offset] = DigitToAsciiChar(firstDigit);
chars[offset + 1] = DigitToAsciiChar(secondDigit);
chars[offset + 2] = DigitToAsciiChar(thirdDigit);
chars[offset + 3] = DigitToAsciiChar(fourthDigit);
}
static void Write4DigitsAndPostfix(Span<char> chars, int offset, int value, char postfix)
{
Write4Digits(chars, offset, value);
chars[offset + 4] = postfix;
}
if (omitDelimiters)
{
int length = 14 + (strictDateTimeDelimiter ? 1 : 0) + (milliseconds ? 3 : 0);
return string.Create(length, (dateTime, strictDateTimeDelimiter, milliseconds), (chars, state) =>
{
(var _dateTime, var _strictDelimiter, var _milliseconds) = state;
Write4Digits(chars, 0, _dateTime.Year);
Write2Digits(chars, 4, _dateTime.Month);
if (_strictDelimiter) Write2DigitsAndPostfix(chars, 6, _dateTime.Day, 'T');
else Write2Digits(chars, 6, _dateTime.Day);
int tOffset = _strictDelimiter ? 1 : 0;
Write2Digits(chars, 8 + tOffset, _dateTime.Hour);
Write2Digits(chars, 10 + tOffset, _dateTime.Minute);
Write2Digits(chars, 12 + tOffset, _dateTime.Second);
if (_milliseconds) Write3Digits(chars, 14 + tOffset, _dateTime.Millisecond);
});
}
else
{
int length = 19 + (milliseconds ? 4 : 0);
return string.Create(length, (dateTime, strictDateTimeDelimiter, milliseconds), (chars, state) =>
{
(var _dateTime, var _strictDelimiter, var _milliseconds) = state;
Write4DigitsAndPostfix(chars, 0, _dateTime.Year, '-');
Write2DigitsAndPostfix(chars, 5, _dateTime.Month, '-');
Write2DigitsAndPostfix(chars, 8, _dateTime.Day, _strictDelimiter ? 'T' : ' ');
Write2DigitsAndPostfix(chars, 11, _dateTime.Hour, ':');
Write2DigitsAndPostfix(chars, 14, _dateTime.Minute, ':');
if (_milliseconds)
{
Write2DigitsAndPostfix(chars, 17, _dateTime.Second, '.');
Write3Digits(chars, 20, _dateTime.Millisecond);
}
else
{
Write2Digits(chars, 17, _dateTime.Second);
}
});
}
}
/// <summary>
/// Converts the ISO 8601:2004 (<c>yyyy-MM-dd HH:mm:ss.fff</c>) string representation of a date and time to its <see cref="DateTime"/> equivalent faster than <see cref="DateTime.TryParseExact"/>.
/// </summary>
/// <param name="isoDateTimeString">The string containing a date and time to convert.</param>
/// <param name="milliseconds">Whether the string contains milliseconds.</param>
/// <param name="noDateTimeDelimiter">if <see langword="true"/>, the delimiter between date and time (<c>'T'</c>) is assumed to be omitted (<c>yyyy-MM-ddHH:mm:ss.fff</c>).</param>
/// <param name="noDelimiters">if <see langword="true"/>, all delimiters, except for <c>'T'</c> between date and time when
/// <paramref name="noDateTimeDelimiter"/> is <see langword="false"/>, are assumed to be omitted (<c>yyyyMMddHHmmssfff</c>, <c>yyyyMMddTHHmmssfff</c>).</param>
/// <returns><see langword="true"/> if <paramref name="isoDateTimeString"/> was converted successfully; otherwise, <see langword="false"/>.</returns>
public static bool TryParseIsoDateTime(this string isoDateTimeString, out DateTime dateTime, bool milliseconds = false, bool noDateTimeDelimiter = false, bool noDelimiters = false)
{
int expectedLength = (milliseconds, noDateTimeDelimiter, noDelimiters) switch
{
(false, false, false) => 19, // yyyy-MM-ddTHH:mm:ss
(true, false, false) => 23, // yyyy-MM-ddTHH:mm:ss.fff
(false, false, true) => 15, // yyyyMMddTHHmmss
(true, false, true) => 18, // yyyyMMddTHHmmssfff
(false, true, false) => 18, // yyyy-MM-ddHH:mm:ss
(true, true, false) => 22, // yyyy-MM-ddHH:mm:ss.fff
(false, true, true) => 14, // yyyyMMddHHmmss
(true, true, true) => 17, // yyyyMMddHHmmssfff
};
if (isoDateTimeString == null || isoDateTimeString.Length != expectedLength)
{
dateTime = default;
return false;
}
static int AsciiCharToDigit(char digit) => digit - '0';
static bool IsDigit(int i) => 0 <= i && i <= 9;
static bool TryRead4Digits(ref ReadOnlySpan<char> chars, bool skipNext, out int value)
{
int a = AsciiCharToDigit(chars[0]);
int b = AsciiCharToDigit(chars[1]);
int c = AsciiCharToDigit(chars[2]);
int d = AsciiCharToDigit(chars[3]);
if (!IsDigit(a) || !IsDigit(b) || !IsDigit(c) || !IsDigit(d))
{
value = 0;
return false;
}
chars = chars[(skipNext ? 5 : 4)..];
value = (a * 1000) + (b * 100) + (c * 10) + d;
return true;
}
static bool TryRead3Digits(ref ReadOnlySpan<char> chars, bool skipNext, out int value)
{
int a = AsciiCharToDigit(chars[0]);
int b = AsciiCharToDigit(chars[1]);
int c = AsciiCharToDigit(chars[2]);
if (!IsDigit(a) || !IsDigit(b) || !IsDigit(c))
{
value = 0;
return false;
}
chars = chars[(skipNext ? 4 : 3)..];
value = (a * 100) + (b * 10) + c;
return true;
}
static bool TryRead2Digits(ref ReadOnlySpan<char> chars, bool skipNext, out int value)
{
int a = AsciiCharToDigit(chars[0]);
int b = AsciiCharToDigit(chars[1]);
if (!IsDigit(a) || !IsDigit(b))
{
value = 0;
return false;
}
chars = chars[(skipNext ? 3 : 2)..];
value = (a * 10) + b;
return true;
}
ReadOnlySpan<char> isoSpan = isoDateTimeString.AsSpan();
int millisecond = 0;
if (TryRead4Digits(ref isoSpan, !noDelimiters, out int year)
&& TryRead2Digits(ref isoSpan, !noDelimiters, out int month)
&& TryRead2Digits(ref isoSpan, !noDateTimeDelimiter, out int day)
&& TryRead2Digits(ref isoSpan, !noDelimiters, out int hour)
&& TryRead2Digits(ref isoSpan, !noDelimiters, out int minute)
&& TryRead2Digits(ref isoSpan, !noDelimiters && milliseconds, out int second)
&& (!milliseconds || TryRead3Digits(ref isoSpan, false, out millisecond)))
{
dateTime = new DateTime(year, month, day, hour, minute, second, millisecond, DateTimeKind.Unspecified);
return true;
}
else
{
dateTime = default;
return false;
}
}
/// <summary>
/// Converts the ISO 8601:2004 (<c>yyyy-MM-dd HH:mm:ss.fff</c>) string representation of a date and time to its <see cref="DateTime"/> equivalent faster than <see cref="DateTime.TryParseExact"/>.
/// </summary>
/// <param name="isoDateTimeString">The string containing a date and time to convert.</param>
/// <param name="milliseconds">Whether the string contains milliseconds.</param>
/// <param name="noDateTimeDelimiter">if <see langword="true"/>, the delimiter between date and time (<c>'T'</c>) is assumed to be omitted (<c>yyyy-MM-ddHH:mm:ss.fff</c>).</param>
/// <param name="noDelimiters">if <see langword="true"/>, all delimiters, except for <c>'T'</c> between date and time when
/// <paramref name="noDateTimeDelimiter"/> is <see langword="false"/>, are assumed to be omitted (<c>yyyyMMddHHmmssfff</c>, <c>yyyyMMddTHHmmssfff</c>).</param>
/// <returns>An object that is equivalent to the date and time contained in <paramref name="isoDateTimeString"/>.</returns>
/// <exception cref="ArgumentNullException"><paramref name="isoDateTimeString"/> is null.</exception>
/// <exception cref="FormatException"><paramref name="isoDateTimeString"/> is not in the correct ISO format.</exception>
public static DateTime ParseIsoDateTime(this string isoDateTimeString, bool milliseconds = false, bool noDateTimeDelimiter = false, bool noDelimiters = false)
{
if (isoDateTimeString == null) throw new ArgumentNullException(nameof(isoDateTimeString));
if (!TryParseIsoDateTime(isoDateTimeString, out DateTime dateTime, milliseconds, noDateTimeDelimiter, noDelimiters))
throw new FormatException("String is not in the correct ISO format");
return dateTime;
}
}
using BenchmarkDotNet.Attributes;
using System.Globalization;
namespace DateTimeIso;
[ReturnValueValidator(failOnError: true)]
public class FromStringBenchmark
{
private const int _count = 10000;
public readonly struct Data
{
public required readonly string[] Dates { get; init; }
public required string BuiltinFormat { get; init; }
public required bool Milliseconds { get; init; }
public required bool NoDateTimeDelimiter { get; init; }
public required bool NoDelimiters { get; init; }
public static implicit operator Data((string builtinFormat, bool milliseconds, bool noDateTimeDelimiter, bool noDelimiters) tuple)
{
RandomDateTime _random = new(42);
var dates = new string[_count];
for (int i = 0; i < _count; i++) dates[i] = _random.Next().ToString(tuple.builtinFormat);
return new Data
{
Dates = dates,
BuiltinFormat = tuple.builtinFormat,
Milliseconds = tuple.milliseconds,
NoDateTimeDelimiter = tuple.noDateTimeDelimiter,
NoDelimiters = tuple.noDelimiters
};
}
public override string ToString()
{
return BuiltinFormat;
}
}
[ParamsSource(nameof(DataValues))]
public Data data;
public static IEnumerable<Data> DataValues => new Data[]
{
("yyyy-MM-ddTHH:mm:ss.fff", true, false, false),
("yyyy-MM-ddTHH:mm:ss", false, false, false),
("yyyy-MM-ddHH:mm:ss.fff", true, true, false),
("yyyy-MM-ddHH:mm:ss", false, true, false),
("yyyyMMddTHHmmssfff", true, false, true),
("yyyyMMddTHHmmss", false, false, true),
("yyyyMMddHHmmssfff", true, true, true),
("yyyyMMddHHmmss", false, true, true)
};
[Benchmark(Baseline = true)]
public DateTime[] System_DateTime_TryParseExact()
{
DateTime[] parsed = new DateTime[_count];
for (int i = 0; i < _count; i++)
DateTime.TryParseExact(data.Dates[i], data.BuiltinFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out parsed[i]);
return parsed;
}
[Benchmark]
public DateTime[] Extension_TryParseIsoDateTime()
{
DateTime[] parsed = new DateTime[_count];
for (int i = 0; i < _count; i++)
data.Dates[i].TryParseIsoDateTime(out parsed[i], data.Milliseconds, data.NoDateTimeDelimiter, data.NoDelimiters);
return parsed;
}
}
namespace DateTimeIso;
public sealed class RandomDateTime
{
private static readonly DateTime start = new(1995, 1, 1, 0, 0, 0, DateTimeKind.Unspecified);
private static readonly DateTime end = new(2025, 1, 1, 0, 0, 0, DateTimeKind.Unspecified);
private static readonly int daysRange = (end - start).Days;
private readonly Random generator;
public RandomDateTime(int? seed = null)
{
generator = seed == null ? new Random() : new Random((int)seed);
}
public DateTime Next()
{
return start
.AddMilliseconds(generator.Next(0, 1000))
.AddSeconds(generator.Next(0, 60))
.AddMinutes(generator.Next(0, 60))
.AddHours(generator.Next(0, 24))
.AddDays(generator.Next(daysRange));
}
}
using BenchmarkDotNet.Attributes;
namespace DateTimeIso;
[ReturnValueValidator(failOnError: true)]
public class ToStringBenchmark
{
private DateTime[] _dates = Array.Empty<DateTime>();
private const int _count = 10000;
public readonly struct Data
{
public required string BuiltinFormat { get; init; }
public required bool Milliseconds { get; init; }
public required bool StrictDateTimeDelimiter { get; init; }
public required bool OmitDelimiters { get; init; }
public static implicit operator Data((string builtinFormat, bool milliseconds, bool strictDateTimeDelimiter, bool omitDelimiters) tuple)
{
return new Data
{
BuiltinFormat = tuple.builtinFormat,
Milliseconds = tuple.milliseconds,
StrictDateTimeDelimiter = tuple.strictDateTimeDelimiter,
OmitDelimiters = tuple.omitDelimiters
};
}
public override string ToString()
{
return BuiltinFormat;
}
}
[ParamsSource(nameof(DataValues))]
public Data data;
public static IEnumerable<Data> DataValues => new Data[]
{
("yyyy-MM-dd HH:mm:ss.fff", true, false, false),
("yyyy-MM-dd HH:mm:ss", false, false, false),
("yyyy-MM-ddTHH:mm:ss.fff", true, true, false),
("yyyy-MM-ddTHH:mm:ss", false, true, false),
("yyyyMMddHHmmssfff", true, false, true),
("yyyyMMddHHmmss", false, false, true),
("yyyyMMddTHHmmssfff", true, true, true),
("yyyyMMddTHHmmss", false, true, true)
};
[GlobalSetup]
public void Setup()
{
_dates = new DateTime[_count];
RandomDateTime _random = new(42);
for (int i = 0; i < _count; i++) _dates[i] = _random.Next();
}
[Benchmark(Baseline = true)]
public string[] System_DateTime_ToString()
{
string[] formated = new string[_count];
for (int i = 0; i < _count; i++)
formated[i] = _dates[i].ToString(data.BuiltinFormat);
return formated;
}
[Benchmark]
public string[] Extension_ToIsoString()
{
string[] formated = new string[_count];
for (int i = 0; i < _count; i++)
formated[i] = _dates[i].ToIsoString(data.Milliseconds, data.StrictDateTimeDelimiter, data.OmitDelimiters);
return formated;
}
}
@Guiorgy
Copy link
Author

Guiorgy commented Nov 14, 2023

Setup

  • OS: Windows 10 (10.0.19045.3570/22H2/2022Update)
  • CPU: AMD Ryzen 9 5950X
  • BenchmarkDotNet: v0.13.10

ToString

  • .NET SDK: 7.0.403
Method data Mean Error StdDev Ratio
System_DateTime_ToString yyyy-MM-dd HH:mm:ss 1,180.0 μs 11.12 μs 10.40 μs 1.00
Extension_ToIsoString yyyy-MM-dd HH:mm:ss 382.5 μs 7.31 μs 6.48 μs 0.32
System_DateTime_ToString yyyy-MM-dd HH:mm:ss.fff 2,043.1 μs 38.91 μs 41.64 μs 1.00
Extension_ToIsoString yyyy-MM-dd HH:mm:ss.fff 424.1 μs 8.42 μs 12.07 μs 0.21
System_DateTime_ToString yyyy-MM-ddTHH:mm:ss 1,281.8 μs 22.20 μs 24.67 μs 1.00
Extension_ToIsoString yyyy-MM-ddTHH:mm:ss 379.7 μs 7.23 μs 9.14 μs 0.30
System_DateTime_ToString yyyy-MM-ddTHH:mm:ss.fff 2,081.8 μs 24.65 μs 23.05 μs 1.00
Extension_ToIsoString yyyy-MM-ddTHH:mm:ss.fff 404.1 μs 4.35 μs 4.06 μs 0.19
System_DateTime_ToString yyyyMMddHHmmss 1,092.3 μs 21.66 μs 35.59 μs 1.00
Extension_ToIsoString yyyyMMddHHmmss 384.0 μs 3.07 μs 2.72 μs 0.35
System_DateTime_ToString yyyyMMddHHmmssfff 1,952.1 μs 14.98 μs 14.01 μs 1.00
Extension_ToIsoString yyyyMMddHHmmssfff 403.6 μs 2.18 μs 1.94 μs 0.21
System_DateTime_ToString yyyyMMddTHHmmss 1,062.4 μs 9.79 μs 9.16 μs 1.00
Extension_ToIsoString yyyyMMddTHHmmss 385.9 μs 4.64 μs 4.34 μs 0.36
System_DateTime_ToString yyyyMMddTHHmmssfff 1,921.2 μs 19.01 μs 17.78 μs 1.00
Extension_ToIsoString yyyyMMddTHHmmssfff 416.5 μs 2.74 μs 2.56 μs 0.22
  • .NET SDK: 8.0.100
Method data Mean Error StdDev Median Ratio RatioSD
System_DateTime_ToString yyyy-MM-dd HH:mm:ss 902.5 μs 17.76 μs 19.01 μs 908.4 μs 1.00 0.00
Extension_ToIsoString yyyy-MM-dd HH:mm:ss 275.8 μs 5.25 μs 6.45 μs 275.1 μs 0.31 0.01
System_DateTime_ToString yyyy-MM-dd HH:mm:ss.fff 1,897.5 μs 33.63 μs 31.46 μs 1,895.0 μs 1.00 0.00
Extension_ToIsoString yyyy-MM-dd HH:mm:ss.fff 322.2 μs 6.32 μs 6.76 μs 321.8 μs 0.17 0.00
System_DateTime_ToString yyyy-MM-ddTHH:mm:ss 893.7 μs 17.73 μs 43.82 μs 908.0 μs 1.00 0.00
Extension_ToIsoString yyyy-MM-ddTHH:mm:ss 277.9 μs 3.97 μs 3.10 μs 278.9 μs 0.33 0.01
System_DateTime_ToString yyyy-MM-ddTHH:mm:ss.fff 1,955.7 μs 29.68 μs 39.62 μs 1,937.7 μs 1.00 0.00
Extension_ToIsoString yyyy-MM-ddTHH:mm:ss.fff 316.1 μs 5.96 μs 5.28 μs 314.5 μs 0.16 0.00
System_DateTime_ToString yyyyMMddHHmmss 814.1 μs 16.22 μs 38.55 μs 802.5 μs 1.00 0.00
Extension_ToIsoString yyyyMMddHHmmss 289.6 μs 5.77 μs 9.80 μs 286.5 μs 0.35 0.02
System_DateTime_ToString yyyyMMddHHmmssfff 1,824.9 μs 18.83 μs 17.62 μs 1,826.2 μs 1.00 0.00
Extension_ToIsoString yyyyMMddHHmmssfff 277.1 μs 4.85 μs 5.39 μs 277.9 μs 0.15 0.00
System_DateTime_ToString yyyyMMddTHHmmss 822.1 μs 14.26 μs 18.03 μs 828.4 μs 1.00 0.00
Extension_ToIsoString yyyyMMddTHHmmss 285.5 μs 5.53 μs 5.68 μs 285.9 μs 0.35 0.01
System_DateTime_ToString yyyyMMddTHHmmssfff 1,871.4 μs 30.77 μs 27.28 μs 1,876.1 μs 1.00 0.00
Extension_ToIsoString yyyyMMddTHHmmssfff 328.2 μs 6.52 μs 5.78 μs 327.7 μs 0.18 0.00

TryParse

  • .NET SDK: 7.0.403
Method data Mean Error StdDev Ratio
System_DateTime_TryParseExact yyyy-MM-ddHH:mm:ss 1,949.2 μs 23.88 μs 22.33 μs 1.00
Extension_TryParseIsoDateTime yyyy-MM-ddHH:mm:ss 251.5 μs 2.92 μs 2.58 μs 0.13
System_DateTime_TryParseExact yyyy-MM-ddHH:mm:ss.fff 2,162.6 μs 41.16 μs 38.50 μs 1.00
Extension_TryParseIsoDateTime yyyy-MM-ddHH:mm:ss.fff 275.6 μs 3.23 μs 3.02 μs 0.13
System_DateTime_TryParseExact yyyy-MM-ddTHH:mm:ss 2,174.1 μs 37.02 μs 32.82 μs 1.00
Extension_TryParseIsoDateTime yyyy-MM-ddTHH:mm:ss 247.9 μs 2.44 μs 2.28 μs 0.11
System_DateTime_TryParseExact yyyy-MM-ddTHH:mm:ss.fff 2,389.9 μs 29.52 μs 26.17 μs 1.00
Extension_TryParseIsoDateTime yyyy-MM-ddTHH:mm:ss.fff 271.9 μs 1.46 μs 1.30 μs 0.11
System_DateTime_TryParseExact yyyyMMddHHmmss 1,214.2 μs 13.10 μs 10.94 μs 1.00
Extension_TryParseIsoDateTime yyyyMMddHHmmss 249.8 μs 3.00 μs 2.81 μs 0.21
System_DateTime_TryParseExact yyyyMMddHHmmssfff 1,369.4 μs 9.95 μs 9.31 μs 1.00
Extension_TryParseIsoDateTime yyyyMMddHHmmssfff 276.0 μs 1.83 μs 1.63 μs 0.20
System_DateTime_TryParseExact yyyyMMddTHHmmss 1,488.0 μs 14.19 μs 13.27 μs 1.00
Extension_TryParseIsoDateTime yyyyMMddTHHmmss 250.1 μs 3.07 μs 2.87 μs 0.17
System_DateTime_TryParseExact yyyyMMddTHHmmssfff 1,650.3 μs 18.11 μs 16.94 μs 1.00
Extension_TryParseIsoDateTime yyyyMMddTHHmmssfff 275.7 μs 2.18 μs 1.82 μs 0.17
  • .NET SDK: 8.0.100
Method data Mean Error StdDev Ratio
System_DateTime_TryParseExact yyyy-MM-ddHH:mm:ss 2,356.7 μs 45.84 μs 70.00 μs 1.00
Extension_TryParseIsoDateTime yyyy-MM-ddHH:mm:ss 261.8 μs 5.23 μs 6.42 μs 0.11
System_DateTime_TryParseExact yyyy-MM-ddHH:mm:ss.fff 2,685.9 μs 50.06 μs 49.16 μs 1.00
Extension_TryParseIsoDateTime yyyy-MM-ddHH:mm:ss.fff 295.4 μs 5.00 μs 4.68 μs 0.11
System_DateTime_TryParseExact yyyy-MM-ddTHH:mm:ss 2,710.9 μs 50.32 μs 47.07 μs 1.00
Extension_TryParseIsoDateTime yyyy-MM-ddTHH:mm:ss 254.7 μs 5.01 μs 5.36 μs 0.09
System_DateTime_TryParseExact yyyy-MM-ddTHH:mm:ss.fff 3,123.3 μs 46.24 μs 43.25 μs 1.00
Extension_TryParseIsoDateTime yyyy-MM-ddTHH:mm:ss.fff 283.5 μs 5.60 μs 7.08 μs 0.09
System_DateTime_TryParseExact yyyyMMddHHmmss 1,417.9 μs 26.54 μs 26.07 μs 1.00
Extension_TryParseIsoDateTime yyyyMMddHHmmss 244.6 μs 4.66 μs 4.36 μs 0.17
System_DateTime_TryParseExact yyyyMMddHHmmssfff 1,656.7 μs 25.39 μs 23.75 μs 1.00
Extension_TryParseIsoDateTime yyyyMMddHHmmssfff 264.6 μs 4.80 μs 4.49 μs 0.16
System_DateTime_TryParseExact yyyyMMddTHHmmss 1,819.7 μs 33.71 μs 31.54 μs 1.00
Extension_TryParseIsoDateTime yyyyMMddTHHmmss 258.3 μs 5.12 μs 4.79 μs 0.14
System_DateTime_TryParseExact yyyyMMddTHHmmssfff 2,025.0 μs 39.73 μs 39.02 μs 1.00
Extension_TryParseIsoDateTime yyyyMMddTHHmmssfff 289.7 μs 5.54 μs 5.18 μs 0.14

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment