Click here to Skip to main content
Click here to Skip to main content

A TimeZone Aware DateTime Implementation

By , 24 Feb 2010
 

Introduction

This article focuses on how I've created a time zone aware DateTime wrapper. I do not claim to be an expert on the field, but I have spent some weeks of research on the topic, and I think I understand some of the complexities we need to address. The biggest problem we have today when working with .NET DateTime instances are that they, by default, represent local time, and they do not carry any information about which time zone they were originally created in. Working with DateTime instances created in another time zone than your own seems very difficult and awkward. A usual workaround has been to convert values to UTC, together with some time zone information, an offset, and if daylight saving time is in use, before serializing the information (to disk, database, or over the network). These are some of the issues this library tries to address.

Converting DateTime instances to UTC is, of course, supported by this library. This is currently the standard way of persisting date and time data to the database. When retrieving these DateTime instances, one would typically send the UTC date and time to some factory, together with all the meta data (such as offset, time zone definition, and a flag indicating if daylight saving is in use), and be able to produce a correct LocalDateTime instance with time local to the requested time zone. Then, instances of LocalDateTime will be exposed internally in the rest of the application to ease date and time manipulations. This is currently what we are doing where I work, and we have the challenge that some Use Cases and reports are working with different DateTime instances representing different time zones concurrently in the same report (view), and it is very important for our customers that this logic works correctly.

Background

If you start Googling around on the topic of DateTime implementation, you will come across these URLs:

Basically, all three BCL blog entries try to explain why DateTime became what it is, and that they do understand that a lot of API consumers are not very satisfied. They also delve into how they are trying to amend the situation with .NET 3.5's new date time structure called DateTimeOffset. Reading the blog comments is very interesting as most of the comments indicate the users are not satisfied with the current approach. Interestingly, the new DateTimeOffset does not carry time zone information, only a TimeSpan to represent the offset. Thus, this will not solve the problem of representing local time transparently and retrieving it as such somewhere else in the world. Also, when converting from one time zone to another, the DST rules are needed. Without including the time zone information, the receiver working with a serialized DateTimeOffset must guess about this. Now, most developers work around this problem as described earlier. But then again, are they any better off with the new structures offered by .NET 3.5 than they were with DateTime?

Another thing, you can write some code to look up time zone services or the tz-database to keep your time zone definitions up to date. This is pretty much similar to how Java bundles their time zones internally in the JRE. Take a look at the implementation of the TimeZone class to see how this can be done.

Using the Code

Now, let's look at how the LocalDateTime implementation works. I have provided many constructors; some constructors derive the time zone meta data from the Operating System and identify the TimeZone instance to use. But, if you would like to create a DateTime instance rooted in another time zone, then you should use the constructor below:

/// <summary>
/// Convenient constructor for creating a local date time instance in any time zone.
/// </summary>
/// <remarks>
/// Note that this constructor will not modify provided
/// date time value if provided time is within DST.
/// This should be corrected by the invoker,
/// or if the DateUtil.TimeZoneAdjustDateTime method is used,
/// this will be corrected automatically.
/// </remarks>
/// <param name="time">The time.</param>
/// <param name="zone">The time zone.</param>
public LocalDateTime(DateTime time, ITimeZone zone, bool isDST) : this()
{
    IsLocalTimeBased = false;
    ticks = time.Ticks;
    timeZoneId = zone.CanonicalID;
    this.isDST = isDST;
    NullInitSummerWinterDST();
}

For instance, using this constructor would look like this:

LocalDateTime cetDateTime = 
  new LocalDateTime(new DateTime(2008, 12, 1), TimeZones.CET, false);

I used Reflector on System.DateTime to create an IDateTime interface including all the public instance methods. Here is just a small excerpt of the interface:

/// <summary>
/// DateTime interface wrapping all methods
/// on DateTime so that you can interact with
/// an date time instance just as if it was a normal date time.
/// </summary>
public interface IDateTime
{
    #region Properties
    /// <summary>
    /// Gets the date component of this instance.
    /// </summary>
    IDateTime Date { get; }

    /// <summary>
    /// Gets the day of the month represented by this instance.
    /// </summary>
    int Day { get; }

    /// <summary>
    /// Gets the day of the week represented by this instance.
    /// </summary>
    DayOfWeek DayOfWeek { get; }

    /// <summary>
    /// Gets the day of the year represented by this instance.
    /// </summary>
    int DayOfYear { get; }

    /// <summary>
    /// Gets the hour component of the date represented by this instance.
    /// </summary>
    int Hour { get; }

    /// <summary>
    /// Gets a value that indicates whether the time represented
    /// by this instance is based on local time,
    /// Coordinated Universal Time (UTC), or neither.
    /// </summary>
    DateTimeKind Kind { get; }

    /// <summary>
    /// Gets the milliseconds component
    /// of the date represented by this instance.
    /// </summary>
    int Millisecond { get; }

    /// <summary>
    /// Gets the minute component of the date represented by this instance.
    /// </summary>
    int Minute { get; }

    /// <summary>
    /// Gets the month component of the date represented by this instance.
    /// </summary>
    int Month { get; }

    /// <summary>
    /// Gets a System.DateTime object that is set to the current date
    /// and time on this computer, expressed as the local time.
    /// </summary>
    IDateTime Now { get; }

This interface is, of course, implemented on the LocalDateTime so that functions that API programmers are used to are available on LocalDateTime. The type is also implemented as an immutable struct to behave as close to DateTime as possible. Thus, the instance created above could also look like:

IDateTime cetDateTime = 
  new LocalDateTime(new DateTime(2008, 12, 1), TimeZones.CET, false);

When creating one hundred million date time instances compared to creating one hundred million LocalDateTime instances, the creation of LocalDateTime instances had an extra cost if constructors that need to derive time zone information were used. But, by using the constructor meant for MSSQL or a factory inside your application that produces LocalDateTimes, there was no noticeable time difference (the DateTime struct was 600 milliseconds faster on creation of one hundred million instances).

/// <summary>
/// Internal constructor to be used
/// by SQL-server when creating an instance of the class
/// based on internally stored type value.
/// </summary>
/// <param name="ticks">The number of ticks that makes up a date</param>
/// <param name="timeZoneId">The CanonicalId as defined
///         by the Olson TZ-database for a given time zone.</param>
/// <param name="isDST">A stored value indicating
///       whether the ticks value is within a DST range.</param>
public LocalDateTime(long ticks, string timeZoneId, bool isDST) : this()
{
    this.ticks = ticks;
    this.timeZoneId = timeZoneId;
    this.isDST = isDST;
}

This constructor also reveals what columns you must create if you won't use LocalDateTime as a User Defined Type. By using a user defined type, these values will be stored along with the struct instance in a single column. To make this possible, I had to add some attributes to the struct and also implement the nullable interface:

[Serializable]
[SqlUserDefinedType(Format.Native)]
public struct LocalDateTime : IDateTime, INullable
{
....

Below is a passing Unit Test demonstrating that the LocalDateTime implementation is time-zone aware:

/// <summary>
/// First create a LocalDateTime in NY-time at 01:59:59AM,
/// one second before the timezone's summer time ends.
/// Due to different DST changes, converting to CET
/// will change the summer time to winter time 
/// for that exact point in time since CET ends
/// summer time before America/New York timezone does. 
/// While in CET time, add one second and convert
/// that LocalDateTime instance back into New York time. 
/// The time should now NOT be 2 AM, but actually 1 AM as the end of DST rule for 
/// America/New York timezone is to set the clock 1 hour back.
/// </summary>
[TestMethod]
public void TestAmerica_NewYorkEndDSTByConvertingToCETAndAddingOneSecondAndConvertingBack()
{
    // Get DST change day
    TimeZone tzNewYork = TimeZones.America__New_York;
    DaylightSavingTime winter = tzNewYork.WinterChange;

    int dayInMonth = DateUtil.FindDayInMonth(2009, winter.Month, 
                     winter.GetDayOfWeek(), winter.GetDayOccurrenceInMonth());
    DateTime winterDateTime = new DateTime(2009, winter.Month, dayInMonth);

    // Set time to 01:59 AM
    TimeSpan oneSecondBefore2AM = new TimeSpan(1, 59, 59);
    DateTime dateTime = winterDateTime.Add(oneSecondBefore2AM);

    // Create a LocalDateTime to represent this time with
    // TimeZone information specified, one second before DST ends
    LocalDateTime ldt = new LocalDateTime(dateTime, tzNewYork, true);

    // Assert that the dateTime instance is equal to localDateTime instance
    Assert.AreEqual(ldt.GetDateTime(), dateTime);

    // Assert that the localDateTime instance's DST flag is true
    Assert.IsTrue(ldt.IsDaylightSavingTime());

    LocalDateTime cet = LocalDateTime.ConvertTo(ldt, TimeZones.CET);

    // Add one second to both the dateTime instance and the cet instance
    dateTime = dateTime.AddSeconds(1);
    IDateTime localDateTime = cet.AddSeconds(1);

    //Transform the manipulated CET back to New York time:
    ldt = LocalDateTime.ConvertTo((LocalDateTime)localDateTime, ldt.TimeZone);

    // Assert that these are not equal as the dateTime instance
    // should be 02:00 AM while the localDateTime instance should be 01:00 AM
    Assert.AreNotEqual(ldt.GetDateTime(), dateTime);

    // Subtract one hour to the dateTime instance so that
    // it will be 01:00 AM and assert that these instances now are equal.
    Assert.AreEqual(ldt.GetDateTime(), dateTime.AddHours(-1));

    // Assert that localDateTime instance's DST flag now is set to false
    Assert.IsFalse(ldt.IsDaylightSavingTime());
}

Since I like to use NHibernate as my object relational mapper, I have created a CompositeUserType to make it possible to save this using the usual NHibernate mappings. This works for both UDT and the multicolumn approach.

This is the first version of this small library. It may contain bugs, and there are probably a lot of things to improve. If you have any feedback, please contact me so that I can improve this little library.

Policy Changes

Another approach worth looking into (which we currently have abandoned) is the possibility of registering the LocalDateTime struct as a 'User Defined Type' (UDT) in your favorite database. This would at least speed up data retrieval, since you would not have to convert UTC time to the offset time value for the time zone it should be expressed in. By utilizing user defined types, the information you usually use three or four columns to store can now be represented in a single column of type LocalDateTime.

After some discussion, we decided against utilizing a UDT in MSSQL. In the end, it may prove an extra burden upgrading customers if we need to re-register a UDT. Also, sorting and ordering based on date and time will not work as long as the LocalDateTime data is represented in local time to the defined time zone. At least, if UDT is used, the LocalDateTime should convert the date time to UTC and store it as such for consistent SQL manipulations in the DBMS. Although we consider these issues as such drawbacks that we ended up using the "three column approach", this doesn't mean that UDT might not be the best fit in other applications.

History

Added Unit Test project and more tests demonstrating how LocalDateTime works.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

steinard
Software Developer
Norway Norway
Member
http://www.linkedin.com/in/steinardragsnes

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralPerformance on Add/SubtractmemberJulian Skagen17 Feb '10 - 8:58 
Hi!
 
I grabbed your code and played around with it and found that there are some performance penalties when looping and calling AddHour() or Subtract(someLocalDateTime) within a loop. It seems like this could be more efficient it was possible to avoid converting to UTC for every Add/Subtract operation in the loop.
 
By the way, great library! It becomes very easy to handle date and times across different time zones using this lib.
 
Cheers,
Julian.
GeneralRe: Performance on Add/Subtractmembersteinard23 Feb '10 - 8:41 
Hi!
 
Thanks for the feedback Wink | ;)
I'll have a look at the problem. It's about time to upload an updated version. A lot of improvements have been done since last update.
Cheers,
Steinar.

GeneralRe: Performance on Add/Subtractmembersteinard24 Feb '10 - 0:22 
Hi!
 
I've tried to update this article but I was redirected to a page telling me to send an Article Update Request because this page was already marked as updated????
 
Anyway, I sent them the updated sources in a zip and hopefully they will update the download link. Anyway, if this should not work out well then send me an email at steinar.dragsnes__at__gmail.com
 
To increase performance by a magnitude of 5, I created a LocalDateTimeEnumerator class which is designed to enumerate on hour/day/month/year resolution. Since there is no time zone change when constantly adding 1 hour to a date time I was able to reduce the number of checks that is needed to be taken to just check around the DST boundary defined for that time zone.
 
For detailed information, please check out the LocalDateTimeEnumeratorTest.
Cheers,
Steinar.

GeneralMy vote of 1memberGilad Kapelushnik8 Dec '08 - 4:48 
poor design
GeneralRe: My vote of 1membersteinard8 Dec '08 - 9:08 
Hi!
 
Would you care to elaborate a little on that so that I can make it better?
 
Thanks for your opinion,
 
Thanks Wink | ;)
Steinar.

GeneralISO 8601memberPIEBALDconsult8 Dec '08 - 2:01 
Have you read up on ISO 8601?
 
"Time Zones" are evil; avoid them at all cost.
GeneralAgreed with the below posters.... [modified]memberaxelriet8 Dec '08 - 0:32 
Never, ever store local times for the aformentionned reasons. DateTime.UtcNow all the way!
 
BTW I just wonder: you did not miss the TimeZone[^] class by any chance?
 
modified on Monday, December 8, 2008 6:38 AM

GeneralRe: Agreed with the below posters.... [modified]membersteinard8 Dec '08 - 8:44 
Hi, no, I did not miss it, and by the way, you should use the new TimeZoneInfo class if possible. I do not use this class as I want to be backward compatible and because I do not want to rely on the registry for fetching time zone information. You have more control over the time zones if you pull them down from the tz-server and compile them in the library as constants. Then you simply update it a couple of times a year and you are up to date.
 
You can still store time as utc and use the library for working with hard types such as UtcDateTime, CetDateTime.
 
Thanks for feedback,
Steinar.
GeneralUTC for all storage is still the best way to go ...memberHightechRider7 Dec '08 - 17:28 
If you can convert the time to a UTC time that is still the best way to store it in your database because:-
 
1) There are no ambiguous or missing times in UTC time. Any timezone with daylight savings time has a spring-forward gap and a spring-back repeated hour. That messes up all manner of calculations: How many hours is it from 2:05AM to 2:07AM? In UTC time it's always 2 minutes but in local time it could be 2 minutes or it could be 1 hour and 2 minutes or it could be 'error no such time'.
 
2) All your times sort correctly even if they were entered by users in different timezones. So, user A commenting on user's B comment on user C's photo doesn't show their comments in the wrong order even if user C is in Europe, user A is in Japan and user B is in the USA. And user D gets to see the whole thread in whatever timezone they are in because you convert UTC to local on the way out in the user's local timezone.
 
3) Daylight savings time rules change from time to time. To be able to reliably say how many hours it is from DateTime A to DateTime B you would need to store every historical variation in the DST rules in order to be able to calculate that correctly, and even then because of (1) you couldn't calculate it in every case because there would be ambiguities.
 
The key exception to this rule is when you have a local datetime that you cannot convert to UTC time because you can't be sure of the timezone, e.g. Datetimes from digital cameras or camcorders where all you have is a local time and have no idea what timezone it is in.
 
The other one to watch for is where you have an event at a given time in a given location, e.g. 10AM: Family Reunion in Taos, New Mexico. In this case you need to do the UTC conversion in some timezone other than the one your user is in right now. And you want to store the fact that it is a time that should be shown in the local New Mexico timezone not the user's timezone.
 
Grouping is another key issue - you need to convert your UTC times into local times BEFORE you group them into days because my 'today' might not be the same as your 'today'.
GeneralRe: UTC for all storage is still the best way to go ...memberSoundman32.27 Dec '08 - 22:34 
I agree with this poster. Store everything in UTC and display in the users own timezone.
I've been doing time based stuff since the early nineties and had loads of problems until I adopted this method.
GeneralRe: UTC for all storage is still the best way to go ... [modified]membersteinard8 Dec '08 - 9:06 
Hi!
 
Thanks for your elaborations. I cannot say I disagree with you on anything. I think that I'm able to represent a local time without missing any hours due to DST if I store timezone information and a flag indicating if it is in DST time in the database. Unit tests should be able to verify this. Thus, at 2:59 AM on last Sunday in October and the DST flag is true, I would know that this is the hour that will be set back, and not the actual spring-back repeated hour. One minute later the clock will then turn to 2:00 AM and the isDST flag must be set to false.
 
1) I agree, all calculations on a date time should be performed in UTC time, but that does not imply that you should not wrap these calculations in a type and convert time back and forth keeping track of DST and your timezone.
 
2) I still agree, there is no reason why LocalDateTime instances should not be sorted in UTC time. Since each instance of a LocalDateTime could represent different timezones, how else should they be sorted?
 
3) Yes, this happens all the time. I thought I would use the a strategy pattern to load the different timezones pr year from a file. Others might want to store these historical timezones in a database, this is up to anyone else to decide.
 
Thanks for your input, I'm going to upload the unit test project so it becomes easier to see how this works.
 
Thanks Wink | ;)
Steinar.
modified on Tuesday, December 9, 2008 3:50 PM

NewsRe: UTC for all storage is still the best way to go ...membersteinard16 Apr '09 - 13:45 
Hi!
 
Thanks for the great feedback you provided a few months ago. Now the LocalDateTime API is shipped along with our product to around 50 customers all over Europe. During sprints this year we have found small bugs and more unit tests have been written. We also went for the classic three column storage in the DB, all times stored in UTC of course.
 
I would greatly appreciate if you (or anyone else) looked at the unit tests, seeing how the code works when working with DateTime instances representing other time zones then your own (as this was one of the major reasons for creating this library). And if any bugs are found, please report them to me so that I can fix them and prove them fixed with a unit test.
 
Thanks Wink | ;)
Steinar.

QuestionRe: UTC for all storage is still the best way to go ...memberGio Bejarasco11 Jun '09 - 11:42 
Hi. Great article. As a UDT developer, I'd love to see some sample scripts of the UDT under T-SQL. You mentioned it has been deployed already. Does this mean you're using the UDT in production database?
AnswerRe: UTC for all storage is still the best way to go ...membersteinard4 Aug '09 - 1:08 
Hi!
 
No, we decided against using LocalDateTime as a user defined type in SQL server. Customers would not like us to provide user defined types (they want a standard database for migrating data between DB systems), other questions brought up were how date time queries in the database would work, as many queries fetch rows between two dates, how LocalDateTime columns would display it's data etc. Thus I did not get the time needed to research this at all. So basically, we are using NHibernate and written some custom mapping logic so we never see any sql or construction of LocalDateTime between the database and our domain model. It all happens in the mapping logic of NHibernate and domain objects are populated with LocalDateTime instances stright away. But I think that UDT would be faster and I think there are appropriate usages for this. But for us the standard usage would be the three column approach: DateTime reportTime, string timeZoneId, bool isDst.
 
Just having this library is a great benefit for us. Currently, all applications are internally switching from DateTime to LocalDateTime. The process will be done in a week or two.
 
Feel free to download the code and play with it. Let me know how it goes.
 
Thanks Wink | ;)
Steinar.

GeneralRe: UTC for all storage is still the best way to go ...memberGio Bejarasco5 Aug '09 - 4:14 
I had my own share of headaches dealing with non-timezone aware datetimes. Topics like these are a great eye opener of how important this kind of data are. And I believe your clients are still on Sql Server 2005 or below right?
GeneralRe: UTC for all storage is still the best way to go ...membersteinard5 Aug '09 - 21:36 
Hi!
 
Yes, only a few are on 2005, the majority is on SQL server 2000. That is another reason for doing this in a rather traditional way when it comes to storing DateTimes in the database. The good thing is that the mapping from three columns to a single objects happens transparently to our code in NHibernate. So we never see those details and can work with LocalDateTime instances without considering timezone changes as these are all handled by the library.
 
Since last updated, lots of minor bugs have been identified and corrected and I will update the project in a few days. Thanks for great feedback.
 
Thanks Wink | ;)
Steinar.

GeneralRe: UTC for all storage is still the best way to go ...membersupercat925 Feb '10 - 4:54 
I would think the best way to store times is as a combination of absolute time, time zone, and time-zone-certainty indicator (such that a time could be stored as:
  1. 12:30 uct; time zone unspecified
  2. 12:30 uct; -6+1 (central daylight time)
  3. 7:30 local time, probably -6+1 (central daylight time)
  4. 7:30 local time; time-zone unknown
Information could be transferred to such a format from any other and back without any confusion or ambiguity not present in the original format. Further, storing information in this way would allow retrospective dates and times to be displayed correctly without having to maintain a list of all changes to DST rules.
GeneralRe: UTC for all storage is still the best way to go ...memberHightechRider25 Feb '10 - 5:24 
Your proposal would NOT allow a DateTime to be "displayed correctly without having to maintain a list of all changes to DST rules" for anyone outside the original user's timezone. To display the DateTime of an event to any user in whatever timezone they are in now you need to convert a DateTime to UTC first and then to their timezone, and to convert it to UTC you would need "a list of all changes to DST rules".
 
In fact, it's worse than that, you'd also need to know their precise location too because timezone boundaries change over time (see http://en.wikipedia.org/wiki/Time_in_Indiana[^]) and because there are variations even within a timezone.
 
See also special timezone considerations for "Navajo Indian Reservations" which further complicate matters.
 
In short, all developers should be encouraged to always store datetime values in UTC except in very rare circumstances with justification as to why it is impossible to store them in UTC. In those rare cases where UTC is impossible you are left with a value that is virtually useless for any calculation purposes.
GeneralRe: UTC for all storage is still the best way to go ...membersupercat925 Feb '10 - 6:11 
In short, all developers should be encouraged to always store datetime values in UCT except in very rare circumstances with justification as to why it is impossible to store them in UTC. In those rare cases where UTC is impossible you are left with a value that is virtually useless for any calculation purposes.
 
A problem with that is that in some cases, one will have more confidence in the fact that a particular event happened at a particular local time than that the fact that it at a particular absolute time; in other cases, one will have more confidence in the event having occurred at a particular absolute time than in its having occurred at a particular absolute time. In situations where one has total control over date/time generation, one can avoid trouble, but what should a system do when importing data which is not in UTC format (e.g. when copying data from a FAT-formatted drive)? Converting data repeatedly between UTC and local time is a recipe for disaster; importing the data with an assumed time zone, but with marked so local time had priority, would largely avoid such dangers).
 
As for the correctness of display, I guess that depends what one wants to display. Suppose someone moves their computer from California to New York. Should a file that was created at 9:00am in California be shown in the user interface as having been created at 9:00am or 5:00am? I would suggest that there would be great value in being able to show things both ways (probably my preferred format would be to generally show things in the local time where they occurred, with an indicator if the time-zone didn't match the current one).
GeneralRe: UTC for all storage is still the best way to go ...memberHightechRider25 Feb '10 - 6:33 
The FAT scenario would be a "rare circumstance" but even there you do not have enough information to do anything meaningful with the date time values because you do not know the source timezone or location. If the user gives you that extra data you should convert all the values to UTC for storage in the new system as you import them, but you will still have to make some assumptions in doing so ...
 
In the second example, if you have UTC in the database you CAN display the value in either timezone ("Created 9:00AM local time, 5:00AM California time") but if you only have local time you CANNOT do that without a complete history of all timezones and their historical time and boundary changes.
 
Worse though, if you only have local time and it's a timezone that recognizes DST there is one hour every year when the UTC time is ambiguous because the clocks went back. (And there's one hour where there should be no values, but you would need extra code to handle bad data that is in the missing hour.)
 
Consider also sorting scenarios, without UTC you cannot easily sort items according to when they occurred. If you have offices in California and New York I think you'll want to be able to order messages between them correctly!
 
Like I keep saying, UTC is the only sensible format to store date time information in a database. If you can't generate a UTC datetime from the input then the value you have may as well be stored as a string because there's very little you can do with it without a lot of extra effort (including a supporting database of all timezones and their historical changes), and even then you cannot have complete certainty and you have to deal with invalid times because of DST changes!
GeneralRe: UTC for all storage is still the best way to go ...membersupercat926 Feb '10 - 4:49 
HightechRider wrote:
The FAT scenario would be a "rare circumstance" but even there you do not have enough information to do anything meaningful with the date time values because you do not know the source timezone or location. If the user gives you that extra data you should convert all the values to UTC for storage in the new system as you import them, but you will still have to make some assumptions in doing so ...

 
If one stores the fact that the file was created at 11:23am local time, then copying the file back to a FAT disk will yield the same time stamp as the file had originally. Otherwise copying a file from FAT to NTFS, and then later copying it back to a FAT disk, may yield a different time stamp. Given the popularity of FAT-formatted USB memory sticks for file interchange, I wouldn't consider the FAT scenario to be a "rare circumstance".
 
HightechRider wrote:
In the second example, if you have UTC in the database you CAN display the value in either timezone ("Created 9:00AM local time, 5:00AM California time") but if you only have local time you CANNOT do that without a complete history of all timezones and their historical time and boundary changes.

 
My preferred approach, in case it was unclear, was to store both the time and the time-zone offset, so that one would essentially be storing both local and an absolute time; having those, along with an indicator of which time was more "reliable", would allow maximum versatility. One wouldn't need to have a complete history of historical timezone changes, since the timestamp would indicate what the offset was for that particular timestamp.
 
BTW, the normal hardware standard on PC's is to have the clock chip store local time in year-month-day hours-minutes-seconds format. There is a "daylight" flag in the hardware which doesn't do anything at the hardware level but get stored; if the PC notices that the daylight flag is not set, but the date is within the daylight-saving range, the software is supposed to, when it next reads the clock, set the time ahead an hour and set the daylight flag. Nearly all clock chips seem to work similarly. I wonder why it's hard to find a clock chip that simply keeps time in absolute seconds (since doing anything with time other than just displaying it is a lot more convenient when counting seconds than when dealing with yy-mm-dd h:m:s).
GeneralRe: UTC for all storage is still the best way to go ...membersteinard27 Feb '10 - 12:35 
Hi!
 
There is nothing in this library that dictates how time should be stored. Currently I'm using NHibernate mappings to store all LocalDateTime instances in UTC while I use a second column for the TimeZone id the UTC time should be converted into when retrieved from the database.
GeneralRe: UTC for all storage is still the best way to go ...memberpwasser25 Feb '10 - 16:01 
This is a great post that summarises the issues lucidly.
 
Those of us who were involved in Y2K??? learned a lot about all this back then.
 
Point 3 is very valid. I live in Perth Western Australia where we have had a number of changes to DST.
 
Time servers (and GPS) give us UTC for good reason - it allows us to UNAMBIGUOUSLY synchronise events occuring all over the world.
Peter Wasser

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130516.1 | Last Updated 24 Feb 2010
Article Copyright 2008 by steinard
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid