Tuesday, January 14, 2014

DateTime.Parse vs DateTime.ParseExact for culture issues

I'm sure most of us savvy .NET developers have come across the dreaded issues that surround the inconsistent standards when working with multilingual / multicultured applications. Namely the sites that provide the opportunity for a user to change their language and/or culture for their convenience.

Dealing with different languages is one thing, but that in itself isn't so bad because it mainly deals with a resource file of some sort that allows mapping of one word (or a sentence) to a different word of a different language. The site can then replace those words where it finds them.

Dealing with data, and specifically dates on the other hand, is a completely different story.

Seriously, why did the Americans have to come up with a date format that doesn't even conform to itself!? Generally speaking, numbering systems work by having the larger metric unit at the front, then the second metric unit succeeding it, and so on (e.g. $15,432,67). Naturally you would expect the date structure to be the same so that the military format (yyyy/MM/dd) would be found wherever we deal with dates.

Even though the Australian format doesn't conform to this, it at least has consistency by having the reverse, whereby the smallest metric is found at the beginning of the sequence (dd/MM/yyyy).

The U.S. format, however, is an influence of their own language. It comes purely from a cultural perspective where they are naturally inclined to say "February the 15th" rather than "the 15th of February". That has lead to the demise of their date format which logically makes no sense (MM/dd/yyyy).

Regardless of the format, we are still faced with the dilemma of having to interpret this in code so that our data isn't corrupted by the front-end client machine's culture, and the server's culture, when the server-side code deals with the data.

You may find that you have a JQuery date picker that can help you "set the culture" as shown below:

$(".datepicker").datepicker({ dateFormat: "dd/mm/yy" });

The problem would arise once the user clicks submit and hits a server with the "en-US" culture.
The moment you write the following code, you will face some issues:

var date = DateTime.Parse(Request.Form["date"]);

One of two problems will arise:
  • the date conforms to either en-AU or en-US because the "day" is not greater than 12, and therefore will not complain when translating it into a month part.
  • a FormatException will occur because the day is considered month and is invalid if greater than 12.
The way to work around this so as to Parse the date into the current culture of the server, but based on the culture you are expecting the string to be coming in from the client side.

var date = DateTime.ParseExact(Request.Form["date"], "dd/MM/yyyy", CultureInfo.CurrentCulture);

What this does is define the structure of the string that is passed into the first parameter, based on the format of the second parameter. Once it maps the string exactly as defined in the second parameter, it can then convert it successfully to a DateTime type based on the third parameter. The CurrentCulture can define the timezone as well as the format, and any other relevant metadata.