mattjohnsonpint / TimeZoneNames

Provides a complete source of localized time zone names and abbreviations.
MIT License
196 stars 32 forks source link

TZNames.GetCountryNames() throws ArgumentNullException #31

Closed lundmikkel closed 6 years ago

lundmikkel commented 6 years ago

I'm having a hard time figuring this out. I'm trying to get all country names for a language, but TZNames.GetCountryNames() keeps throwing an exception (I've reduced the code to something as simple as TZNames.GetCountryNames( "en" )).

The weird thing is that it only throws an exception in my actual code, but not in my test code! I tried to take a picture of the exception message:

tznames

According to the stack trace it happens in GetLanguageKey(), but I couldn't figure out why.

at System.Collections.Generic.Dictionary`2.FindEntry(TKey key)
at TimeZoneNames.TZNames.GetLanguageKey(String languageCode)
at TimeZoneNames.TZNames.GetCountryNames(String languageCode)
mattjohnsonpint commented 6 years ago

Interesting. I cannot reproduce though.

Can you tell me more about your environment? What version of .NET are you targeting? What version of Newtonsoft.Json is in your project? What version of Visual Studio are you debugging with?

Thanks.

lundmikkel commented 6 years ago

So I cannot reproduce it either; that is, I'm only able to reproduce it in my particular solution, but I cannot create a minimal working example that fails.

I'm developing on Windows 10 in VS 15.3.5, targeting .NET 4.6.1 (using the new project structure) with Newtonsoft.Json 10.0.3.

I managed to debug the code using a locally compiled version of the TimeZoneNames project and its pdb. The problem seems to be that Data is empty! CldrLanguageData is empty, so GetLanguageSubkey() is called and returns null since keyParts only contains a single element ("en"). So, there seems to be two problems: GetLanguageKey doesn't guard properly for null keys returned from GetLanguageSubkey(), but more importantly, Data doesn't get populated.

image

lundmikkel commented 6 years ago

Okay, so I think I've figured it out. The problem seems to be caused by TimeZoneData.Load() using JsonSerializer.CreateDefault(). We override JsonConvert.DefaultSettings in our WebApiConfig file to use snake-case property encoding (MyProperty -> my_property), among others.

Changing JsonSerializer.CreateDefault() to JsonSerializer.Create() fixes the problem.

mattjohnsonpint commented 6 years ago

Nice find! I think I've been just used to using CreateDefault instinctively. 😉 And thanks for the PR. I'll merge and ship it in the next few days or so.