|
dev
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
System.TimeZone interface unusable?machine local time zone has been left as an exercise for the user in the .NET framework. It would seem that System.TimeZone, being an abstract class, is meant to be used as a base class for any such implementations. Having thoroughly reviewed the MSDN documentation for System.TimeZone it would seem that, especially considering the new DateTime.Kind property, System.TimeZone is actually unusable as a base class. Previously, although the MSDN documentation suggested otherwise, I had to believe that the spirit of ToLocalTime() was to return a time that was local to the particular time zone instance being used. This belief was strengthened by the shared source implementation Microsoft provided in 2002, and has been shared by any implementation I have seen that uses System.TimeZone as a base class (see http://www.michaelbrumm.com/simpletimezone.html for one example). The addition of DateTime.Kind in .NET 2.0 has proven this belief to be incorrect. ToLocalTime() must by contract always return machine local time. Here's an experiment. Fully implement the System.TimeZone abstract interface for any time zone other than your own. Now set a breakpoint in all of your methods and call TimeZone.ToLocalTime() for DateTimes of Local, Utc, and Unspecified DateTime.Kind. You should discover, as I did, that your code never gets called. Now try TimeZone.ToUniversalTime() for the same values. Interestingly, ToUniversalTime() WILL call your code for both Local and Unspecified DateTime.Kind values. Make sense of that. I just want to understand what the purpose of System.TimeZone really is. If it were sealed, and all of its methods made static, it seems it would lose no utility whatsoever. Am I missing something? Any discussion would be appreciated. Nosiren,
| System.TimeZone it would seem that, especially considering the new Using ILDASM, it appears that TimeZone.ToLocalTime in .NET 2.0 is hard wired | DateTime.Kind property, System.TimeZone is actually unusable as a base | class. to a concrete implementation class. IMHO a very bad no no in OO (rhyme not really intended). I understand that they are still accepting bug reports & feature requests at http://lab.msdn.microsoft.com/ProductFeedback/. You should be able to override TimeZone.ToLocalTime itself and have the behavior you expect. Something like: Public Class MyTimeZone Inherits TimeZone ... Public Overrides Function ToLocalTime(ByVal time As DateTime) As DateTime If time.Kind = DateTimeKind.Local Then Throw New ArgumentOutOfRangeException("time.Kind", time.Kind, "DateTime is already Local time!") End If Return time + GetUtcOffset(time) End Function ... End Class However the above doesn't seem to work as I would expect... The quirk/caveat is going to be what to do with DateTimeKind.Local on input to MyTimeZone.ToLocalTime. My sample only allows Utc or Unspecified date time values, as the parameter states "a UTC time". Considering that the time parameter maybe in a different time zone then the this time zone, IMHO the exception is the "better" choice. Alternative if the input is already Local then one could simply return it "As is", as its already local... http://msdn2.microsoft.com/en-us/library/system.timezone.tolocaltime.aspx -- Show quoteHope this helps Jay [MVP - Outlook] ..NET Application Architect, Enthusiast, & Evangelist T.S. Bradley - http://www.tsbradley.net <nosi***@gmail.com> wrote in message news:1135116806.102980.277330@g44g2000cwa.googlegroups.com... | It is well known that the implementation of time zones other than the | machine local time zone has been left as an exercise for the user in | the .NET framework. It would seem that System.TimeZone, being an | abstract class, is meant to be used as a base class for any such | implementations. Having thoroughly reviewed the MSDN documentation for | System.TimeZone it would seem that, especially considering the new | DateTime.Kind property, System.TimeZone is actually unusable as a base | class. | | Previously, although the MSDN documentation suggested otherwise, I had | to believe that the spirit of ToLocalTime() was to return a time that | was local to the particular time zone instance being used. This belief | was strengthened by the shared source implementation Microsoft provided | in 2002, and has been shared by any implementation I have seen that | uses System.TimeZone as a base class (see | http://www.michaelbrumm.com/simpletimezone.html for one example). | | The addition of DateTime.Kind in .NET 2.0 has proven this belief to be | incorrect. ToLocalTime() must by contract always return machine local | time. | | Here's an experiment. Fully implement the System.TimeZone abstract | interface for any time zone other than your own. Now set a breakpoint | in all of your methods and call TimeZone.ToLocalTime() for DateTimes of | Local, Utc, and Unspecified DateTime.Kind. You should discover, as I | did, that your code never gets called. Now try | TimeZone.ToUniversalTime() for the same values. Interestingly, | ToUniversalTime() WILL call your code for both Local and Unspecified | DateTime.Kind values. Make sense of that. | | I just want to understand what the purpose of System.TimeZone really | is. If it were sealed, and all of its methods made static, it seems it | would lose no utility whatsoever. Am I missing something? | | Any discussion would be appreciated. | Hi Jay,
Thanks for the reply. > Using ILDASM, it appears that TimeZone.ToLocalTime in .NET 2.0 is hard wired My thoughts exactly.> to a concrete implementation class. IMHO a very bad no no in OO. > You should be able to override TimeZone.ToLocalTime itself and have the I would say this is true, but I have to consider the contract of the> behavior you expect. base class. According to the MSDN documentation, the return value of ToLocalTime must be "A DateTime instance whose value is the local time that corresponds to time... Local time is the date and time on the computer you are using." Therefore, overriding ToLocalTime to return anything other than machine local time breaks the contract for ToLocalTime, and will cause incorrect results for someone expecting the documented base class behavior. > The quirk/caveat is going to be what to do with DateTimeKind.Local on input The definition of Local throughout MSDN still seems to be machine local> to MyTimeZone.ToLocalTime. My sample only allows Utc or Unspecified date > time values, as the parameter states "a UTC time". Considering that the time > parameter maybe in a different time zone then the this time zone, IMHO the > exception is the "better" choice. Alternative if the input is already Local > then one could simply return it "As is", as its already local... time, so although there are problems as you have specified, they are different than you have mentioned. Most notably, any DateTime that is not UTC or machine local time must have a Kind of DateTimeKind.Unspecified. Regardless, it seems perfectly sensible for ToLocalTime() to assume a UTC parameter and for ToUniversalTime() to take a "native time" parameter (avoiding the phrase "local time" for obvious reasons). Personally, I suspect that the addition of DateTime.Kind to the framework was not for the benefit of the TimeZone class at all. It's my understanding that, prior to .NET 2.0, the XML Serializer made the fundamentally flawed assumption that all outoing dates were in machine local time and all incoming dates were in UTC. Since the serializer documentation is the only other place the Kind property is mentioned, I have to conclude that DateTime, a core component of the framework IMHO, has been hijacked to fix mistakes made in the XML Serializer. If that is true, then this really is a nasty little hack. Even the new documentation for DateTime reads like raw hackery: "Prior to the .NET Framework version 2.0, the DateTime structure contains a 64-bit field composed of an unused 2-bit field concatenated with a private Ticks field." You can almost hear Jon Lovitz saying, "I meant to do that... yeah, that's the ticket." As it stands, I've pretty much concluded that the documented interface for System.TimeZone is fundamentally broken, and am moving on with my own base class with a similar interface but a more sensible contract. Thanks, Russ A quick follow-up. It appears I am not the first person to notice the
problems associated with System.TimeZone, and Microsoft has, in fact, addressed the issue: http://lab.msdn.microsoft.com/productfeedback/viewfeedback.aspx?feedback id=fb328fdb-c488-45e4-a08d-481cc0e3a436 Closed as won't fix. Ces't la vie. | ToLocalTime must be "A DateTime instance whose value is the local time I interpret "local time" as local to the "current" Time Zone. Currently | that corresponds to time... Local time is the date and time on the | computer you are using." Therefore, overriding ToLocalTime to return | anything other than machine local time breaks the contract forI "current" Time Zone is TimeZone.CurrentZone. If you create a TimeZone object then that object is the "current" Time Zone. Although I agree with the gest of your comments. The documentation is misleading, so the method cannot be truely implemented correctly. | The definition of Local throughout MSDN still seems to be machine local Ah! There's the rub! "seems to be", "local time" really needs to be defined better in relation to what, especially when you start deriving classes... -- Show quoteHope this helps Jay [MVP - Outlook] ..NET Application Architect, Enthusiast, & Evangelist T.S. Bradley - http://www.tsbradley.net <nosi***@gmail.com> wrote in message news:1135694003.995396.12920@g49g2000cwa.googlegroups.com... | Hi Jay, | | Thanks for the reply. | | > Using ILDASM, it appears that TimeZone.ToLocalTime in .NET 2.0 is hard wired | > to a concrete implementation class. IMHO a very bad no no in OO. | | My thoughts exactly. | | > You should be able to override TimeZone.ToLocalTime itself and have the | > behavior you expect. | | I would say this is true, but I have to consider the contract of the | base class. According to the MSDN documentation, the return value of | ToLocalTime must be "A DateTime instance whose value is the local time | that corresponds to time... Local time is the date and time on the | computer you are using." Therefore, overriding ToLocalTime to return | anything other than machine local time breaks the contract for | ToLocalTime, and will cause incorrect results for someone expecting the | documented base class behavior. | | > The quirk/caveat is going to be what to do with DateTimeKind.Local on input | > to MyTimeZone.ToLocalTime. My sample only allows Utc or Unspecified date | > time values, as the parameter states "a UTC time". Considering that the time | > parameter maybe in a different time zone then the this time zone, IMHO the | > exception is the "better" choice. Alternative if the input is already Local | > then one could simply return it "As is", as its already local... | | The definition of Local throughout MSDN still seems to be machine local | time, so although there are problems as you have specified, they are | different than you have mentioned. Most notably, any DateTime that is | not UTC or machine local time must have a Kind of | DateTimeKind.Unspecified. Regardless, it seems perfectly sensible for | ToLocalTime() to assume a UTC parameter and for ToUniversalTime() to | take a "native time" parameter (avoiding the phrase "local time" for | obvious reasons). Personally, I suspect that the addition of | DateTime.Kind to the framework was not for the benefit of the TimeZone | class at all. | | It's my understanding that, prior to .NET 2.0, the XML Serializer made | the fundamentally flawed assumption that all outoing dates were in | machine local time and all incoming dates were in UTC. Since the | serializer documentation is the only other place the Kind property is | mentioned, I have to conclude that DateTime, a core component of the | framework IMHO, has been hijacked to fix mistakes made in the XML | Serializer. If that is true, then this really is a nasty little hack. | Even the new documentation for DateTime reads like raw hackery: "Prior | to the .NET Framework version 2.0, the DateTime structure contains a | 64-bit field composed of an unused 2-bit field concatenated with a | private Ticks field." You can almost hear Jon Lovitz saying, "I meant | to do that... yeah, that's the ticket." | | As it stands, I've pretty much concluded that the documented interface | for System.TimeZone is fundamentally broken, and am moving on with my | own base class with a similar interface but a more sensible contract. | | Thanks, | | Russ | |
|||||||||||||||||||||||