3

I am trying to get the offset hours of a particular time for EST timezone like this

var est = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
est.GetUtcOffset(new DateTime(2020, 3, 9)).Hours;

This works fine and returns me -4, which is right for 9th March 2020 because the daylight saving changes on 8th March 2020 02:00:00, but when I try to run the same code for date 8th March 2020 02:00:00, it returns me -5, while my understanding is that from 2am of 8th march it should start returning me -4.

To get the -4, I have to run it for 3am, that is one hour after the daylight changing.

But why is it so? Why do I have to add one hour to make daylight change take effect?

Pawan Nogariya
  • 8,330
  • 12
  • 52
  • 105
  • 1
    Because the change makes clocks skip from 2am to 3am. – juharr Oct 27 '20 at 11:35
  • @juharr - Ah! so it skips the clock for the time difference between daylights changes! Never known this. So basically whatever hours are getting added/subtracted to the daylight time should be skipped to get the correct offset? – Pawan Nogariya Oct 27 '20 at 11:40
  • 1
    Yeah basically 2am to 3am when the change occurs doesn't really exist so it just gives the -5 offset if you ask about those times. It's even worse when it changes from -4 back to -5 because the same hour occurs twice. – juharr Oct 27 '20 at 11:43
  • Got it! Thanks for this useful information. Do you know if daylight time can ever be more than one hour for any timezone? – Pawan Nogariya Oct 27 '20 at 11:49
  • 1
    I'm not aware of it being more than an hour anywhere, but I think there are places that do a half hour change and there are locations within timezones that do not do the change at all. – juharr Oct 27 '20 at 11:55
  • There are indeed time zones with more than an hour DST bias, but only in Antarctica and none are currently implement in Windows. If you use .NET on other platforms such as Linux, you may encounter those. A half-hour DST bias zone *is* in Windows, with "Lord Howe Standard Time". Either way, I don't recommend hardcoding one hour. Use the `ToDateTimeOffset` extension method I mention in my answer below. – Matt Johnson-Pint Oct 27 '20 at 18:04

1 Answers1

1

From the Remarks section of the TimeZoneInfo.GetUtcOffset docs:

... If dateTime is ambiguous, or if the converted time is ambiguous, this method interprets the ambiguous time as a standard time. If dateTime is invalid, this method returns a TimeSpan object that reflects the difference between UTC and the time zone's standard time.

The datetime 2020-03-08 02:00:00, is invalid in the US Eastern time zone, because the clocks advance from 01:59:59 to 03:00:00 on that day. Thus, the GetUtcOffset uses its described behavior of returning the standard time offset. You can detect this if you first call TimeZoneInfo.IsInvalidTime.

You might want to also use other methods from TimeZoneInfo to apply specific behavior. For example, it's commonly desired in appointment scheduling scenarios to use the behavior I presented in the ToDateTimeOffset extension method in this other answer.

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