HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Conversion of datetime strings in PHP pages to user's timezone

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
conversiontimezonephpuserpagesstringsdatetime

Problem

I am working on a PHP/MySQL application that uses a different time zone 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:

" />


And, every instance of a datetime string is wrapped thus:

datetime_column ?>


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?

Solution

I would think it would be easier and more reliable to use timezone offsets rather than exact server time vs. client time. You can get the client-side offset using new Date().getTimezoneOffset() which returns the offset in minutes from UTC. When the timezone is +2 then the offset is -120.

PHP

" />


HTML



JavaScript

var serverTimeZone= $("meta[name='timezoneoffset']").attr("content").substring(0,3);
// getTimezoneOffset returns (client timezone * -60). 
// With timezones the the formula would be (clientTz - serverTz) * 60 * 60000
var timezoneOffset = (new Date().getTimezoneOffset() + (serverTimeZone * 60)) * 60000;
$("span.datetime-convert").each(function(){
    var date = parseDatetime($(this).text());
    if(date) { // If date is not wellformed the script would crash without this guard
      var offsetDate = new Date(date.getTime() + timezoneOffset);
      $(this).text(offsetDate .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;
}


Also there's no need to calculate the offset for each individual date. It can be actually a bit misleading when the offset is slighlty different for each date.

http://jsfiddle.net/xXVPC/1/

More functional:

var serverTimeZone= $("meta[name='timezoneoffset']").attr("content").substring(0,3);
// getTimezoneOffset returns (client timezone * -60). 
// With timezones the the formula would be (clientTz - serverTz) * 60 * 60000
var timezoneOffset = (new Date().getTimezoneOffset() + (serverTimeZone * 60)) * 60000;
$("span.datetime-convert").each(function(){
    var e = $(this);
    parseDatetime(e.text(), new function(date) {
      var offsetDate = new Date(date.getTime() + timezoneOffset);
      e.text(offsetDate.toLocaleString());
    });
});
function parseDatetime(value, callback) {
    var a = /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/.exec(value);
    if (a) {
        callback(new Date(+a[1], +a[2] - 1, +a[3], +a[4], +a[5], +a[6]));
    }
}

Code Snippets

<meta name="timezoneoffset" content="<?php echo date('P') ?>" />
<meta name="timezoneoffset" content="+0200" />
var serverTimeZone= $("meta[name='timezoneoffset']").attr("content").substring(0,3);
// getTimezoneOffset returns (client timezone * -60). 
// With timezones the the formula would be (clientTz - serverTz) * 60 * 60000
var timezoneOffset = (new Date().getTimezoneOffset() + (serverTimeZone * 60)) * 60000;
$("span.datetime-convert").each(function(){
    var date = parseDatetime($(this).text());
    if(date) { // If date is not wellformed the script would crash without this guard
      var offsetDate = new Date(date.getTime() + timezoneOffset);
      $(this).text(offsetDate .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;
}
var serverTimeZone= $("meta[name='timezoneoffset']").attr("content").substring(0,3);
// getTimezoneOffset returns (client timezone * -60). 
// With timezones the the formula would be (clientTz - serverTz) * 60 * 60000
var timezoneOffset = (new Date().getTimezoneOffset() + (serverTimeZone * 60)) * 60000;
$("span.datetime-convert").each(function(){
    var e = $(this);
    parseDatetime(e.text(), new function(date) {
      var offsetDate = new Date(date.getTime() + timezoneOffset);
      e.text(offsetDate.toLocaleString());
    });
});
function parseDatetime(value, callback) {
    var a = /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/.exec(value);
    if (a) {
        callback(new Date(+a[1], +a[2] - 1, +a[3], +a[4], +a[5], +a[6]));
    }
}

Context

StackExchange Code Review Q#3534, answer score: 3

Revisions (0)

No revisions yet.