How does DateTimeOffset deal with daylight saving

2019-01-10 23:37发布

问题:

I know that DateTimeOffset stores a UTC date/time and an offset. I also know from this MSDN blog entry that DateTimeOffset should be used to "Work with daylight saving times".

What I'm struggling to understand is exactly how DateTimeOffset "work(s) with daylight saving times". My understanding, little that there is, is that daylight saving times are a political decision and cannot be inferred from purely an offset. How can it be that this structure is DST friendly if it only stores an offset?

I gather there may be a way to use the TimeZoneInfo class in conjunction with DateTimeOffset. How would I do that?

Finally, are there any better ways I could achieve the following?

(I've seen some posts from Jon Skeet about Noda-Time but I gather it's not production ready yet and I don't know if it would integrate well into our existing solution).

Here's our scenario. The server is for unfortunate legacy reasons running on UK time. We have customers starting to come on-stream from Australia which has multiple time zones. Other countries could come on-stream at any time.

We have a scheduler which is based on the Hardcodet scheduler (uses DateTimeOffset). It works very well. However, in our database we only store enough data to construct a DateTime object (see below) and in our subclassed and plumbing code we just use DateTime, as originally we were supporting UK users only.

This scheduler is responsible for immobilising and mobilising plant equipment. It's therefore vital that the scheduled events run at the user's DST-adjusted local time.

The user enters a schedule on our web site; currently this is stored in the database as a day of the week, hour and minute. When the data is read we create a DateTime object for the next occurence of that day, hour and minute. I am free to alter the db structure to additionally store an offset or timezone.

When that date and time arrives, the scheduler sends the command (and retries for a while). It then runs again at the same day and time next week (although the service will actually have been recycled by then and the code will have run again).

ALL I need to achieve is the firing of scheduled events at the timezone-adjusted local date and time for that user using a scheduler which subclasses from Hardcodet. If DateTimeOffset is really DST-aware it may be that all I need to do is store an offset and change our plumbing code to use this structure but I'm getting the impression it's not as simple as that. (We may be able to get the current timezone from the plant's GPS position, but that's a discussion for another day :)).

回答1:

DateTimeOffset itself isn't really DST-aware, but TimeZoneInfo is. A DateTimeOffset represents a fixed instant in time - so you get to a DateTimeOffset via something that is time zone aware. In other words, if I asked for a DateTimeOffset now in the UK, I'd end up with something with an offset of +1 hour from UTC. If I asked for a DateTimeOffset for some time in December in the UK, I'd end up with something with an offset of 0 hours from UTC.

If you change your database to include the offset and you create the DateTimeOffset from the user's chosen DateTime (which should be of kind "unspecified") and their time zone, then that should give you the correct offset taking DST into account.

One thing to be aware of though: if I schedule something now for "2 years time" and you determine the offset now, that offset may not be correct in the future - for example, the government could change when DST applies, and obviously that's not going to change what's stored in your database.