2006-01-08

AJAX × Date × Time × Time zones - best practices

Are you developing a site or application which relies on javascript, which somewhere on some page or in some view shows some time, or a date, or even a weekday to the visitor? Registration time, for instance. Or an advance notice of your next scheduled downtime? Anything at all! Do you also let visitors from other cities, and maybe even from other countries, visit your web site?

Great! Then this article is for you.

Because if you do, then you have run into the problem of time zones. Or, if you haven't, then your poor visitors have. In a typical scenario, you are in one time zone, your web server in another and the visitor is in some third place you can't even begin to imagine. Azerbadjan, perhaps. Or Tadjmbekistan. (No, I'm kidding; there is no Tadjmbekistan. ...or is there?)

Time zones are our friends, as common people; they make clock readings correspond vaguely to the height of the sun on the sky, letting us wake up almost at the same time in the morning wherever we are on the planet. Very convenient way of organizing work hours with light hours. It's not perfect, though, and in a vain attempt of doing some slight adjustments to the sun's annoying habit of drifting some over our hours, we adopted daylight savings time, DST for short, half of the year, shifting our scale by an hour to compensate. This has been widely regarded as a bad move, and has over the course of centuries in all likelihood given us much more trouble than ever the Y2K problem did. But we're used to it, and it's hard to switch back, even though we now have artificial lighting so we can perform work any time we well please anyway.

What time and day is it right now? You probably have an answer that fits your local reality well. Your web server probably has an idea of its own, too. It might even be in concert with yours; it mostly at least gets the weekday right. But on the other side of the globe, it might still be yesterday. Or already be tomorrow, from your point of view. And you bet you will have visitors from there, who find it at best bothersome that your web site insists on getting these things wrong.

So you append a "PST" to your time readings.

No, you don't. Humans hate performing time zone math. They are not even very good at it. And your visitors from Azerbadjan don't even know what it stands for. And those who do, will wonder if that is Pacific Standards Time, or if it's maybe daylight savings time over there, and in either case, how many longitudes away is PST, anyway? Then they will very likely get an off by one error in their calculation anyway, and you bet they will be pissed at that self centered... Well, let's stop there; we all get the point.

So you introduce a time zone option in your user settings.

No, you don't. Or at least you shouldn't, if this is the problem you are trying to solve. A time zone choice is good if you, for example, want your site to be able to relate time in one visitor's time zone to the time in other visitor's time zones, but for now, we just want to format times for one visitor in her own frame of reference.

Besides, time zones are complicated things, with local political rules, all unlike the rest, and only roughly corresponding with the longitude of the visitor. "Naïve" time zones, like "UTC+1" for central Europe, for instance, will be off by an hour half of the year, and real time zones, like "Europe/Stockholm", where DST rules are taken into account, is a whole lot of work and knowledge to maintain, or have your programming language / environment maintain, and always get right. And was there really no Tadjmbekistan? If there were, would the guys who wrote the functions to handle the math know about their rulesets? And did they also cater for the changes they did on becoming the People's Democratic Republic of Tadjmbekistan last year?

Unlikely.

So, what do you do?

Your visitor's browser knows what time zone it is in. It even knows what time it is. And, it's programmable. See? You probably knew all those things already; after all you are developing applications for it, in it, and the rest is history. So you let the browser do the math for you. And for your visitor.

There is an easy way, and the hard way. And as the result will be the same, I suggest you don't bother much with Javascript's meagre support for time zone arithmetics with date.getTimezoneOffset() and similar trickery, because there is a beautiful time zone called unix time, which all good programming environments handle, including javascript. What time is it in unix time, right this moment?

Click to find out.

Yes. A number. And it isn't even related to time zones; unix time is the same, everywhere; in space, too, actually. And your visitor's browser knows how to convert it to the time zone the computer was set up for. It's as trivial as passing that integer to the constructor of the javascript Date object. Multiplied by a thousand, to get it in milliseconds (which is the native time unit to javascript), rather than seconds. Similarly, if your environment provides nanosecond timestamps, divide by a thousand instead.

Generalizing wildly, I'll assume you pull most times from a MySQL database, in which case you should tell it to give you unix times using SELECT UNIX_TIMESTAMP(modified) AS modified, for instance. Do it as close to the data source as possible to have as little code trying to apply local understanding of date and time mathematics as possible, to avoid unnecessary pitfalls. Pass this integer along to the client, and format it appropriately to the visitor. I would suggest a format for dates which lists month names rather than figures, as variants on the theme X/Y/Z theme offer too many interpretations, forcing the reader to guess which variant you prefer, even if you are kind and foreseeing enough to supply four digit years.

Here, you might actually want to provide a configuration option on how the visitor prefers to read dates and time. But don't try being too clever, bundling the choice of date format with the choice of country, or interface language (as does Google Mail, who move on to downgrading functionality if you opt for a Swedish interface -- for instance, you suddenly can't choose sender addresses if you switch to the Swedish locale). Suggesting default choices based on locale choice is good, assuming what goes with what is not.

Here is the most trivial date formatting method possible to get you started or for debugging purposes, and one somewhat more sanitized version. Most of you will probably want to cook up something better; browse your options among the many available methods of the Date object for primitives. Just remember to stay clear of the legacy getYear() function; it's getFullYear() you want to use. If you use some library, it probably already has good date formatting methods that will do a good job if you pass them a Date object.
function formatDebug( timeInteger )
{
return (new Date( timeInteger )).toString();
}

function formatTime( time )
{
function zeropad( n ){ return n>9 ? n : '0'+n; }
var t = time instanceof Date ? time : new Date( time );
var Y = t.getFullYear();
var M = t.getMonth(); // month-1
var D = t.getDate();
var d = t.getDay(); // 0..6 == sun..sat
var day = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'][d];
var mon = ['Jan','Feb','Mar','Apr','May','Jun',
'Jul','Aug','Sep','Oct','Nov','Dec'][M];
var h = t.getHours();
var m = t.getMinutes();
var s = t.getSeconds();
return day +' '+ D +' '+ mon +', '+ Y +', '+
zeropad(h)+':'+zeropad(m)+':'+zeropad(s);
}

As you are pioneering this field of end-user usability, you may want to state that times and dates are indeed given in the visitor's frame of reference, as people have generally come to expect to see times given in some random and hence typically fairly useless time zone. This can be seen as a not entirely bad reason for actually providing a time zone configuration option, should you want one. I would suggest defaulting it to "auto" or "local time" using the above method, though, as that is most likely what the user would want to see, anyway. This way, the configuration option actually doubles as documentation of what times the site shows, in a place a visitor is likely to look for it. To make it extra apparent that you render proper times, you might equip the page with the setting with a printout of present time, which the visitor will easily recognize as the time her computer clock shows (since they are in fact one and the same).

Similarly, if your web site does not require javascript, neither should you introduce this requirement just for handling date and times. You can do both, though, if you have the time zone configuration option doing time zone math server side, and provide the javascript version for locally rendered times. It might look like this in rendered code:
<noscript>Jan 8, 2006, 14:26</noscript>
<script type="text/javascript">
document.write(formatTime(new Date(1136726801*1000)))
</script>

...That's all we have time for today. Hopefully, you and your visitors will have all the time in the world, and get them properly in sync too. Best of luck to you all!
blog comments powered by Disqus