runtime: DateTimeOffset does not parse a valid ISO-8601 datetime string

Description

DateTimeOffset does not correctly parse a valid ISO-8601 datetime string. Wikipedia claims the current ISO-8601 definition prefers a comma as the decimal mark for the lowest time order present: Screenshot 2021-04-23 163058

However, DateTimeOffset is not capable of parsing a datetime string with a comma decimal mark for the lowest time order when that time order is seconds:

        static void Main(string[] args)
        {
            static void Test()
            {
                var dateString = "2021-04-23T13:04:17,307642270+02:00";

                DateTimeOffset date = DateTimeOffset.MinValue;

                try
                {
                    date = DateTimeOffset.Parse(dateString);
                }
                catch (Exception e)
                {
                    Console.WriteLine($"date: {e.Message}");
                }
                finally
                {
                    Console.WriteLine($"date: {date}");
                }
            }

            Test();
        }

Configuration

Code above running on .NET 5.0.202 on Windows 20H2 (OS Build 19042.928).

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 15 (8 by maintainers)

Commits related to this issue

Most upvoted comments

Although DateTimeOffset.Parse (as opposed to ParseExact) allows excess digits of fractional seconds, it looks like you cannot change the separator character there by cloning CultureInfo.InvariantCulture and then setting its NumberFormat.NumberDecimalSeparator or anything else, because . is hardcoded near the ParseFraction calls:

https://github.com/dotnet/runtime/blob/2f740adc1457e8a28c1c072993b66f515977eb51/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeParse.cs#L647-L654 https://github.com/dotnet/runtime/blob/2f740adc1457e8a28c1c072993b66f515977eb51/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeParse.cs#L2980-L2982

If .NET removed the following length check, then I think you could use “FFFFFFFFF” (upper case so that it also accepts fewer than nine digits): https://github.com/dotnet/runtime/blob/2f740adc1457e8a28c1c072993b66f515977eb51/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeParse.cs#L4052

Besides, it is a bit misleading that failing the length check causes result.SetBadDateTimeFailure() to be called even though the problem is in the format string (can never match any input) and not in the input string.

“2021-04-23T13:04:17,307642270+02:00” has nine digits of fractional seconds (i.e. nanoseconds precision), but “fffffff” only allows seven digits, and DateTimeOffset does not support “fffffffff” as a custom format specifier. ☹

@chris-steema my proposal was trying to avoid allocating any new string. but if this is not issue to you, then that is ok to do what you have proposed.