Windows 10 breaks .NET date parsing in certain locales

If you’re running an app in Windows 10 or Windows Server 2016 under .NET 4.0 or newer, you will see date parsing errors under seven locales. This blog post will explain the issue, the fix (it’s coming!) and the workarounds.

First off, I would like to thank the .NET Framework team at Microsoft for fixing this speedily. Jay Schmelzer and his people also helped by giving me all the details and proofreading this blog post. That said, my recommendations and any possible mistakes are still my own, not theirs. :-)

Edit 2015-10-09: This has been fixed now. The updates are as follows:

  • KB3093266 – Windows 10
  • KB3088956 – Windows Server 2012 R2 and Windows 8.1
  • KB3088955 – Windows Server 2012 and Windows 8
  • KB3088957 – Windows 7 SP1, Windows Server 2008 SP2, Windows Server 2008 R2 SP1, and Windows Vista SP2

The issue

Windows 10 changes the date and time formatting settings for some cultures. Of particular concern are seven cultures for three different regions:

  • Finnish
  • Norwegian Bokmål (“Norway” and “Svalbard and Jan Mayen” variants)
  • Serbian (variants “Cyrillic, Kosovo”, “Latin, Montenegro”, “Latin, Serbia” and “Latin, Kosovo”).

For these seven cultures, Windows 10 changes the date and time separators to be the same. For example, in Finnish, the standard date format used to be 26.8.2015 21:08, while it is now 26.8.2015 21.08 – note the subtle change in the time separator.

Note that any change in separators can cause your code to break – for example, if you have written a parser that imports time-of-day values by relying on certain culture settings, you may find that your parsing logic no longer works. But the fact that the time separator changed to be the same as the date separator creates an issue far more insidious and severe.

In all currently released versions of .NET, the DateTime.Parse method has a shortcoming: It always fails to parse a date or a date+time combination in a culture where the date/time separators are the same character. This bug, together with Windows 10’s culture changes, breaks the previously hard rule of DateTime.Parse always being able to parse the culture’s default DateTime representation. Now, DateTime.Parse(DateTime.Now.ToString()) no longer works under the described conditions. Neither does DateTime.Parse(DateTime.Now.ToShortDateString()), which is somewhat counterintuitive since the changed time separator isn’t even involved, but true nonetheless – the parser thinks it’s parsing a time instead of a date.

If you own the callsite to DateTime.Parse, you can use ParseExact (see an example below in the workarounds section) and avoid the issue. In fact, using ParseExact is a best practice anyway, if you know the format you’re parsing from. But the real is problem is that almost all of .NET Framework relies on the assumption that default datetime representations survive format/parse roundtrips – and thus, many parts of .NET don’t use ParseExact.

The most problematic failures will occur in databinding and modelbinding code. You will find that WPF, WinForms and Modern (UWP) Apps will fail when binding dates to controls. ASP.NET MVC will fail on modelbinding from form input. It will simply be impossible to enter a valid date. Depending on your scenario, your application may throw FormatExceptions, your DateTime fields will always show errors and refuse to accept input, or your modelbound ASP.NET input will be empty.

Yes, that’s serious. That’s why we have this on Connect (for .NET Framework) and GitHub (for CoreCLR).

The fix (and what about previous .NET or Windows versions?)

Microsoft has fixed this issue in a forthcoming update to .NET 4.6. This patch is planned to ship in Windows 10’s September update. DateTime.Parse will be improved to deal with a scenario where the two separators are the same. The separators won’t change back, and the new separators may still break your code in other scenarios – but that’s not a Windows or .NET Framework bug.

How about previous versions of Windows? Since it was Windows 10 that introduced the new separators, you won’t hit this on older versions of Windows. Technically you could – if your system was running a custom locale with date/time separators set to the same character, but in practice custom locales are rare, and such custom locales probably nonexistent. At the moment, there are no plans to patch this separately for older Windows versions.

How about previous versions of .NET Framework? First off, you will not see this if you’re running an app on a version older than .NET 4.0. That is because .NET 4.0 is the first version of the Framework to use the OS culture data – versions before that carried their own regional settings, and they don’t contain cultures where date and time separator is the same character.

The workarounds

If you can wait until the update comes out, you don’t need to read the rest of this blog post. If you can’t, I’ll give you some ideas on what to do.

As I already stated, if you have an explicit DateTime.Parse call, replace it with ParseExact. That is fairly straightforward to do if you can special case the mentioned 7 cultures. For example, for a Finnish date-only field, you can do DateTime.Parse(stringToParse, "d.M.yyyy", CultureInfo.GetCultureInfo("fi-FI")).

For all the other scenarios, you need to apply the previous code fix… The trick is knowing where to do it.

  • For Windows Forms data binding, you need to set the Binding.Parse event to a logic that special cases the said cultures. For a big app, the problem is getting that set up for all the relevant bindings in your application. You might want to explore reflection or similar strategies for doing programmatic injection of custom parsers for all DateTime fields. If you already have custom parsers in place, good luck marrying these two together.
  • For WPF data binding, you might want to embed this into an IValueConverter (see tutorial). Again, finding all the necessary injection spots may be a headache.
  • For ASP.NET MVC, you need to write a custom ModelBinder. The nice thing here is that you are able to apply this binding easily to all DateTime/Nullable<DateTime> objects by just adding your binder to the ModelBinders collection in your application startup. However, it is important to remember that the default behavior for ASP.NET MVC is to use InvariantCulture for parsing HTTP GET request parameters but to use the CurrentCulture for HTTP POST parameters (more here).
  • If you are at the deployment end of the stick (i.e. trying to get those .NET apps to run on computers you administer), you can turn the custom locale approach to your benefit and create a locale that has separate date & time separators. You need to use Locale Builder for that – and yes, it works on Windows 10 even though the blog post only talks about 8.1. Of course, this doesn’t help you as a developer if you cannot enforce the custom locale on your customers.

If you come across other scenarios or have solutions to share, add a comment. Please let me know if you have other feedback / questions / clarifications as well. Thanks!

August 27, 2015 · Jouni Heikniemi · 52 Comments
Tags: ,  · Posted in: .NET

52 Responses

  1. Pandora forgot password no email - August 12, 2019

    Great work. Thank you so much for sharing this such a nice information here in the blog for visitors.

  2. Firesticknosignal - September 13, 2019

    I love to read your blog this is so informative. Thanks for posting this kind of information. If you experience issues regarding Amazon Fire Stick device you can contact our experts or visit our website – https://www.firesticknosignal.com

Leave a Reply