1

I'm getting an unexpected DateTime when converting from:

(UTC) Dublin, Edinburgh, Lisbon, London to (UTC-08:00) Baja California

Below is the code I have been using. I'm expecting serverDateTime to be 29/03/2016 00:00:01 (-8 hours), but instead I get 28/03/2016 23:00:01 - which is a 9 hour difference.

    private static void Main(string[] args)
    {
        ReadOnlyCollection<TimeZoneInfo> timeZones = TimeZoneInfo.GetSystemTimeZones();
        TimeZoneInfo localTimeZone = timeZones.FirstOrDefault(tz => tz.DisplayName.Contains("London"));
        TimeZoneInfo serverTimeZone = timeZones.FirstOrDefault(tz => tz.DisplayName.Contains("California"));
        DateTime clientDateTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 29, 8, 0, 1);
        DateTime serverDateTime = TimeZoneInfo.ConvertTime(clientDateTime, localTimeZone, serverTimeZone);
    }

My local machine is in the UK, which is currently UTC+1, and Baja - California is currently UTC-7, so I'm expecting to get an 8 hour difference, instead of 9. What am I doing wrong?

Thanks in advance.

nf313743
  • 4,129
  • 8
  • 48
  • 63
  • That's *not* UTC (+00:00), that's simply London's timezone that's already using DST (+1:00). I'll bet that DST rules are different in California – Panagiotis Kanavos Mar 29 '16 at 16:41
  • BTW it's *far* easier to use NodaTime to work with time. There *is* a Windows Timezone that corresponds to UTC but I haven't found the proper index yet – Panagiotis Kanavos Mar 29 '16 at 16:49
  • Why are you converting time? Convert Time it not required in most cases. Only time it is really needed is when you enter data that was collected in a different timezone. All computers store time in UTC and default to using timezone settings when inputting and displaying time. Converting time you can end up with a time that is not UTC. – jdweng Mar 29 '16 at 16:57
  • [TimeZoneInfo.Utc](https://msdn.microsoft.com/en-us/library/system.timezoneinfo.utc(v=vs.110).aspx) already returns the UTC timezone. It's name is plain `UTC` without city names – Panagiotis Kanavos Mar 29 '16 at 16:58
  • @jdweng no they don't. In fact, all times are assume to be *local* times, which is why the OS's timezone setting is important. The *real* fix a) to use DateTimeOffset and not make *any* assumptions about offsets and/or b) use a library like NodaTime that allows you to specify the timezone name instead of an offset, thus avoiding DST rule changes. `Russia/Moscow` hasn't changed but the DST rules for Russia change every other year – Panagiotis Kanavos Mar 29 '16 at 17:01
  • Panagiostis. Read my response carefully. Time in PC is stored as a number in UTC. Otherwise computer would not be able to send data accurately. Any time sent electronically from one PC to another uses UTC. Any time input/output is converted to local time using timezone settings. – jdweng Mar 29 '16 at 17:14

1 Answers1

5

A few things:

  • "(UTC-08:00) Baja California" refers to Baja California, Mexico - not California, USA.
  • This zone entry follows Mexican DST rules, which doesn't start DST until April 3rd this year. Thus this entry is on UTC-8 still, explaining the time difference you observed.
  • This particular entry is actually wrong in Windows, as it turns out that the entire state of Baja California follows USA rules for daylight saving time, not Mexican rules.

    • There is an extensive multi-thread discussion of this in the tz mailing list archives in October and November 2015. This resulted in the corresponding IANA zone America/Santa_Isabel being deprecated with release 2016a. It now links to America/Tijuana instead, which already had been following USA DST rules.
    • Microsoft has not yet made a similar change to its data, but it is likely in a future update to the Windows time zone data. (I have already communicated this to the appropriate personnel.) In the meantime, use "(UTC-08:00) Pacific Time (US & Canada)" - even if you're talking about Baja California, Mexico.
  • Don't try to look up a time zone by its DisplayName. Those values will be different depending on operating system language. Instead, use TimeZoneInfo.FindSystemTimeZoneById. The Id properties are not localized. Additionally, Microsoft considers the Id values to be stable identifiers, and thus they will not change with future updates. The DisplayName values have been modified in the past, and could indeed change in the future.

    • Use the ID "GMT Standard Time" for "(UTC) Dublin, Edinburgh, Lisbon, London"
    • Use the ID "Pacific Standard Time" for "(UTC-08:00) Pacific Time (US & Canada)"
    • The ID "Pacific Standard Time (Mexico)" is for "(UTC-08:00) Baja California" - but for the reasons I described, don't use this entry.
  • Really, you shouldn't be concerned with the time zone on the server at all. The server should only be concerned with UTC. (note that London is not UTC, since it switches for BST in the summer)

  • I'm not sure what you're intention was with this line:

    DateTime clientDateTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 29, 8, 0, 1);
    

    Pulling the month and year from DateTime.Now is going to use the server's time zone. Then you combine with fixed day of 29 and fixed time at 8:00:01. This will fail in February of a non-leap year (when there are only 28 days in the month), and also could give bad dates when the server's date is not in the same month and year as the client's (such as near the transition from one month to another).

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575