Base types, Collections, Diagnostics, IO, RegEx…
Thanks all for the feedback on
A Brief History of DateTime. Thanks Justin for responding to most of this. I
can elaborate on some of the issues raised:
>> (3) Was there any consideration given in the design process around
making DateTimeOffset an (immutable) reference type?
We did not really consider this because unless something is going to be of an
unpredictable size, there is not much benefit of an immutable reference type
over a value type. Also, since we wanted to replace many DateTime scenarios
going forward we did not want to have a type that performed significantly
differently. Can you clarify why you would prefer this design?
>> If I use DateTimeOffset, I will still need to convert it to DateTime
when passing it as a parameter to existing methods. This introduces an
opportunity for errors.
This might seem scary, but it should not be as problematic as it might seem.
The conversions to DateTime can lose some the display time, but not the absolute
point in time. Any existing API that treats the DateTime as an absolute point in
time will get the right results. Once that don’t will often be subject to usage
problems regardless of whether the input is a DateTime or something converted
>> As it is, we now filter through all source code searching for DateTime
usage. Every instance is flagged as a potential bug (and usually is) needing
The need to do this is unfortunate, but I would agree that it is necessary
with DateTime. The nice thing about DateTimeOffset is that if you can be in a world
where within your own application you are using it and not DateTime, the number
of usability problems is significantly reduced. Arithmetic, comparison, display and
serialization all default to a behavior that is much more likely to be what it
is intended. Conversions to DateTime for legacy APIs still need some checking,
but there are fewer mistake opportunities than when passing in a DateTime
>> A better solution is to wrap something like
We agonized over whether to include separate data with this functionality
because we know it is important and preferable to the Windows data by many
customers. It was for this reason that we ensured that the system was extensible
enough that someone could populate this data into TimeZoneInfo. A challenge was
that there is significant complication to everyone to dealing with multiple
copies of this data when updates are needed, such as happened in the USA this
year. This is something that could still be done in the future if there is
sufficient demand, so we can take this as an AddRef on demand for it, but for
now we did not want to default people into having a second copy of the time zone data
on every machine that could create administrative problems if it got stale.
>> Any thoughts on this? If not, what is the preferred way of storing and
converting back to ateTimeOffset from a SQL column?!
IIn this case you would really need to decide if you cared about knowing the
absolute time as well as the offset. As discussed, most of the time you need the
absolute time, so I would just use the UTC. If you do care about both and you
can’t wait for the next SQL release, you would need to use an extra column,
which could either be an extra DateTime (e.g. DateTimeutc+DateTimeLocal), or you
could store either the local or UTC plus its offset, probably in an integer
field counting the ticks, depending on which one you needed more often,
although I would recommend the UTC value because then sorting the column would
>> 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!
>> 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.
This is great input. I did not elaborate why we did not head further down a
road like this. Another way to have solved this would be to have a type that is
UTC by definition and can never be anything else, which is essentially what
Win32 did. If you want to go with a model of Interface coupled with concrete
types that could be UTC, you have something very close to that in Whidbey
anyway, since you can have DateTime instances with Kind=Utc that you can inspect
and verify that are UTC. Regardless of whether you are using this flags-based
approach or using an Interface with concrete implementations, the solution is
kind of ineffective. For example, in both cases public APIs that take DateTime
as input have to deal with the possibility that is not the UTC input, and
possibly that its time zone is completely unspecified. You can use
DateTimeOffset in this manner too if you follow the convention of always using a
There are many other problems with a type constrained to be UTC. It is hard
for human beings to process in situations like debugging and inspecting
persisted formats, because they have to do some math every time they want to
make sense of it. Obviously when you display to a user you want to convert to a
local time. Here things get tricky. You can either make this conversion happen
only during formatting (e.g. a ToStringLocal()) method but then you can’t
programmatically inspect sub-parts of the local instance which you need to do
some times. Alternatively you can provide a local representation but to do that
you either have to break the “always UTC” convention and deal with the
complexity of that, or you need a whole new type just for that. Another problem
is that this still does not address scenario F above where you need to work with
an absolute point in time, but you also don’t want to lose what its original
local value was where that might differ from the time zone on the machine.
What you ideally want is a type with the identity and reliability of a UTC
Data Type without these usability down-sides. This is what DateTimeOffset is. It
may not be obvious at first, but the identity, comparison and arithmetic are all
based on the absolute UTC time so you get this more reliable and consistent
behavior where it counts, but it also addresses the usability concerns above.
The time zone offset part can be thought of as ancillary data that is not part
of the value’s core identity in the same way that the trailing zeros in a
Decimal values are.
My main issue with DateTimeOffset is that it *is not a* DateTime and thus does not integrate well into the framework. Specifically, it can not be used in place of a DateTime but must be converted at various points. Ideally I would like to extend DateTime, but that is not possible. The only other solution is a common interface, but then many APIs would need to be updated to take advantage of that. (Backward compatibility could be maintained, though.)
For the most part, DateTimeOffset seems to have the required functionality. However, in the end I will still need to work with DateTime because it will not and can not integrate into the existing framework.
Honestly, I have created my own UTC-based DateTime wrapper. However, for the exact same reasons as DateTimeOffset, it too will not integrate into the framework.
This is the heart of the issue, and it is not being addressed.
Regarding the point about value type vs. reference type for DateTimeOffset. The reason that I would prefer a reference type is solely so that I can extend the type to my own needs (assuming it were not sealed). Making it a value type without any interfaces denies me of that.
And on a similar note, I entirely agree with chronos. Because DateTimeOffset does not extend DateTime or implement any common interface, it does not fit well into the framework. It is little more than a wrapper that any of can create on our own. What we need from you, Microsoft, is a means to integrate that well into your framework. As the designers of a *common framework*, that should be a primary objective.
I agree with the above posters. The type needs to fit well into the framework. That can be done with two methods: 1) type hierarchy (via inheritance) and 2) interfaces. You are not providing either. DateTimeOffset is nothing more than a wrapper around DateTime. The type does not suit my needs very well, so I have developed my own wrapper. It fits into the framework exactly as well as DateTimeOffset (ie, not at all). Either make DateTime inheritable (somehow) or provide a common interface. Anything else does not solve the fundamental problem.
I need an IDateTime interface too, but for slightly different reasons. I deal with a many BC dates. Unfortunately, the design of DateTime only permits dates from January 1, 0001 and up. While I have created my own implantation, it of course does not fit into the framework, and even worse, I can not even convert it to a DateTime type when needed.
DateTime is broken on so many levels. Provide us with a common IDateTime interface. Let us customize the type to our own specific needs. It was a poor design and it is time to fix it. The longer you wait, the harder it will be to deal with.
Thanks for the feedback everyone. We do plan to integrate DateTimeOffset throughout the Framework where appropriate. In .NET 3.5, we have taken the first steps by adding support for DateTimeOffset to XML Serialization and aligning the type with Microsoft SQL Server 2008. In the next version of the Framework after .NET 3.5, we plan to integrate DateTimeOffset more thoroughly throughout the Framework adding new overloads, methods, and properties where it makes sense to do so.
Justin Van Patten
CLR Program Manager
I do not mean to be rude, but you really are not comprehending the pains and difficulties that many of us are trying to convey.
1) DateTimeOffset does not extend DateTime or implement a common interface. Therefore it can be used as a replacement for the broken DateTime.
2) A default instance of DateTime is temporarily ambiguous. Ideally it should default to UTC. It can be manually set to UTC, but if ever forgotten, you have a bug which may not be so easy to find. The default DateTime is broken.
3) Conversion to DateTime is a potential source of error. If DateTimeOffset actually was a DateTime (via extension or a common interface), then no conversion would be necessary.
4) DateTime only allows dates from January 1st 0001. Custom types that fix this issue can not even be converted to DateTime when needed. No need for conversion if there was already a common interface.
5) The design of DateTimeOffset does not suite some developers. Yet you leave us with options for customizing it (extension, interface). Same for DateTime.
6) New overloads, methods, and properties for DateTimeOffset are not desired or needed. What is needed is overloads, methods, and properties for IDateTime.
Along with DateTime, DateTimeOffset is a complete of epic proportions. Provide us with an IDateTime interface and start updating signatures to use it. That is the only option to fix this terrible mess. And you can even maintain complete backward compatibility at the same time.
Call me a realist or a pessimist, but this subject should not really surprise anyone. Just last year the HashSet<T> was announced without an ISet<T> or even an abstract Set<T>. Anyone who wants another set type is, well, screwed. APIs are being designed around HashSet<T> when they really should be coded to ISet<T>. Just like DateTime, we all lose.
Like it or not, Microsoft is building a framework for themselves, not for everyone else. Ideally they should keep this stuff internal instead of teasing us with partially designed functionality. In the end, we all will need our own implementations that will not "fit" into the framework.
A truly useful framework would code to interfaces. That would be a huge win for everyone. Unfortunately this does not happen enough with the BCL.
Something learned during the Whidbey phase: with few exceptions, once Beta 1 is released, it is generally too late to get these kinds of things changed. And Beta 2 is right around the corner.
Interfaces are not a "silver bullet" to API usability problems. They are ideally fit when there can be multiple implementation of something very simple and obvious (for example, sorting).
DateTimeOffset is not a new implementation of DateTime. It is a combination of UTC DateTime and timezone offset. It can not be stored without data lose in datetime column in SQL Server or Oracle. And that's why it is not possible to abstract from DateTimeOffset and DateTime by using IDateTime interface.
After repeated experiences of frustration with the existing DateTime, I searched the web for help and found this page.
The problem that my team keeps running into it that DateTime is not always UTC. While we audit the code in an attempt to ensure that proper settings are consistently enabled, the team is large and some code inevitably slips through causing difficult to find and costly bugs.
Reading through the comments and some of the earlier posts, I really think that there should be a UtcDateTime type as others have suggested. However, it needs to integrate well into the framework, meaning that it will need to be a DateTime. At this late point in the game, the only option in some kind of common IDateTime interface.
DateTimeOffset does not seem to be what we need precisely because it is not a DateTime and does not share any common interfaces.
Unless you are going to depreciate DateTime and rewrite all existing related APIs, then DateTimeOffset is not a solution to the problem. An IDateTime interface, while requiring some API signature updates, seems to be an ideal solution moving forward to this really serious problem.
Interfaces are not the "silver bullet" to API usability problems. However, in this case, it is precisely what is needed. DateTimeOffset is not be a new implementation of DateTime. And that is precisely why it does not solve the
underlining problems with DateTime. What I need is a UtcDateTime that is a DateTime. Inheritance and interfaces are the only solutions. Inheritance is not possible for technical reasons, so a common interface needs to be implemented: IDateTime.
SQL Server and Oracle are not part of the framework and are thus immaterial. There are solutions for storing UTC data in databases, but this is not the appropriate forum for such a discussion.
Based on the feedback from my last CLR week ,
I think one CLR week a year is about right,
Have you ever had to deal with consumer and provider of webservices residing in different time zones