Base types, Collections, Diagnostics, IO, RegEx…
System.TimeZoneInfo (currently available as part of .NET Framework 3.5 Beta 1) contains methods for checking if a DateTime instance represents an ambiguous or invalid time in a specific time zone. These methods are particularly useful for validating user-supplied points in time.
Time zones that adjust their time for Daylight Saving Time (in most cases by moving the clock time back or forward by 1 hour) have gaps and repeats in the timeline — wherever the clock time was moved forward or back by the adjustment. Let’s use Pacific Standard Time as an example. In 2007 Pacific Standard Time (PST) changes to Pacific Daylight Time (PDT) at 02:00AM (“spring forward”) on the second Sunday in March and then returns at 02:00AM (“fall back”) on the first Sunday in November:
Pacific Daylight Time (PDT) to Pacific Standard Time (PST)2007 Transition
Sunday, November 3, 2007 (first Sunday in November)
This day has 25 hours because of the repeated hour
PST <REPEAT in clock time>
The repeated time period is referred to as an ambiguous time range. The term Ambiguous Time is used because when only given a clock time, such as “01:30AM November, 3, 2007”, it is impossible to tell from that context alone if it is in Pacific Standard Time (PST) or Pacific Daylight Time (PDT).
The TimeZoneInfo.IsAmbiguousTime instance method is used to determine if a DateTime represents an ambiguous time in the given time zone:
public Boolean IsAmbiguousTime(
It is completely legitimate to pass ‘Ambiguous Time’ DateTime instances to methods. However, application code may want to detect input that falls in an ambiguous time period and then prompt the user for clarification. For such a case, the TimeZoneInfo.GetAmbiguousTimeOffsets() method can be used to retrieve a TimeSpan array of UTC offsets that could apply to that DateTime.
public TimeSpan GetAmbiguousTimeOffsets(
Pacific Standard Time (PST) to Pacific Daylight Time (PDT)2007 Transition
Sunday, March 10, 2007 (second Sunday in March)This day has 23 hours because of the gap in clock time
<GAP in clock time>
The gap or “hole in time” is referred to as an invalid time range. The term Invalid Time is used because it is impossible for the clock time to ever be in that range. Let me repeat that — invalid time is impossible to reach — the only way to get an invalid time in a DateTime is to accept bad user input or to write (bad) code that does not respect time zones.
The TimeZoneInfo.IsInvalidTime instance method is used to determine if a DateTime represents an invalid time in the given time zone:
public Boolean IsInvalidTime(
Since ‘Invalid Time’ DateTime instances represent a time that does not exist, TimeZoneInfo APIs do not accept them as valid input.
The only way an invalid time can be created is through parsing user supplied input or by having logic bugs in an application under development. Because of this, APIs such as TimeZoneInfo.ConvertTime throw ArgumentException when the DateTime parameter is an invalid time. When working with user supplied input, it is best to first verify the input with TimeZoneInfo.IsInvalidTime() before calling TimeZoneInfo.ConvertTime():
public static DateTime ConvertTime(
// An ArgumentException is thrown from ConvertTime when dateTime represents
// an invalid time in sourceTimeZone. When working with user-supplied input
// it is best to first validate the input with IsInvalidTime() before calling
ArgumentException("The supplied DateTime represents an invalid time. For example, when the clock is adjusted forward, any time in the period that is skipped is invalid.", "dateTime")
This is exactly why we need a UTC-DateTime type. There need not be any ambiguity or invalid times. A non-UTC datetime should be treated as a bug. Displaying timezone-specific times should only be done at presentation time and is easily calculated as an offset of the UTC time.
wagahai, wouldn't that only count the cases with no user input? For example in a scheduling application a user could enter an invalid date on say a conference call. You wouldn't be able to calculate that back to a proper utc time without some extra knowledge, right?
Of course. However, a UI that does not require a TZ to be set when a user enters a time is arguably fundamentally flawed. One solution is to assume (and document in the application specification) that the TZ is local for user input. Then, interpret the time in the user's timezone, but store it as UTC. Of course a properly designed UTC-DateTime, which only stores date/time in UTC, could automatically do the conversation for you. Just supply a timezone as one of the parameters.
I seriously hope that Microsoft will unseal the DateTime type so that I can fix so many of these long standing issues myself.
.NET Framework 3.5 and Visual Studio 2008 have officially shipped! Soma has the announcement on his blog