none
Is System.TimeZone appropriate as a base class?

    Question

  • It would seem that, as a friendly .NET developer, I would want to write concrete TimeZone classes that implement the abstract TimeZone interface provided by the .NET framework.  However, after a thorough examination of the MSDN documentation, this seems impossible.  Note that all of my statements here are based on the assumption that "local date and time" in MSDN always means "machine local date and time."  I have not found any evidence to suggest otherwise.

    The primary problem with the TimeZone interface is that it provides no methods for translating a given time from UTC to the actual concrete time zone represented by the instance.  Note that the method ToLocalTime does not perform this function; it exclusively returns a DateTime set to machine local time... right down to the DateTime.Kind property.  It's interesting to note that, if you do implement the abstract interface of System.TimeZone, ToLocalTime() will not call any of your overrides, while ToUniversalTime() will.

    From my study, even implementing the TimeZone abstract interface is a significant challenge.  It's actually not material to this discussion, but DaylightTime, the structure returned by abstract method GetDaylightChanges, must be in machine local time, too (check the DaylightTime.Start and DaylighTime.End properties in MSDN), which means that simply returning "2am on the first Sunday in April" is wrong for any time zone other than the one you're sitting in.

    What is material to this discussion is that the argument to abstract method GetUtcOffset is supposed to be in either a machine local time or a time that is already in the target time zone... it's a contadiction in back-to-back sentences in MSDN and I don't know which one is right.  Unfortunately, neither option actually allows you to perform a conversion from Utc, which is the most sensible option.

    So ultimately it seems I can not do anything useful with a class derived from System.TimeZone.  Everything about the System.TimeZone interface is meant specifically for use with the machine local time zone.  So, assuming that .NET is supposed to be a solid object-oriented framework, why is System.TimeZone an abstract class?  It could be a sealed class with nothing but static methods and its utility would not be diminished.

    If I'm missing something, please enlighten me, because I want to do the right thing, but I can't find any documentation that makes me believe this is possible.  In particular, I want to see the code that would convert a DateTime from US Eastern to US Pacific on my computer in London given instances of properly implemented EasternTimeZone and PacificTimeZone classes, using only the System.TimeZone interface and following all of the "contracts" indicated in MSDN's documentation.

    Wednesday, December 21, 2005 9:50 PM

Answers

  • I'm am the development owner of System.DateTime and System.TimeZone. My advice would be to not try to use System.TimeZone as a base class. I would actually classify our attempt to make TimeZone a point of extensibility as a mistake, and if you are creating a class to represent time zones other than the current one, I would create a new hierarchy and not inherit from this one.

    There are a number of problems with the contract System.TimeZone implies that really make it only suitable for representing the local machine time zone, and not other time zones. For example it is unclear what ToLocalTime should do. Should it convert from the represented time zone to machine local, or from UTC to the represented time zone. If the former the behavior is inconsistent with the CurrentTimeZone implementation, and if the latter then the name does not make sense.

    When shipping V1.1 we were conscious that we only supported the local time zone because we were just wrapping what was available in Win32. Because it seemed cheap, we just made it abstract to take care of the extensibility thinking that others could build other time zones on top of it, but we did not really think it through. If we were to design it again, we would have either not had any extensibility, or we would have designed the extensibility in a more thorough way.

    Anthony Moore

    Base Class Libraries Development.

     

    Friday, January 13, 2006 2:42 PM

All replies

  • I don't believe that's possible because a time zome is configured by the computer, not configurable by .Net. You can use .Net to display time zone offsets for various countries, but all it does it display, it doesn't allow you to change the offset of the time zone for a given DateTime instance. In other words, you can't change the time just by changing the time zone. To change the time you need to subtract or add from or to the local time.
    Wednesday, December 21, 2005 9:56 PM
  • System.TimeZone is an abstract class, and as such is clearly intended for use as a base class.  One would assume that classes that implement the System.TimeZone abstract interface would provide implementations for time zones other than "machine local," such as Eastern or Pacific.  The logical purpose of such implementations would be to aid time zone conversion.

    My position is that the current interface for System.TimeZone is not equal to the task.  Its methods do not provide the functionality they pretend to support, unless you are using the implementation provided by CurrentTimeZone.  Further, the MSDN documentation contradicts itself in several key areas, and the recent addition of DateTime.Kind actually makes things worse.

    If the MSDN documentation is to be considered the authoritative source for the responsibilities of a System.TimeZone implementation, then the interface is broken, and as a core class of the .NET framework it should be fixed.  There are three ways to achieve this fix:

    1. System.TimeZone can be sealed so that it can no longer pretend to be a base class.  This is obviously impossible, because several people have written implementations derived from System.TimeZone that ignore the requirements of its contract in order to provide something that works.
    2. System.TimeZone can be extended to include methods clearly intended, through documentation, for conversion to the time zone represented by the actual TimeZone instance.
    3. The contract for System.TimeZone and System.Globalization.DaylightTime can be modified so that they are no longer married to the time zone of the machine.  Since TimeZone.CurrentTimeZone already provides machine-local functionality, it should not be enforced in the interface.

    Before the release of .NET 2.0, I would have recommended option three.  It is perfectly sensible for TimeZone.ToLocalTime to take a DateTime in UTC and return a DateTime in the instance time zone, and for TimeZone.ToUniversalTime to always assume a DateTime in the instance time zone and return a DateTime in UTC.  Unfortuantely, .NET 2.0 has made this impossible, because any ambiguity wiggle-room in the contract of TimeZone.ToLocalTime has been erased: it must return a result in machine local time (i.e. its Kind property set to DateTimeKind.Local).  As previously mentioned, the 2.0 implementation of TimeZone.ToLocalTime doesn't even access GetUtcOffset (I don't know if it used to, but the shared source implementation certainly did).

    Ultimately, what I really want is confirmation that I'm not crazy, and that System.TimeZone, in its current form, fails as a base class for any implementation other than CurrentTimeZone.  Given that confirmation, I will go ahead with my own custom TimeZone hierarchy, and ignore the fact that System.TimeZone exists.

    Thursday, December 22, 2005 4:10 PM
  • I'm am the development owner of System.DateTime and System.TimeZone. My advice would be to not try to use System.TimeZone as a base class. I would actually classify our attempt to make TimeZone a point of extensibility as a mistake, and if you are creating a class to represent time zones other than the current one, I would create a new hierarchy and not inherit from this one.

    There are a number of problems with the contract System.TimeZone implies that really make it only suitable for representing the local machine time zone, and not other time zones. For example it is unclear what ToLocalTime should do. Should it convert from the represented time zone to machine local, or from UTC to the represented time zone. If the former the behavior is inconsistent with the CurrentTimeZone implementation, and if the latter then the name does not make sense.

    When shipping V1.1 we were conscious that we only supported the local time zone because we were just wrapping what was available in Win32. Because it seemed cheap, we just made it abstract to take care of the extensibility thinking that others could build other time zones on top of it, but we did not really think it through. If we were to design it again, we would have either not had any extensibility, or we would have designed the extensibility in a more thorough way.

    Anthony Moore

    Base Class Libraries Development.

     

    Friday, January 13, 2006 2:42 PM
  • I want to know the current EST time from any time zone keeping into cosndieration Daylight saving using VB/C#.Net.Pl guide me.

     

    Thursday, September 14, 2006 8:46 PM
  • I have a similar requirement.  After looking around, have 2 suggestions:

    1) use a webservice to request the current time in Eastern Time Zone. (there are web services out there that will return current time for a specified time zone)

    2) Code the rules for daylight savings time in a class (note rules change in 2007), then pass the UTC of the date of the machine the app is running and return the Eastern time zone equivalent.  The UTC offset for ET is -5 standard time, -4 in savings time. trickiest part is determing the nth Sunday in March & November (April and October pre 2007)

    The first is less code and would work for a connected application, 2nd is some work, but would not need internet connectivity.

    Hope this helps.

    Tuesday, September 26, 2006 1:21 AM