Base types, Collections, Diagnostics, IO, RegEx…
For the .NET 3.5 release, the BCL team has been trying to solve some problems related to dates, times and time zones that customers having been asking us to address for some time. We’ve invested in two significant features:
DateTimeOffset is a completely new DateTime type that stores the UTC Offset in addition to the DateTime. In presenting the design of this type, there are a couple of questions that keep coming up that we would like to address. The full rationale behind these provisional decisions requires going back through some of the history of DateTime over the last 8 years.
In .NET 3.5 there will be a new DateTime type called DateTimeOffset. The name of this type is an interesting topic in itself, but current plans are that this new type will complement rather than fully replace the existing DateTime type, and thus it will not be called DateTime2. A couple of questions keep coming up about this which I will address in this post by covering some relevant history:
It is necessary to start with the original rationale and design issues surrounding the original DateTime type.
The original DateTime type was mostly designed in 1998-1999, as part of the the new .NET Platform type system. Up until that time, almost all platforms (e.g. Win32, C, VB, COM, databases) represented dates and times with a combined date and time type that had no time zone information. The time zone context was outside the type’s data and in the application’s context, in the same way that using Decimal to represent money involves the context of the currency unit living outside the Decimal instance. The option of a DateTime with a UTC offset or a time zone ID was discussed and there was a lot of design back and forth. There was a lot of desire to keep the type system simple, and while a time zone aware DateTime was better at representing absolute points in time such as a file time-stamp, it got awkward when doing certain things:
Another factor was that many prior platforms had lived with DateTime types like this without running into serious issues. In the end, the desire to keep the platform simple won out, and the DateTime was a date and a time and nothing else, although support for conversion between local and UTC was provided using the machine’s local time zone.
Once this was shipped, a number of serious problems became clear:
In V2.0, when the severity of these issues was fully understood, design began on a solution. There was actually a fully developed specification to address the above issues by adding a UTC offset to the existing DateTime type. This was going to be a challenging operation since this was a significant change to what the type was. The only way to keep a reasonable compatibility guarantee was to make the time zone offset optional. However, this proposed change simply did not stand up to design scrutiny and implementation trials, and we discovered that our options of changing the existing type were significantly more limited than we had hoped. Here were some of the problems that emerged:
This was a difficult situation. It was extremely undesirable to leave every existing API taking DateTime and accepting or returning local instances with unreliable behavior around DST transitions. But a comprehensive change to DateTime was not possible in a compatible way either. It was decided to do a very minimal change to DateTime by using some unused bits in the structure to indicate if an instance was UTC or Local, and using an extra state to disambiguate the hour repeated during DST transition to solve the reliability problem. The DateTime.Kind property was introduced to solve the reliability problem without doing a full deprecation of usage of the type. However, it was not a comprehensive solution because to maintain compatibility, the Kind could only be very minimally used in existing APIs. It was decided that we would try to make it possible for existing APIs to use the Kind, but make any behavior changes on DateTime itself opt-in as much as possible. Thus the Kind is used in the critical conversions to and from Local and UTC, but not when DateTime instances are compared or formatted by default.
Even this minimal change presented significant compatibility challenges. An example of this was DateTime.ToString. If the instance was marked with DateTimeKind.Utc, it would makes sense to output its time zone offset as “+00:00” instead of pulling in the machine’s local time which only makes sense for local instances. At one point the code actually did this more correct behavior. However, we found that a significant number of users of DateTime were taking a dependency on this incorrect behavior and were broken by this change. They were serializing UTC instances in XML, and because it defaulted to formatting as a local time and because Parse converted back to the local time zone by default, their code was working most of the time, even though the persisted string would have been incorrect if parsed by a 3rd party system. To maintain compatibility even this change had to be backed out, and correct formatting of the time zone offset had to be made opt-in via the new “o” and “K” format options.
The DateTimeKind solved the most pressing issues with DateTime, but still left the space with a lot of unresolved issues. It was still very difficult to use correctly, and it could not deal well with the server scenarios where instances from different machines in different time zones needed to be handled.
So, this should address the first question of why we are not currently pursuing further the option of adding an optional offset to the existing DateTime type.
After .NET 2.0 it became clear that there was still considerable demand for a type with DateTime and a UTC offset combined. This is the type we are delivering in .NET 3.5 (DateTimeOffset). The second question then comes up as to why we are planning to a new type that complements DateTime instead of creating a complete replacement and calling it DateTime2. It is definitely compelling to have a single new type so that there does not have to be complex guidance around which of the types to use for what scenarios.
Even with compatibility taken out of the picture a lot of the reasoning above still makes it compelling to have new type that is always absolute. First, consider the landscape of date and time related scenarios:
(Scenarios C-D might be even better handled by dedicated Date and Time types. These options are still on the table, although they will not be in the .NET 3.5 release).
The existing DateTime can do scenarios A-E. But it does a mediocre job of E, because you have to convert it to and from UTC and Local depending on whether you want human-readable display or accurate arithmetic. For scenario F, you need to store an additional field to make it work. The proposed new DateTime with UTC offset is significantly better for scenario E and enables scenarios F with a single type instance. However, it is not as good for scenarios A-D where it would have to default to some arbitrary time zone offset. As a point of reference, the majority of DateTime scenarios involve E, although A and C are fairly common also, and F becomes more important when richer Time Zone support is available.
It is possible to create a new type that addresses scenarios A-D as well by making the UTC Offset optional rather than required. But this creates a lot of the same problems encountered during the aborted attempt to create such a type in .NET 2.0:
An interesting question that is always useful to ask about a design is: Given what we know now, what would we do differently if we could start again?
It would be hard to get broad consensus on this point. My personal opinion is that the date and time space is too complicated to address with a single type. If I could start again, I would have something like the V1.0 DateTime, but have a separate DateTimeOffset type also. The main difference to where we will land with the current plan of record is that we would not need the DateTimeKind that was added to DateTime in V2.0. This was really a band-aid that would not have been needed if a DateTimeOffset had been available in V1. That being said, my own opinion is that the DateTimeKind solution was critical to salvage reliable usage of the existing APIs given that there was no better type to use in V1.0.
Great, insightful post about a difficult subject.
Andrew McCallum is right that Java had similar problems with their Date-Class. But worse they did it wrong the second time with the ugly Calendar class, I've never seen such an unintuitive Date-API. Luckily they started JSR 310 and I really hope they will integrate most of the design of the great Joda-Library.
Despite your well argued point, this is still looks like a nasty hack.
What do we do with a restless trader in Singapore executing a trade through a London app online to the NASDAQ in New York, and need to ensure we execute the trade within the Quote time.. what we need is a UTCDateTime from end-to-end that is only converted to local-time when we need to display it..
Universal Time is a Universal Standard!
Exactly my point, Stephen Channell.
While we can work with DateTimeOffset up to a point, it will need to be converted to a DateTime to work with existing APIs in the framework. It will be difficult if not impossible to avoid that conversion, which invites an opportunity for error and hence bugs.
What we really need is a UtcDateTime that *is a* DateTime. That may not be possible for technical reasons (value type), but if an IDateTime interface were to be introduced and all framework signatures were updated to use the interface, both backward compatibility could be preserved and those needing a UtcDateTime would be free to use it without need for conversion. It would integrate well with the framework, too.
I'd have to support chronos and Stephen Channell in that DateTimeOffset seems like a non-solution to the problem.
UTCDateTime is an intuitive concept and IDateTime would solve compatibility issues for future revisions.
I must agree with chronos, Stephen Channel, and Morten Mertner. DateTimeOffset is not a solution to the real problem. Backward compatibility can be preserved with the addition of an IDateTime interface while also providing a path towards a real solution: UtcDateTime, which would implement IDateTime.
Based on the feedback from my last CLR week ,
I think one CLR week a year is about right,
CLR Week: A new annual tradition.
Have you ever had to deal with consumer and provider of webservices residing in different time zones
皆さん、こんにちは 前回お約束した通り、少しずつではありますがTechEdでのDEMOのフォローをしていきたいと思います。 今回は.NET Framework 3.5 で改善された TimeZone への対応について紹介したいと思います。今回、ご紹介するのは
皆さん、こんにちは 前回お約束した通り、少しずつではありますがTechEdでのDEMOのフォローをしていきたいと思います。 今回は.NET Framework 3.5 で改善された TimeZone への対応について紹介したいと思います
Celexa and aalcohol. Celexa and provigil. Celexa poids. Celexa and birthcontrol.
This is the first of three postings I'm writing to follow up on the MSDN Events sessions I delivered