Daylight Saving Time (DST) is the practice of 'advancing' clocks during the summer. Normal practice is to advance the clock 1 hour during spring, and are adjusted backwards during autumn. In Europe we adjusted the clocks last weekend (Oct. 30th)., and the US will do the same next weekend (Nov. 6th). I thought this would be a good time to talk a little about DST, and what it means for us programmers.
DST is a rather 'weird' phenomana. There is here is a lot of dispute over the actual benefits of having DST, the original arguments of reducing energy usage and crime have been proved and disproved by numerous studies. Some countries even stopped using DST, to later resume using it. Some countries stopped using it all together.
Here is a map of countries that observe DST.
At first, you would think and hope that this is reflected in the dates printed by the Console.Writeline, and that this snippet of code would produce something like this:
But, sadly it does not. It produces the following output (and thus, not observing the DST switch).
Why is this? We add one hour with each iteration, so logically it should print 02:00:00 AM twice. The issue here is the DateTime structure. DateTime does not contain information about timezones. From .NET 2.0 onwards, DateTime does contain a 'Kind' property, of type DateTimeKind. The Kind of a DateTime struct can be 'Local', 'Utc' or 'Unspecified'. To provide for backwards compatibility with pre .NET 2.0 versions, the Kind of a DateTime instance will always be 'Unspecified' unless the kind is specified in the constructor, or set with the static DateTime.SpecifyKind method. To further provide backwards compatibility, a 'Unspecified' DateTime will behave like a 'Local' DateTime.
In our example, we have not set the 'Kind' of the DateTime struct in the constructor, therefore it will behave like a Local DateTime. So, going form 01:00 AM to 02:00 AM by adding one hour, and then adding one hour from 02:00 AM to 03:00 AM is expected behavior. We can change this behavior by specifying the Kind of the DateTime struct to UTC in the constructor. Basically, we are working only with UTC untill we present output to the user. When we want to present the output, we use the ToLocalTime() method to format the date according to the current timezone and culture information.
This produces the following output:
A very good alternative when dealing with different timezones is using the DateTimeOffset struct. This structure is a 'timezone' aware DateTime alternative that was introduced in .NET 3.5. It represents a point in time relative to UTC. If we want to achieve something similar, we can use the following code:
Here we create a local DateTime object, and use it to instantiate a DateTimeOffset. It is not necessary to supply a local DateTime in the DateTimeOffset constructor, it also supports constructors almost identical to DateTime. We iterate through the hours in the same fashion, and we print the localized time to the console. The output shows what we want, and it even includes the timezone offset information. You can clearly see the UTC offset switch.
This output is possible because DateTimeOffset stores it's information in UTC format, so calculating with the dates also occurs in UTC. It is best practice and really conveniant to always use UTC internally, and only convert it to a local time when it has to be presented (either to a user, or to another (legacy) system that requires a certain timezone.
The PI System works in the exact same way. You don't have to worry about DST changes. PI uses UTC time internally, and only when it needs to be presented to the user it will use the localized time. This means that internally, PI does not have 23 or 25 hour days internally: only 24 hour days. There is a short video on the Youtube OSIsoftLearning channel here
For instance, this is what you would get if you create a trend PI Processbook covering the period of a DST switch (in this case, advancing one hour in 2010)
Sometimes however you have to know the number of hours in a day (specially when creating daily averages or aggregates). The DayLightTime class contains the timestamps of the start and end of DST for a given year. You can obtain a DayLightTime instance from a System.TimeZone. To get the number of hours in day for your current timezone:
And we can use it like so:
The output will then be:
Some good reads about working with Dates, Times, TimeZones and DST in .NET:
- The System.DateTimeOffset structure.
- The System.DateTime structure.
- Choosing Between DateTime, DateTimeOffset, and TimeZoneInfo.
- DateTimeOffset: A New DateTime Structure in .NET 3.5.
- A Brief History of DateTime.
- A Brief History of DateTime Follow-up.
- DateTime FAQ Entries.
- DateTime.ToUniversalTime returns MaxValue/MinValue on overflow.
- Time Zones in the .NET Framework.
- TimeZoneInfo: Working with Ambiguous and Invalid Points in Time.
And now for some fun and offtopic facts on DST:
- The proper description of DST is 'Daylight Saving Time', not 'Daylight Savings Time'
- A man, born just after 12:00 a.m. DST, circumvented the Vietnam War draft by using a daylight saving time loophole. When drafted, he argued that standard time, not DST, was the official time for recording births in his state of Delaware in the year of his birth. Thus, under official standard time he was actually born on the previous day--and that day had a much higher draft lottery number, allowing him to avoid the draft.
- While twins born at 11:55 p.m. and 12:05 a.m. may have different birthdays, Daylight Saving Time can change birth order -- on paper, anyway. During the time change in the fall, one baby could be born at 1:55 a.m. and the sibling born ten minutes later, at 1:05 a.m. In the spring, there is a gap when no babies are born at all: from 2:00 a.m. to 3:00 a.m.
- In the U.S., Arizona doesn’t observe Daylight Saving Time, but the Navajo Nation (parts of which are in three states) does. However, the Hopi Reservation, which is entirely surrounded by the Navajo Nation, doesn’t observe DST. In effect, there is a donut-shaped area of Arizona that does observe DST, but the “hole” in the center does not.
I couldn't verify these, so I'm not 100% sure about wether they are true
- Daylight saving time once single handedly thwarted a terrorist attack, causing the would-be terrorists to blow themselves up instead of other people. What happened was, in September 1999, the West Bank was on daylight saving time while Israel was on standard time; West Bank terrorists prepared bombs set on timers and smuggled them to their associates in Israel. As a result, the bombs exploded one hour sooner than the terrorists in Israel thought they would, resulting three terrorists dying instead of the two busloads of people who were the intended targets.
- I personally cannot really believe this one, I hope someone from the US can verify: To keep to their published timetables, trains cannot leave a station before the scheduled time. So, when the clocks fall back one hour in October, all Amtrak trains in the U.S. that are running on time stop at 2:00 a.m. and wait one hour before resuming. Overnight passengers are often surprised to find their train at a dead stop and their travel time an hour longer than expected. At the spring Daylight Saving Time change, trains instantaneously become an hour behind schedule at 2:00 a.m., but they just keep going and do their best to make up the time.
Sources for this article: