简体   繁体   中英

.NET - Canadian DateTime Format Bug

I currently have an application that needs to support multiple cultures. A date string is being passed in and is being parsed to a DateTime object. To allow for multiple cultures I am first setting the thread's culture and UICulture.

Here is an example of my code as it is:

First I set the culture for this thread. This is passed in on the URL (ex. en-us, en-ca, fr-ca):

CultureInfo ci = new CultureInfo(culture, false);
Thread.CurrentThread.CurrentUICulture = ci;
Thread.CurrentThread.CurrentCulture = ci;

I then take a date string that is also passed in on the URL and convert it to a DateTime. Depending on the culture the date will be passed in as mm/dd/yyyy or dd/mm/yyyy.

I parse the date strings with the following code:

DateTime DateTimeObject;
bool validDate = DateTime.TryParse(DateStringFromURL, Thread.CurrentThread.CurrentCulture, DateTimeStyles.None, out DateTimeObject);

The TryParse works for most cultures and out comes a valid datetime object. A problem arises with en-ca and fr-ca though. If the wrong format is passed in, the datestring does not parse correctly.

The following shows which format .NET seems to expect for each culture:

         dd/MM/yyyy    MM/dd/yyyy
EN-CA      Valid        Invalid
FR-CA     Invalid        Valid

EDIT: To be more exact here are the examples causing me problems:

For EN-CA:

DateTime.Parse("26/08/2014") //VALID
DateTime.Parse("08/26/2014") //EXCEPTION THROWN

For FR-CA:

DateTime.Parse("26/08/2014") //EXCEPTION THROWN
DateTime.Parse("08/26/2014") //VALID

This is backwards from how other systems treat this culture's date formatting.

Why are the formats seemingly backwards? Is this a bug with .NET 4.5?

Any and all help would be appreciated, thanks.

NOTE: .NET Version 4.5

You should probably look into Invariant culture. That is what you should use for your URL passing. You can use the local culture for display purposes on the client.

Typically, whenever you are storing data (for example, in a database or file ) it is best to use the Invariant culture. When displaying data you can use the local culture. When passing data around, you want to use Invariant culture.

Read more here .

I believe your assumptions are wrong. This console application:

static void Main(string[] args)
{
    var enca = new CultureInfo("en-ca", false);
    var frca = new CultureInfo("fr-ca", false);

    Console.WriteLine("enca dd/MM/yyyy: " + ParseDate("26/08/2014", enca));
    Console.WriteLine("enca MM/dd/yyyy: " + ParseDate("08/26/2014", enca));

    Console.WriteLine("frca dd/MM/yyyy: " + ParseDate("26/08/2014", frca));
    Console.WriteLine("frca MM/dd/yyyy: " + ParseDate("08/26/2014", frca));

    Console.ReadKey();
}

static bool ParseDate(string date, CultureInfo culture)
{
    try
    {
        DateTime.Parse(date, culture);
        return true;
    }
    catch
    {
        return false;
    }
}

Has output:

enca dd/MM/yyyy: False
enca MM/dd/yyyy: True
frca dd/MM/yyyy: False
frca MM/dd/yyyy: True

There is definitely a bug in data parsing for Canadian culture. If you try following having CurrentCulture = "en-CA":

DateTime.ParseExact("2014/09/20", "yyyy/MM/dd", Thread.CurrentThread.CurrentCulture)

you'll get following exception:

A first chance exception of type 'System.FormatException' occurred in mscorlib.dll

works fine if you replace / with something else, like - or with InvariantCulture.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM