Converting a string to DateTime can be unexpectedly tricky: given that the  same date can be represented in a wide myriad of formats, simple tasks – like parsing data from text files – can lead to unexpected results.

In this post we will see the most commonly used methods to convert strings into DateTime objects, and some of the issues we can run in.

Convert a String to DateTime using DateTime.Parse

The Parse method takes a string parameter and converts it to a DateTime object:

DateTime.Parse(String value);

Let’s start with the string “05/12/2018”. We will use the Parse method above to convert it to a proper date:

String myDate = "05/12/2018";
DateTime date = DateTime.Parse(myDate);
Console.WriteLine(date.ToString("dd/MMM/yyyy"));

String was not recognized as a valid DateTime

Unsurprisingly the code above will print to the console the expected 12/May/2018 value. So far so good. Notice though that in order to get that output the Parse method has to do some assumptions about the date Format.

For example, some countries – like the United States – use the Month/Day/Year date format, but some other countries – like France, Spain or the U.K – use the Day/Month/Year. Therefore Spanish citizens would expect the “05/12/2018” string to be converted to December 12th. Furthermore, take another date like the 15th May: Spanish users will introduce that date as “15/05/2018”. Now, the code we used a moment ago will not fare so well:

String myDate = "15/05/2018";
DateTime date = DateTime.Parse(myDate);
Console.WriteLine(date.ToString("dd/MMM/yyyy"));

Indeed, instead of the expected DateTime now we got a nasty exception:

Run-time exception (line 9): String was not recognized as a valid DateTime.

The moral of this story is that when parsing a string as a date we need to know the format used, and we may need to indicate explicitly to the Parse method the Culture (information about the regional configuration) that it needs to use.

So in this case we need to use this overload of the DateTime.Parse method:

DateTime.Parse(String value, IFormatProvider provider);
CultureInfo culture = new CultureInfo("es-ES");
String myDate = "15/05/2018";
DateTime date = DateTime.Parse(myDate,culture);
Console.WriteLine(date.ToString("dd/MMM/yyyy"));

And this time we get the expected output 15/May/2018.

DateTime.Parse vs DateTime.ParseExact

It may seem that having taking the regional configuration into account we have reached the end of our Date conversion woes, correct? Alas, no.The devil is in the details, after all, and we have a few tiny details left to care about.

As you know in a same regional format we may write the same date in many different ways. For example, supposing we are using the USA format, “05/12/2018” can be written like this:

  • 05/12/2018
  • Saturday, May 12 2018
  • Sat, 12 May 2018
  • Sat, May 12 2018
  • 2018-05-12

… and a great more number of ways. When trying to read dates stored as strings in any kind of file or database,  we found out that third party applications can be very creative when it comes to save dates as strings.

So let’s imagine that we got a third party program that generates text files with string dates that another application needs to read, and convert to DateTime objects. The catch is that this third party software is using a slightly peculiar format date and 01/12/2018 has become 12/Jan./18. We try to process it in the same manner we did before:

CultureInfo culture = new CultureInfo("en-US");
String myDate = "12/<em>Jan</em>./18";
DateTime date = DateTime.Parse(myDate,culture);
Console.WriteLine(date.ToString("dd/MMM/yyyy"));

And this time we encounter this already familiar exception:

Run-time exception (line 9): String was not recognized as a valid DateTime.

When we do have a not-standard string that .NET may be unable to interpret correctly we can use the ParseExact method specifying as a parameter the exact formatting string:

DateTime.ParseExact(string value, string format, IFormatProvider provider, DateTimeStyles style);
DateTime.ParseExact(string value, string[] formats, IFormatProvider provider, DateTimeStyles style);

As we see the ParseExact method differs from the Parse method in that we pass as a parameter the formatting used by the date, notice also this:

  • We have an overload that allow us to specify an array of acceptable formattings.
  • The point above is important because ParseExact is that: EXACT. If we pass a date string that does not match the specified format, we will encounter again the String was not recognized as a valid DateTime exception.

If we rewrite the code snippet using ParseExact, we can now parse the troublesome date string:

CultureInfo culture2 = new CultureInfo("en-US");
String myDate2 = "12/Jan./18";
DateTime date = DateTime.ParseExact(myDate2, "d/MMM./yy",culture2, DateTimeStyles.None);
Console.WriteLine(date.ToString("dd/MM/yyyy"));

Parse vs TryParse, ParseExact vs TryParseExact

The DateTime.Parse and DateTime.ParseExact methods throw an exception when they fail to parse a String: therefore, we should wrap the code with a try/catch. An alternative is to use the TryParse/TryParseExact variants. Those methods do not throw an exception, and instead return a Boolean indicated if the conversion was successful or not.

Let’s see an example for TryParse:

DateTime convertedDate;
String myDate = "05/12/2018";

Boolean isValid = DateTime.TryParse(myDate, out convertedDate);
if (isValid)
    Console.WriteLine(convertedDate.ToString("dd/MMM/yyyy"));
Advertisements