-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Description
TwoDigitYearMax is the century assumption we use when parsing a date string with a two digit year. Currently all our calendars seem to use 29, ie., 29 implies 2029 but 30 implies 1930. This suggests back in Windows 98, Windows chose 29 and that's where we got 29 from. At least back to 2.0, we seem to have been defaulting to 29 if we couldn't read the system setting. We no longer read Windows NLS settings by default, and ICU does not have such data, so the default of 29 applies almost everywhere, unless overridden in code.
so eg --
var c = CultureInfo.GetCultureInfo("en-US").Calendar;
Console.WriteLine($"{c.GetType()} calendar has TwoDigitYearMax of {c.TwoDigitYearMax}");
var dt = DateOnly.Parse("10/10/28");
Console.WriteLine(dt);
dt = DateOnly.Parse("10/10/35");
Console.WriteLine(dt);gives
System.Globalization.GregorianCalendar calendar has TwoDigitYearMax of 2029
10/10/2028
10/10/1935
While Excel still uses 29, Windows now has moved to 49 for at least some calendars. Currently on my Windows box, with the en-US culture and Gregorian calendar, if I run with DOTNET_SYSTEM_GLOBALIZATION_USENLS=1 then I get System.Globalization.GregorianCalendar calendar has TwoDigitYearMax of 2049. Windows allows you to change this setting although it's deep in the UI:
Now that we're controlling this value by default on all OS, the value has become much more important than on .NET Framework. We may choose to make a similar decision as we are approaching 2030. The closer we get to 2030 the more likely it will be that if I type "1/1/30" I mean 2030.
Options
- Leave as-is. Document that users should explicitly increase TwoDigitYearMax if they parse 2-digit years and the data has a different assumption.
- Leave as-is, but on Windows when using ICU, call specially into NLS for the two digit cutoff, since ICU has no value. This makes Windows inconsistent with other OS, by default.
- Change to something larger that gives wiggle room, eg 49 (there appears to be no consensus, see below) possibly with a global config switch to revert to 29, similar to ICU/NLS. Doc as a breaking change.
Prior art:
Python uses a cutoff of 68
Javascript uses a cutoff of 49
Java seems to be 99
Golang seems to be 68
Nodatime seems to be 30
Excel uses 29. It respects Windows settings on Windows, but only for user input.
Rust uses 69 in at least one instance - I experimented naively with something like NaiveDate::parse_from_str("70-09-05", "%y-%m-%d")
Perl - not sure, I found one reference to 50, another package (DateTime::Format::Flexible) uses 69
RFC3339 just says the internet should always use 4 digit years.
Perhaps there are other relevant standards/RFC's ?
I don't have Linux/macOS handy. Do they have similar system settings, possibly user modifiable, and separate from ICU? If so, possibly we should read those values on all OS. This would however further increase the possibility of introducing a bug when, eg., developing on macOS and deploying on Linux.
