I ran into a problem related to .NET timezone IDs in combination with XenApp, which can be reduced to the following snippet throwing a TimeZoneNotFoundException
(i.e. the call to TimeZoneInfo.FindSystemTimeZoneById
):
var tzLocal = TimeZoneInfo.Local;
var tzId = tzLocal.Id;
var tz = TimeZoneInfo.FindSystemTimeZoneById(tzId);
The exact exception text is:
System.TimeZoneNotFoundException:
The time zone ID 'Mitteleuropäische Zeit' was not found on the local computer.
at System.TimeZoneInfo.GetTimeZone(String id)
at System.TimeZoneInfo.FindSystemTimeZoneById(String id)
(Something similar happens in NodaTime 1.1, e.g. inside the call to NodaTime.DateTimeZoneProviders.Bcl.GetSystemDefault()
).
The strange thing is that TimeZoneInfo.Local.Id
seems to return the German name of the timezone, although the server is running with the language set to English and the timezone id should be language-neutral (see .Net TimeZoneInfo ID - Is it Windows Language Specific?). But the client's language is German... (Update/Clarification: the problem will not occur if client and server use the same language.)
What I think is going on here is:
- .NET calls
GetTimeZoneInformation
in kernel32.dll in order to retrieve the local timezone. - The API call gets intercepted by XenApp (see Is it possible to get a users timezone for an application hosted by Citrix XenApp?) because XenApp can be configured to use the client's local timezone (see http://mdaslam.wordpress.com/2010/01/05/xenapp-time-zone-setting/).
- The resulting
TIME_ZONE_INFORMATION
structure contains a German standard name (I checked this with p/invoke on the English XenApp server). - Since the
TIME_ZONE_INFORMATION
structure (see http://msdn.microsoft.com/en-us/library/windows/desktop/ms725481(v=vs.85).aspx) does not contain a language-neutral timezone identifier .NET fails to match the returned German timezone identifier to its local timezone "database" (with English names) and uses the (localized) standard name as a fallback identifier for the timezone. Ergo theTimeZoneInfo.Local.Id
contains the German name of the "local" timezone. - Then
TimeZoneInfo.FindSystemTimeZoneById
fails for this fallback identifier because it really is unknown to the system (because it is the localized standard name from a system with a different language).
So how can I work around this issue besides telling the customer to disable the usage of the client's timezone in XenApp?