C# – Parsing a DateTime string with a custom format

In most cases when you need to parse a datetime string with a custom format, you can pass in the format specifier and use DateTime.TryParseExact() (or ParseExact()), like this:

public DateTime? ParseDate(string date) { if (DateTime.TryParseExact(date, "M/d/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime dt)) { return dt; } return null; }
Code language: C# (cs)

This is using the format specifier “M/d/yyyy”.

  • M = 1-2 digit month.
  • d = 1-2 digit day.
  • yyyy = 4 digit year.

The following code uses use this method:

Console.WriteLine($"Parsed 1/1/2021 into {ParseDate("1/1/2021")}"); Console.WriteLine($"Parsed 01/01/2021 into {ParseDate("01/01/2021")}");
Code language: C# (cs)

This outputs the following:

Parsed 1/1/2021 into 1/1/2021 12:00:00 AM Parsed 01/01/2021 into 1/1/2021 12:00:00 AM
Code language: plaintext (plaintext)

Notice that it was able to handle month “1” and “01”, because “M” is a 1-2 month digit specifier. When you’re passing in the format specifier, IntelliSense will pop up a full list of possible format specifier values and a description of what they do (note: I’m using VS2019). You can also refer to this this MSDN page about all of the possible format specifiers.

Parsing a two-digit year

We all know it’s a bad idea to use two-digit years. When you use a two-digit year, you lose information and have to guess what four-digit year it represents.

When you parse a two-digit year with DateTime.ParseExact(), it uses CultureInfo.Calendar.TwoDigitYearMax to determine how to parse it into a four-digit year. The default TwoDigitYearMax on my system right now is 2049. You can pass in a CultureInfo and set TwoDigitYearMax to whatever value makes sense in your scenario.

Here’s an example. Let’s say I need to parse “9912” into “yyMM” and I know I’m dealing with future dates in the current century. If I let it use the default TwoDigitYearMax, it will parse this into “12/1/1999”. I really want it to parse into “12/1/2099”, so I need to set TwoDigitYearMax=2100, like this:

string date = "9912"; CultureInfo culture = new CultureInfo("en-US"); culture.Calendar.TwoDigitYearMax = 2100; if (DateTime.TryParseExact(date, "yyMM", culture, DateTimeStyles.None, out DateTime dt)) { Console.WriteLine($"Parsed {date} into {dt}"); } else { Console.WriteLine($"Unable to parse {date}"); }
Code language: C# (cs)

This output the following:

Parsed 9912 into 12/1/2099 12:00:00 AM
Code language: plaintext (plaintext)

The current year is 2021. What if I want to assume the two-digit year always starts at the current year? I can set TwoDigitYearMax to the current year + 99, like this:

string date = "2112"; CultureInfo culture = new CultureInfo("en-US"); culture.Calendar.TwoDigitYearMax = DateTime.Now.Year + 99; if (DateTime.TryParseExact(date, "yyMM", culture, DateTimeStyles.None, out DateTime dt)) { Console.WriteLine($"Parsed {date} into {dt}"); } else { Console.WriteLine($"Unable to parse {date}"); }
Code language: C# (cs)

This output the following:

Parsed 2112 into 12/1/2021 12:00:00 AM
Code language: plaintext (plaintext)

Dealing with uncertainty with a two-digit year

In the examples above I mentioned that I knew I was dealing with future dates. What if you’re dealing with dates that could be in either the future or past, or have more than a 100 year range?

I can think of two examples:

  • Birthdates
  • Expiration dates

If you were parsing data with birthdates that had two-digit years, you won’t be able to say with 100% certainty that you’re going to guess the correct four-digit year.

For example, let’s say you get the birthdate: “1/1/19”. Logically, all birthdates will be in the past, so you could set the TwoDigitYearMax = the current year of 2021. But this birthdate could realistically be either “1/1/1999” or “1/1/1919”, since there are definitely people who are over 100 years old.

How would you deal with this? My recommendation would be, whenever there is uncertainty involved, have a person double-check the results and confirm the year. This is the problem with two-digit years – there is always a chance you guessed the wrong year.

Leave a Comment