Scott Hanselman

How to parse string dates with a two digit year and split on the right century in C#

March 08, 2019 Comment on this post [8] Posted in DotNetCore | Learning .NET
Sponsored By

So you've been asked to parse some dates, except the years are two digit years. For example, dates like "12 Jun 30" are ambiguous...or are they?

If "12 Jun 30" is intended to express a birthday, given it's 2019 as the of writing of this post, we can assume it means 1930. But if the input is "12 Jun 18" is that last year, or is that a 101 year old person's birthday?

Enter the Calendar.TwoDigitYearMax property.

For example, if this property is set to 2029, the 100-year range is from 1930 to 2029. Therefore, a 2-digit value of 30 is interpreted as 1930, while a 2-digit value of 29 is interpreted as 2029.

The initial value for this property comes out of the DEPTHS of the region and languages portion of the Control Panel. Note way down there in "additional date, time, & regional settings" in the "more settings" and "date" tab, there's a setting that (currently) splits on 1950 and 2049.

Two Digit Year regional settings

If you're writing a server-side app that parses two digit dates you'll want to be conscious and explicit about what behavior you WANT so that you're not surprised.

Setting TwoDigitYearMax sets a 100 year RANGE that your two digit years will be interpreted to be within. You can also just change it on the current thread's current culture's calendar. It's up to you.

For example, this little app:

string dateString = "12 Jun 30"; //from user input
DateTime result;
CultureInfo culture = new CultureInfo("en-US");
DateTime.TryParse(dateString, culture, DateTimeStyles.None, out result);
Console.WriteLine(result.ToLongDateString());

culture.Calendar.TwoDigitYearMax = 2099;

DateTime.TryParse(dateString, culture, DateTimeStyles.None, out result);
Console.WriteLine(result.ToLongDateString());

gives this output:

Thursday, June 12, 1930
Wednesday, June 12, 2030

Note that I've changed TwoDigitYearMax from and moved it up to the 1999-2099 range so "30" is assumed to be 2030, within that 100 year range.

Hope this helps!


Sponsor: Stop wasting time trying to track down the cause of bugs. Sentry.io provides full stack error tracking that lets you monitor and fix problems in real time. If you can program it, we can make it far easier to fix any errors you encounter with it.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Hosting By
Hosted in an Azure App Service
March 11, 2019 12:22
This allows you to override the OS default split which is great, but ultimately the problem remains you have to make an assumption about the split because of lack of data.

That's since the Y2K issue I've always written physically and electronically as a 4 digit year.
March 11, 2019 14:40
Dates - the gift that keeps on giving ;)
March 13, 2019 16:31
So... different users may end up with different dates parsed in their applications, if they have changed this value (or if the default can be different)… This is going to be fun :-) Not that I have a better alternative, this stuff with dates and times parsing is complicated beyond all of humanity!
March 14, 2019 13:47
Or, if the world just started using ISO-8601, dates would be less of a problem. Most of the time you'd write dates like 2019-03-14 (year month day)
March 14, 2019 16:01
In my opinion trying to do DateTime stuff with only a 2 digit year should be severely outlawed and if somebody tries to do this the whole data center should go up in flames. In 2019 over 18 years AFTER the Y2K "bug" everybody should have learned from it. In the 1970s people had some form of "excuse" but today it IS criminal to save the year only with 2 digits. For me parsing a date with only a 2 digit year should throw an exception with the compiler begging the dev of not being abused in this way!
March 15, 2019 0:35
So, in your example, how is 99 handled? Your range of 1999-2099 allows for a 2-digit year of 99 which now has ambiguity. Though, I agree with Wolfgang. Stuff should burn down for using a 2-digit year.
March 15, 2019 12:04
I wonder where the defaults and configuration for that comes from in .Net Core... assuming of course that's in .Net Core to begin with!
March 18, 2019 17:47
Note that I've changed TwoDigitYearMax from and moved it up to the 1999-2099 range


I think you've actually changed the range to 2000-2099, rather than 1999-2099.

Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.