DateTime and TimeZones: a new type is needed
Fri, Sep 8 2006 14:44
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.
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)