views:

56

answers:

3

I have a page which allows a user to view and edit times (with dates) stored in a database. The times are stored in the database in UTC and attached to a location with a different timezone. When the user views the times they are shown in the attached timezone and not necessarily the timezone of the browser. The user should then be able to edit a time and make and AJAX request. I need to be able to convert the inputted time from an arbitrary timezone to UTC in javascript, but the only conversion javascript seems to allow is from browser timezone to UTC. Passing an absolute offset in javascript is not going to work because the user should be able to edit times before or after daylight savings. This seems like it should be a problem that has been solved before... any pointers?

A: 

I don't think you have to do the timezone conversion on the browser. You can just display an "opaque" date time on the client, let them modify it, then post to the server to convert it to UTC, as required.

Dean Harding
A: 

Not sure if I should put this as an answer but I cannot leave a comment as I did not associate that temporary account with this ID...

Unfortunately it looks like doing the time zone calculation server side is the only clean way to do this, however I'm still hopeful someone might have another solution. By convention in this code all times should be sent in UTC and I'd like to avoid breaking that convention (and making it confusing in other places we might use the service call) if possible.

Nathan
+1  A: 

This is an extremely nasty problem. As long as the user is presented with all times in his/her own timezone (or in GMT), you would have no problem. But asking JS to provide accurate local Daylight Saving Time values for different locales is nasty stuff. The browser is aware of GMT and local time and (thanks to the OS) it also knows when DST kicks in locally. But without changing the user's system timezone information, JS has no way of telling when DST kicks in in another locale. The rules of when DST comes into effect not only differ from country to country, the date can change unexpectedly over time (remember when North American countries recently moved DST dates?). You can likely figure out the locale DST details on your server pretty easily and communicate that to the browser. But it's probably not practical to attempt it entirely in the browser. You could have a sort of DST_changeover_by_locale array in your application, but you'd need to update it periodically.

[EDIT] There seems to be some confusion about how the JS Date object works in regards to timezones. Here are some useful points:

Timezone offsets

// Create a time in winter (Standard time)
dt = new Date('Jan 1 2010 12:00:00 GMT-0000'); 
alert(dt.getTimezoneOffset()); 
// In Japan right now, users would see "-540"
// In New York right now, users would see "300"

// Create a time in summer (DST)
dt = new Date('Jul 1 2010 12:00:00 GMT-0000'); 
alert(dt.getTimezoneOffset()); 
// In Japan right now, users would see "-540"
// In New York right now, users would see "240"
// NOTE: Japan has no DST while NY does

Parsing dates to local time

// The following will all return the same time string, which will be 
// the time according to the user's OS time settings and locale
alert((new Date('Jun 25 2010 13:30:00 GMT-0230'))); // Newfoundland time
alert((new Date('Jun 25 2010 13:00:00 GMT-0300'))); // Atlantic time
alert((new Date('Jun 25 2010 12:00:00 GMT-0400'))); // Eastern time
alert((new Date('Jun 25 2010 11:00:00 GMT-0500'))); // Central time
alert((new Date('Jun 25 2010 10:00:00 GMT-0600'))); // Mountain time
alert((new Date('Jun 25 2010 9:00:00 GMT-0700'))); // Pacific time

Timestamps

// If you don't want to work with strings, use numbers instead. 
// These return the JS timestamp for the same values above. 
// The value is a *delta*, so it is unaffected by DST.
alert((new Date('Jun 25 2010 13:30:00 GMT-0230')).getTime()); // Newfoundland time
alert((new Date('Jun 25 2010 13:00:00 GMT-0300')).getTime()); // Atlantic time
alert((new Date('Jun 25 2010 12:00:00 GMT-0400')).getTime()); // Eastern time
alert((new Date('Jun 25 2010 11:00:00 GMT-0500')).getTime()); // Central time
alert((new Date('Jun 25 2010 10:00:00 GMT-0600')).getTime()); // Mountain time
alert((new Date('Jun 25 2010 9:00:00 GMT-0700')).getTime()); // Pacific time
Andrew