Question

I am building a windows store clock app to show the current time of the user and also for different cities around the world.

Initially, I had planned on doing this completely using time zone web services from Google etc., but after looking at the number of requests allowed in free accounts and the cost involved in getting a paid account, I felt it was better to find an alternate solution without having to mortgage the house.

Searching around, I found the excellent NodaTime library by John Skeet and team. After digging through the documentation and here on stackoverflow, my head is still buzzing with all the date time and timezone related terminology and conversion methods. Anyway, I thought I could do this with 2 options:

Option 1: Using DateTime.Now to get the current system time and then getting time for other zones using nodatime like this (based on code provided by Matt Johnson in reply to another question on SO):

DateTimeZone homeZone = DateTimeZoneProviders.Tzdb["Asia/Colombo"];
LocalDateTime homeTime = LocalDateTime.FromDateTime(DateTime.Now);
ZonedDateTime homeTimeInZone = homeTime.InZoneStrictly(homeZone);
TbTime1.Text = "Home time is: " + homeTimeInZone.ToDateTimeOffset();

DateTimeZone timeZone1 = DateTimeZoneProviders.Tzdb["Australia/Perth"];
ZonedDateTime timeZone1Time = homeTimeInZone.WithZone(timeZone1);
TbTime2.Text = "Timezone 1 time is: " + timeZone1Time.ToDateTimeOffset();

Option 2: After looking further, I found this solution and felt it would also work nicely like this:

public ZonedDateTime GetTimeInTimeZone(string timeZone)
{
    // Timezone is olson timezone e.g. "Asia/Colombo"
    Instant now = SystemClock.Instance.Now;
    var zone = DateTimeZoneProviders.Tzdb[timeZone];
    ZonedDateTime zonedDateTime = now.InZone(zone);
    return zonedDateTime;
 }

Now let me try to get to the question: In both options above, there is a dependency on either DateTime.Now or SystemClock.Instance.Now to first identify the user's system time and THEN convert it to the required timezone's city time. But what happens if the user's system is not set to the correct time? I believe (correct me if wrong) DateTime.Now and SystemClock.Instance.Now are both using the system clock to get the current time? Assuming that the system time is not set correctly, then any timezone conversion will simply show the wrong time for other cities due to our dependency on the user's system time.

In such cases, how do I establish the user's current time without relying on their system clock? Should I revert to using a web service to get the user's current time zone using lat/long or is there a better option using NodaTime etc that can work offline? Thanks.

Was it helpful?

Solution

A couple of points:

  • Avoid using DateTime.Now

    • It's already translated to the local time zone, so during DST fall-back transitions the result can be ambiguous.
    • If you need to get an exact unambiguous moment in time without using Noda Time, then use DateTime.UtcNow.
    • You could also use DateTimeOffset.UtcNow, or DateTimeOffset.Now. When the offset is included, there is no ambiguity.
    • See also The Case Against DateTime.Now on my blog.

  • In Noda Time, realize that SystemClock.Instance is an implementation of the IClock interface. Whenever possible, you should code against the interface, such that you can replace the implementation in your unit tests if desired. Though in the simplest of examples, there's nothing wrong with calling SystemClock.Instance.Now, it just isn't as testable.

  • As far as which time zone input to use, that is entirely based on your application requirements.

    • If you can depend on the system to be set to the correct zone, you can retrieve it with

      DateTimeZone tz = DateTimeZoneProviders.Tzdb.GetSystemDefault();
      
    • If you can't depend on the system time zone to be set correctly, you might consider some other source of input.

    • You mentioned GPS coordinates. If you have that, perhaps from a mobile device, there are solutions for resolving it to a time zone. See here for some options. Noda Time can't help you in this regard.

    • You might also consider asking the user of your app to pick a time zone from either a drop-down list or a map. There are some map-based time zone pickers for HTML/JS here and here. (I am unsure if they will work in a WinJS based Windows Store App or not, and I don't know of any XAML based solutions off hand.)

  • If the actual time of their clock is set wrong, there's not a lot you can do, other than try to reach out to another server to retrieve a time stamp. In most cases, you should rely on the operating system to already be synchronized with a time server.

    • If you do require synchronization with an external service, that can be challenging. You need something that implements NTP properly, including measuring and compensating for transmission delay. That's not easy, and probably requires an external library. I don't know of one off-hand to recommend.

    • Reaching out to a web service and returning the current time isn't necessarily going to be as accurate as you might think, as that does not compensate for the time it takes for the server to transmit that response to you.

    • If you are running on a device with a GPS receiver, then it is technically possible that it can provide an accurate time stamp received from the GPS signal. Whether or not that is retrievable and usable via the Windows Store API, I am not sure. I checked a few references on MSDN but came up empty.

  • Regarding the two code samples you provided, they're doing slightly different things, but go with option 2. It's much cleaner, and is pure Noda Time.

OTHER TIPS

You can usually rely on the local time being accurate, as displayed by the clock. Any Windows machine is setup to talk to a time server, the default is time.windows.com. The user will notice a discrepancy with the rest of the clocks in his house. Getting daylight saving transition dates wrong is certainly possible. But then you don't want to overrule the user's settings, he may well live in a county that's close to the timezone border and opted out of DST or a place that just made up their own rules, like an American Indian tribal area.

Making such decisions about remote places in the world is an entirely different ball of wax. Notable is the island of Samoa, it hopped across timezones in 2011, even crossing the date line from UTC-11 to UTC+13. Daylight savings rules are always affected by local political decisions, they don't make the top of the news in your local newspaper. Some odds that a it does make it to a web service. Mapping a city to a timezone is in itself something that requires an extensive database. If absolute accuracy is required then you really do need a service.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top