Garrett Daniel DeMeyer
Garrett Daniel DeMeyer

Reputation: 931

How can I get Noda Time in Xamarin to return "America/Los_Angeles"?

I am using Noda Time to get the local timezone on the device in Xamarin Forms. We use the code below to return it.

NodaTime.DateTimeZoneProviders.Tzdb.GetSystemDefault().Id;

However, if you set the phone's location to anywhere on the West Coast of USA, it returns "America/Tijuana." This is causing an issue for us which would be solved if it returned something like "America/Los_Angeles" (which is a valid Id) when your location was set to L.A.

Any thoughts? How can I get the library to return a more accurate Id?

Upvotes: 2

Views: 645

Answers (2)

Divyesh
Divyesh

Reputation: 2401

This issue can be fix like this:

For Example: 1. In App.xaml.cs

public partial class App : Application
{

   public static string timeZoneName { get; set; } = string.Empty;

    public App()
    {
        var timezone = string.Empty;
        if (Device.RuntimePlatform == Device.Android)
        {
                timezone = TimeZoneInfo.Local.DisplayName;
        }
        else if (Device.RuntimePlatform == Device.iOS)
        {
                timezone = App.timeZoneName;
        }
    }

}

2. AppDelegate.cs

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
     global::Xamarin.Forms.Forms.Init();
     App.timeZoneName = NSTimeZone.LocalTimeZone.Name;
     LoadApplication(new App());
     return base.FinishedLaunching(app, options);
}
  1. In ViewModel or any class

var timezone = App.timeZoneName;

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1500805

On some platforms, and depending on the version of Noda Time you're using, the ID of the system time zone isn't available, so we have to guess. We do this based on the time zone transitions from January 1st of the current year to January 1st in 5 years' time. (This is the only place where the system clock is used in production code.)

We ask the TimeZoneInfo for its idea of the UTC offset at lots of different instants within that interval (every instant where any of the IANA time zones has a transition). We then "score" each IANA time zone against the TimeZoneInfo values, to see what proportion of the instants return the same UTC offset. We return the ID of the time zone with the highest number of matches, so long as it's at least 70% of them.

In your case, both America/Tijuana and America/Los_Angeles have the same transitions for the 5 years 2018-2022. In tzvalidate format:

2018-03-11 10:00:00Z -07:00:00 daylight PDT
2018-11-04 09:00:00Z -08:00:00 standard PST
2019-03-10 10:00:00Z -07:00:00 daylight PDT
2019-11-03 09:00:00Z -08:00:00 standard PST
2020-03-08 10:00:00Z -07:00:00 daylight PDT
2020-11-01 09:00:00Z -08:00:00 standard PST
2021-03-14 10:00:00Z -07:00:00 daylight PDT
2021-11-07 09:00:00Z -08:00:00 standard PST
2022-03-13 10:00:00Z -07:00:00 daylight PDT
2022-11-06 09:00:00Z -08:00:00 standard PST

Noda Time can't distinguish between the two time zones in that 5 year period, so it returns the one it found first. (It's undefined which one it finds first - that's something we might want to fix by ordering the time zones by ID. I'll file an issue for that.)

I hope that helps explain what you're seeing - it doesn't fix the problem, but it shows that all the code (yours and Noda Time's) is behaving reasonably, in the context of the limited information available.

As suggested in comments, you might want to use platform specific code to resolve this: the .Name property of Foundation.NSTimeZone.LocalTimeZone on iOS and maybe the .ID property of Java.Util.TimeZone.Default on Android.

Upvotes: 8

Related Questions