Skip Navigation Links / Posts / Post
Search site. 
Powered by Google
Darren Neimke (Me)

My Book

Readify

">ASP.NET MVP


Interesting Portals 

NetVibes
This portal feels similar to PageFlakes in many ways but I love their gallery. They also have a feature whre certain chrome elements only become visible when you hover over the web part.

Xtra
A New Zealand news portal. I especially liked the content rotator web part at the top of the middle row. Seems like a nice way to allow a user to browse through data.

 

Posts Archive 

Displaying dates and times in a local users time zone

Categories

Yesterdy I wrote about the TimeZones web service that I've added to this site and today I'll further explain the need for the web service.  To start, let's take a look at the problem of dates and break it into 2 segments: The date value and the format of the date value.

Formatting a culture aware date.

Let's say that you are from the US and you visit my site.  On reading an article (and after sighing that this guy doesn't know what he's talking about) you notice that the time that page says that the article was written on 18/1/2006.  Hrmm, you think to yourself... what is the 18th month again?  This is of course because in the US, dates are formatted as mm/dd/yyyy whereas in Australia here they are formatted as dd/mm/yyyy.

The answer to fixing the formatting of dates is thankfully quite simple.  Rather than formatting the date for a specific culture you can dynamically read the culture for the current user from the accept-languages array that is passed along with the head section of the request.  To do this you simply set the culture of the current thread when the request begins and then delegate all of the formatting of dates and number strings to the framework - in other words, it just works!  Here's the code that you can place in your application's BeginRequest method to achieve this outcome:

void Application_BeginRequest(Object sender, EventArgs e) {
    try {
        if (Request.UserLanguages.Length > 0) {
            Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(Request.UserLanguages[0]);
            Thread.CurrentThread.CurrentUICulture = new CultureInfo(Request.UserLanguages[0]);
        }
    } catch (Exception ex) {
        PublishException(ex);
    }
}


SUB has that code in its startup so go ahead and try it out.  In Internet Explorer open up Tools | Options and choose "Languages" from the General tab.  In there you can add language or change the order of your language preferences.  Change it by adding Arabic or Chinese as your first preference and refresh the browser to see how the dates for this article are formatted.


Setting the correct date value

OK, so formatting culture aware dates is a breeze.  Just a couple of lines of code.  But what about storing the value that is used?  That's somewhat harder.  Here's a scenario:

Your website is hosted on a webserver that is located on the west coast of the US and you are currently living in Australia.  You use the web interface that is supplied with your blogging software to add a new article at 8:00am Australian time which is about 1:00pm Pacific time.  A time difference of 19 hours.

The next week, the people hosting your website move to Greenland and so when you post your next article - again at 8:00am Australian time, the time on the server is now 6:00pm on the previous day.  A time difference of 14 hours.

Finally, daylight time ends in Australia and you post another article at 8:00am Australian time which is now 7:00pm in Greenland.  A difference of 13 hours.

So how would you write a single piece of code that would always know to display the published times of your articles in Australian time?  One way would be to use javascript on the client and pass through the clients time to the server and use that.  It would work but it's cumbersome.

The better way - and the way that it is done for SUB - is to immediately store all dates in UTC time at the time that they are entered.  Working out the current UTC time is a no brainer:


     currentArticle.DateCreated = DateTime.UTCNow ;
     currentArticle.Modified = DateTime.UTCNow ;

The reason for storing the dates in UTC time is that it's easy to work with because every country already has a pre-existing way of defnining an offset from that time to work back to their own local time - the timezone difference.

Now that the time is stored as UTC time it can simply be converted to the local time of a given time zone as soon as it is reloaded from storage.  In the case of SUB the logic for doing that looks like this:


DateTime dt1 = DateTime.Parse(node.Attributes["dateCreated"].Value);
DateTime dt2 = DateTime.Parse(node.Attributes["dateModified"].Value);               
               
TimeZoneInformation info = TimeZoneInformation.FromName(
    BlogConfigurationSettings.TimeZoneName
    );


DateTime utc1 = info.FromUniversalTime(dt1);
DateTime utc2 = info.FromUniversalTime(dt2);

this.DateCreated = utc1;
this.DateModified = utc2;


See that the UTC times are pulled from the XML storage and then the TimeZoneInformation class is spun up for the time zone that the blog has been configured to use.  Then, using that class (which itself uses the underlying Windows API's) the UTC time can easily be converted to the timezone that the blog has been configured to use.

When the data is stuffed back into storage - such as when it is edited - the TimeZoneInformation class is again used to convert the local time back to UTC time as shown in the next snippet:


TimeZoneInformation info = TimeZoneInformation.FromName(
    BlogConfigurationSettings.TimeZoneName
    );

DateTime utc1 = info.ToUniversalTime(this.DateCreated);
DateTime utc2 = info.ToUniversalTime(this.DateModified);


attr = node.OwnerDocument.CreateAttribute("dateCreated");
attr.Value = FormatDateTime(utc1);
node.Attributes.Append(attr);

attr = node.OwnerDocument.CreateAttribute("dateModified");
attr.Value = FormatDateTime(utc2);
node.Attributes.Append(attr);

So when you read this article and you see that it was posted on 19/01/2006 at 8:19:10 AM (if your browser language is Australian anyway) you will know that I wrote it on the morning of the 19th January and not at 1:00am on the morning of the 20th January as would be the case if I was using the server times to store dates.

posted 1/19/2006 6:21:58 PM

 

Comments:

There are no comments to display for this post.

 

Comments are currently disabled for this post.