Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange behaviour of DateTime.Parse

Tags:

c#

.net

datetime

We have a large application that (unfortunately) use DateTime.Parse(text) a lot. Replacing DateTime.Parse with something better is not an option right now.

Recently I upgraded windows (to windows 10) and started to have issues. According to the documentation at https://msdn.microsoft.com/en-us/library/system.datetime.parse(v=vs.110).aspx the method should use CultureInfo.CurrentCulture as default formatprovider. This does not appear to be the case on my pc, unless I'm missing something obvious.

The following code calls a function two times, first without changing any culture settings, then with norwegian culture set on both the culture and ui-culture. For some reason it is able to parse a text given in en-US format (M/d/yyyy) in both cases, but it is unable to parse a date in the format expected by CultureInfo.

What is going on here? I hope I'm missing something obvious..

class Program
{
    static void Main(string[] args)
    {
        var norwegianCulture = new CultureInfo("nb-NO");

        Console.WriteLine("First");
        ParseDates();

        Console.WriteLine("\nSecond");
        Thread.CurrentThread.CurrentUICulture = norwegianCulture;
        ParseDates();

        Console.ReadKey();
    }

    private static void ParseDates()
    {
        Console.WriteLine($"CultureInfo.CurrentCulture: {CultureInfo.CurrentCulture}");
        Console.WriteLine($"CultureInfo.CurrentUICulture: {CultureInfo.CurrentUICulture}");
        Console.WriteLine($"{Thread.CurrentThread.CurrentCulture} - CurrentCulture - {Thread.CurrentThread.CurrentCulture.DateTimeFormat.ShortDatePattern}");
        Console.WriteLine($"{Thread.CurrentThread.CurrentUICulture} - CurrentUICulture - {Thread.CurrentThread.CurrentUICulture.DateTimeFormat.ShortDatePattern}");
        var shortDateString = new DateTime(2015, 9, 5).ToShortDateString();
        WriteParsedDate(shortDateString);
        WriteParsedDate("1/2/2015");
        Console.WriteLine();
    }

    private static void WriteParsedDate(string shortDateString)
    {
        try
        {
            var d = DateTime.Parse(shortDateString, CultureInfo.CurrentCulture);
            Console.WriteLine($"The text {shortDateString} parsed to Year: {d.Year}, Month: {d.Month}, Day: {d.Day}");
        }
        catch (Exception e)
        {
            Console.WriteLine($"The text {shortDateString} could not be parsed.");
            Console.WriteLine($"Error: {e.Message}");
        }
    }
}

Writes this to the console:

First
CultureInfo.CurrentCulture: nb-NO
CultureInfo.CurrentUICulture: en-US
nb-NO - CurrentCulture - dd.MM.yyyy
en-US - CurrentUICulture - M/d/yyyy
The text 05.09.2015 could not be parsed.
Error: String was not recognized as a valid DateTime.
The text 1/2/2015 parsed to Year: 2015, Month: 2, Day: 1


Second
CultureInfo.CurrentCulture: nb-NO
CultureInfo.CurrentUICulture: nb-NO
nb-NO - CurrentCulture - dd.MM.yyyy
nb-NO - CurrentUICulture - dd.MM.yyyy
The text 05.09.2015 could not be parsed.
Error: Strengen ble ikke gjenkjent som en gyldig DateTime.
The text 1/2/2015 parsed to Year: 2015, Month: 2, Day: 1

PARTIAL WORKAROUND

As shf301 writes, this is due to a bug in Windows 10.

I managed to get it to work by changing the time seperator from "." to ":" - As in older versions of Windows. I guess it's working with that change since we are only using the users settings, and not loading/specifying them manually.

like image 520
Steinar Herland Avatar asked Sep 26 '22 19:09

Steinar Herland


1 Answers

This is an open bug listed Connect. It appears that date parsing is failing for any locale that has the same separator's for date and time.

Estonian (Estonia)
Finnish (Finland)
Norwegian Bokmål (Norway)
Norwegian Bokmål (Svalbard and Jan Mayen)
Serbian (Cyrillic, Kosovo)
Serbian (Latin, Montenegro)
Serbian (Latin, Serbia)
Serbian (Latin, Kosovo)

Your example never parses nor format's the date using US settings. First of all DateTime.Parse without an IFormatProvider uses CurrentCulture and not CurrentUICulture and second you explicitly pass CurrentCulture into DateTime.Parse. That's why the output in both cases is exactly the same.

Had "1/2/2015" been parsed using en-US rules, it would have output:

The text 1/2/2015 parsed to Year: 2015, Month: 1, Day: 2

DateTime.Parse is just being clever and assuming that you used a / as a date separator instead of a . and parsing the date as d/M/yyyy.

Until this is fixed you will unfortunately have to changed your calls to DateTime.Parse. Or switch to .Net 3.5 or earlier which is not affected.

like image 127
shf301 Avatar answered Sep 30 '22 07:09

shf301