-
Notifications
You must be signed in to change notification settings - Fork 4.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consider increase to TwoDigitYearMax #75148
Comments
Tagging subscribers to this area: @dotnet/area-system-globalization Issue DetailsTwoDigitYearMax is the century assumption we use when parsing a date string with a two digit year. Currently all our calendars seem to use 29. 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 --
gives
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 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
Prior art: Python uses a cutoff of 68
|
My preference here is trying to read the settings when running on Windows. And we change the default values to |
RPGLE uses a cutoff of 39 (In case we should possibly consider interactions with some "legacy" systems) |
A (weak) argument for 69 is that the start of the Unix epoch is 1970. |
Hi all,
|
@cdbullard you would be welcome, but I'm not sure there's consensus yet on what number to choose. Also on whether we should load the Windows OS value - if the date being parsed is directly from the user (e.g. a UI) then it would make sense, but if the code is processing data from a file one would likely want to have consistent behavior across OS. @dotnet/area-system-globalization would probably best make this call. |
If a change didn't break a unit test, it probably would mean we are missing necessary unit tests and should add them. |
Before using ICU and when using NLS, Core the .NET and .NET Framework depended on the system settings which can be changed by the users. This means parsing dates with 2 digits years will still be dependent on that. Usually, users parsing dates with 2 digits year and want to ensure the consistent results will set the Calendar.TwoDigitYearMax before parsing, something like: CultureInfo ci = (CultureInfo)CultureInfo.InvariantCulture.Clone();
ci.DateTimeFormat.Calendar.TwoDigitYearMax = 2049;
Console.WriteLine($"{DateTime.Parse("2/11/30", ci)}"); Windows has already changed the default too and that affected .NET Framework and we didn't hear any complaints. This can tell the breaking change is really scoped. I am inclining to what I said in #75148 (comment). |
@cdbullard are you still interested in making this change? We can help guide you as needed. |
I apologize for the delay! I am happy to give it a shot--I have created a PR (#76848) with some initial changes, but have not yet attempted any unit test updates (was not sure exactly which ones to consider for this change). Please have a look when you get a chance and I'll try to quickly respond to any feedback. |
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 --
gives
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
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.
The text was updated successfully, but these errors were encountered: