Noda Timezone issue with IDateTimeZoneSource.MapTimeZoneId

I am trying to convert Windows to IANA time zone and below is the code that works most of the time. But when the windows time id = "Turks & Caicos" then below code returns NULL. I am using NODATIME Version 1.3.1

    Public Function ConvertID_WindowsToIana(strWindowsZoneID As String) As String
        If strWindowsZoneID.Equals("UTC", StringComparison.OrdinalIgnoreCase) Then
            Return "Etc/UTC"
        End If

        Dim tzdbSource = NodaTime.TimeZones.TzdbDateTimeZoneSource.[Default]
        Dim tzi = TimeZoneInfo.MapTimeZoneId(strWindowsZoneID)
        Return tzdbSource.CanonicalIdMap(tzi)
    End Function

Here when tzi = -4:00 Turks & Caicos, in this case the return is NULL.

Now when I updated to version 2.2.3, thought that it will fix the stuff, but as per the documentation

enter image description here

And now that function is taking a "Position Of Current String" as parameter.

So my code will look like below:

  Public Function ConvertID_WindowsToIana(strWindowsZoneID As String) As String

        Dim tzi = TimeZoneInfo.FindSystemTimeZoneById(strWindowsZoneID)
        Dim tzid = tzdbSource.GetSystemDefaultId(WHAT TO PUT HERE)
        // some logic
    End Function

Question 1: Why my first code does not work for "Turks and Caicos".

Question 2: I updated thinking it will fix that issue, but now that function is vanished and replaced, and I don't know what to use. Please help me.

P.S: For Eastern and many other time zones the First Code Snippet works fine.

Jon Skeet
people
quotationmark

GetSystemDefaultId doesn't replace all the functionality of MapTimeZoneId - you don't want to call that here.

Instead, use tzdbSource.WindowsMapping to get a WindowsZones that you can then use to find the TZDB ID. Here's some sample code:

using System;
using NodaTime.TimeZones;

public class Test
{
    static void Main()
    {
        var source = TzdbDateTimeZoneSource.Default;

        string windowsId = "Turks And Caicos Standard Time";

        var mapping = source.WindowsMapping.PrimaryMapping;
        if (mapping.TryGetValue(windowsId, out string tzdbId))
        {
            Console.WriteLine($"Mapped to {tzdbId}");
        }
        else
        {
            Console.WriteLine("Not found");
        }
    }    
}

An alternative approach is to use Matt Johnson's TimeZoneConverter package, which can simplify things a bit more. If you're using Noda Time elsewhere, it probably makes sense to stick with Noda Time, but if you're only using it for time zone ID conversion, TimeZoneConverter is a better choice.

As for why "Turks and Caicos" doesn't work - I assume you mean "Turks And Caicos Standard Time" as the ID. That was only introduced into the CLDR mapping data in CLDR v30, which was released over a year later than 1.3.1. If you update to 1.3.5 or 1.4.2, both of those should be fine.

people

See more on this question at Stackoverflow