DateTime and TimeZones: a new type is needed

Kathy Kam asks if we should modify DateTime or create a new type to store time zone information.  I say give us a new type. My reasons are:
Size matters
DateTime in .NET is a pretty high precision (100 nanosecond resolution) storage, using most of the 64 bits.  In .NET 2.0 they took a couple of the upper most bits of DateTime’s 64 bits to indicate if the time was local, UTC, or unspecified. (a non breaking change).  But to store accurate representation of the time zone, and/or the offset then you’d need a lot more bits.  Time zone as an abbreviated string is going to take at least 3 or 4 bytes (32 bits gone).  Offset has to allow for minutes, (+- 720), so that’s another 27 or so bits.  So that leaves us 5 bits to store the actual value in… I don’t think so.
Reality is, a TZDateTime would require probably a full 128 bit to retain the precision DateTime currently has.
This has two significant issues, breaking code, and performance.  If you have any code that is reliant on the in memory size of a structure (or class) that has DateTime fields, then that code is seriously broken. You’d have to replace the DateTime with an Int64. however the likelihood of such code is in fact rare, as most code reliant on such structure layout is PInvoke centred code, and Win32 API typically uses different date storage mechanisms (such as Ole Date which is 8 bytes but a float)
The performance issue would remain though and maybe an overhead if you are doing a lot of date time crunching.
binary serialization : you’re broken.
Code simplicity
But apart from the size of the structure, the big issue I think is how simple will the code be.  At first you might say having two types is more complicated, but you need to consider the transition.  Do you really want to always be checking to see if the DateTime has it’s time zone set ?  how will you know if it’s an old style date, or a new style one ?  How will you tell if the code around that date structure has been updated to persist, and pass the time zone with it, or is the old code ?
Problems with a new type
On the other hand, a new type poses many issues.  It would require new types and support for data storage.   Hang-on, that’s a good thing though isn’t it, as this way we can ensure integrity of data. The cost though is it isn’t simply adding one type to the framework, rather it’s an issue of providing a mesh of supporting types and methods.
UI controls would also need to be updated, but perhaps a different DateTime picker is better than breaking the behaviour of the existing one ? Either way, it would require work on the DateTime pickers which is probably a good thing as we’d hope the next incarnation would also support nullable TZDateTime’s as well 🙂
And we’d probably also need an implicit conversion from DateTime to TZDateTime, but preferably an Explicit conversion from TZDateTime to DateTime.
Anyway, I’m probably drifting off into more the functionality I’d like to see the new timezone aware DateTime structure have (such as overloads on Add, that let you specify whether or nor to take DST transitions into account <g>).  My general feeling is this is a new type, with many new features. If DateTime was not a structure I would say inherit DateTime.  It’s a pity there isn’t an interface the two could share (hint hint).  But I think with the implicit casting to DateTime from the new structure, you could call existing code reasonably easily, and the potential loss of data (TZ offset) would be more obvious due to the explicit cast needed to bring the data back.  If it was just the same structure, I don’t think you’d ever know if the routine was likely to loose data or not.. the complexity of the type and it’s safe and proper usage would be too high.
So my vote is for a new data type, TZDateTime (or DateTimeTZ)

2 Comments so far

  1.   Jonathan Allen on September 8th, 2006          

    I think it should be called DateTimeZone, but besides that I’m behind you 100%.

    One question. Should a cast from DateTime to TZDateTime cause an exception if the DateTime doesn’t have a timezone? If not, should it default to local or UTC?

  2.   bill on September 8th, 2006          

    No it should not cause an exception, as that would:
    1.(i) require people to write more code always checking the DateTime kind
    (ii) which would then also result in people tacking arbitrary decisions about what to do if the kind is unspecified
    2. An implicit covnversion (widening) is one that should not fail, hence you should not throw exceptions there. If the conversion is likely to fail it shold be an explicit conversion not an implicit one.

    As to what to do when the DateTiem kind is unspecified, I beleive the appropiate action would be to treat it as a local DateTime, as is usually the case today. NOTE however, this ambiguity is exactly why a TZDateTime is needed.

    Developers would also have the choice to explicitly construct the TZDateTime, passing in the DateTime, and optionally setting the TZ. If the DateTime kind is unsepcified, no adjusting of the date is needed. If the kind is local or UTC, and the TZ is different from the kind, then the date time wold be adjusted to represent the same instance in time adjusted to the specified time zone.