I am working on an PHP/MySQL application that uses a different timezone from the server it runs on, and neither of the timezones are UTC. I'm converting displayed times to be in the user's timezone, and am wondering whether my approach is sensible. I would love any feedback you might have.
Firstly, the application's current time is written to the output HTML page as a meta
value:
<meta name="date" content="<?php echo date('Y-m-d H:i:s') ?>" />
And, every instance of a datetime
string is wrapped thus:
<span class="datetime-convert"><?php echo $data->datetime_column ?></span>
Then, after the page is loaded, the following JQuery gets the application time, the user time, figures out the difference between these, and adds that difference to the datetime data:
$("span.datetime-convert").each(function(){
var serverTime = parseDatetime($("meta[name='date']").attr("content"));
var userTime = new Date();
var userOffset = new Date(userTime.getTime() - serverTime.getTime());
var timeToConvert = parseDatetime($(this).text());
var convertedTime = new Date(timeToConvert.getTime() + userOffset.getTime());
$(this).text(convertedTime.toLocaleString());
});
function parseDatetime(value) {
var a = /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/.exec(value);
if (a) {
return new Date(+a[1], +a[2] - 1, +a[3], +a[4], +a[5], +a[6]);
}
return null;
}
What am I doing wrong?! :-)
Update 1: I fixed the calculation of userOffset
to use getTime()
.
Update 2: Thanks to Aleksi's feedback, the script now only calculates the offset once, and does so not from the time provided in the meta
element, but a TZ offset in seconds. parseDatetime()
is as above.
// Get client and server timezone offsets in seconds.
var serverTimezone = $("meta[name='timezoneoffset']").attr("content");
var clientTimezone = new Date().getTimezoneOffset() * -60; // getTimezoneOffset returns (client timezone * -60)
// Get the offset between the server and client, in milliseconds.
var timezoneOffset = (clientTimezone - serverTimezone) * 1000;
$("span.datetime-convert").each(function(){
var timeToConvert = parseDatetime($(this).text());
if (timeToConvert) {
var convertedTime = new Date(timeToConvert.getTime() + timezoneOffset);
$(this).text(convertedTime.toLocaleString());
}
});
See also my gist with this code.