8

I have a global website that is passing the IANA timezone id to the server and using Noda Time to map to the Windows Timezone in c# 5 web app.

"Etc/UTC" is being passed to the server but Noda Time can not map it to a Windows time zone. How can I map an IANA timezone id?

public TimeZoneInfo GetTimeZoneByIanaId(string ianaTimeZoneId)
{
    TzdbDateTimeZoneSource timeZoneSource = TzdbDateTimeZoneSource.Default;
    IList<MapZone> zoneMaps = timeZoneSource.WindowsMapping.MapZones;

    // resolve any link, since the CLDR doesn't necessarily use canonical IDs
    IList<string> mapZoneIds = timeZoneSource.CanonicalIdMap.Where(map => map.Value.Equals(ianaTimeZoneId, StringComparison.OrdinalIgnoreCase)).Select(x => x.Key).ToList();
    MapZone mapZone = zoneMaps.FirstOrDefault(zoneMap => zoneMap.TzdbIds.Any(mapZoneIds.Contains));

    if (mapZone == null)
    {
        throw new TimeZoneNotFoundException("Unable to determine the clients timezone using the jsTimezoneDetect plugin");
    }

    TimeZoneInfo timeZone = TimeZoneInfo.FindSystemTimeZoneById(mapZone.WindowsId);

    if (timeZone == null)
    {
        throw new TimeZoneNotFoundException("Unable to determine the clients timezone from NodaTime");
    }

    return timeZone;
}
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
user3772576
  • 93
  • 1
  • 5
  • Looking at https://code.google.com/p/noda-time/source/browse/data/cldr/windowsZones-25.xml, it looks like there isn't a CLDR-defined mapping of UTC. You might need to just hard-code this one :( – Jon Skeet Jun 24 '14 at 20:00
  • Right, thanks. Yes, it's a matter of the entry not being present in the map :( – Jon Skeet Jun 25 '14 at 07:27

1 Answers1

7

As Jon pointed out, the CLDR mapping is not there for "Etc/UTC". Instead, the CLDR maps the Windows "UTC" time zone to "Etc/GMT". IMHO - this is in error.

The CLDR requires "stable identifiers", so it has not traditionally updated its mappings when time zone names change. Instead, one would normally follow the "links" in the time zone database to map to the canonical zone.

However - the TZDB doesn't consider "Etc/GMT" to be a link for "Etc/UTC". They are two distinct zones. There's also "Etc/UCT". This is so that applications that rely on the TZDB for time zone abbreviations can use their choice of abbreviation (GMT, UTC, or UCT). (See discussion here.)

Anyway - thanks for reminding us of this problem. I updated the mapping functions to take this into account.

Community
  • 1
  • 1
Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • This is the only one I am aware of - at least, if you use the mapping functions I linked to in my other answer, it attempts to follow all tzdb links. The discrepancy is because CLDR has a different idea of what is "canonical" than tzdb. I've added [some detail here](https://code.google.com/p/noda-time/issues/detail?id=274) with consideration for the next major version of Noda Time. – Matt Johnson-Pint Jun 25 '14 at 14:43
  • Awesome, I have a global user base and NodeTime has solved a lot of the problems I was having with timezone offsets. Its is an excellent solution thanks – user3772576 Jun 25 '14 at 16:09