Scott Hanselman

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

March 7, '19 Comments [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
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb
Monday, March 11, 2019 8:22:41 AM UTC
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.
Peter
Monday, March 11, 2019 10:40:13 AM UTC
Dates - the gift that keeps on giving ;)
Robert Armour
Wednesday, March 13, 2019 12:31:14 PM UTC
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!
El Dorko
Thursday, March 14, 2019 9:47:06 AM UTC
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)
mortb
Thursday, March 14, 2019 12:01:38 PM UTC
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!
Wolfgang
Thursday, March 14, 2019 8:35:54 PM UTC
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.
Sumo
Friday, March 15, 2019 8:04:27 AM UTC
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!
Richard Price
Monday, March 18, 2019 1:47:10 PM UTC
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.
David Vivash
Comments are closed.

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