Reputation: 13763
I have written some Javascript to convert a database datetime in UTC format into local datetime. It works fine in Firefox and IE, but does not work in Chrome (for some reason it adds 3 hours to the times). Here is my code, any advice would be very appreciated :)
EDIT : The datetime is passed into my first function in the format '2014-06-21 20:00:00'
function convertUTCTimeToLocal(utc24HrDateTime) {
//first convert from 24hr to 12hr clock
var twentyFourHrTime = convertDateToTime(utc24HrDateTime);
var twelveHrTime = convert24hrTo12Hr(twentyFourHrTime);
var twelveHrDateTime = convert12HrToDateTime(utc24HrDateTime, twelveHrTime);
var utc12HrDateTime = twelveHrDateTime + ' UTC';
var date = new Date(utc12HrDateTime);
var dayMonthTimeOnly = convertToDayMonthTimeOnly(date);
return dayMonthTimeOnly;
}
function convert24hrTo12Hr(time) {
// Check correct time format and split into components
time = time.toString().match(/^([01]\d|2[0-3])(:)([0-5]\d)(:[0-5]\d)?$/) || [time];
if (time.length > 1) { // If time format correct
time = time.slice(1); // Remove full string match value
time[5] = +time[0] < 12 ? ' AM' : ' PM'; // Set AM/PM
time[0] = +time[0] % 12 || 12; // Adjust hours
}
return time.join(''); // return adjusted time or original string
}
function convertDateToTime(fixtureDate) {
var d = new Date(fixtureDate); // now
var y = d.getFullYear(); // the full year (4 digits)
var m = d.getMonth() + 1; // 0-based month
var dt = d.getDate(); // 0-based day of the month
dt = dt < 10 ? '0' + dt : dt; // add a preceding 0 to numbers less than 10
var h = d.getHours(); // 0-based hours
h = h < 10 ? '0' + h : h; // add a preceding 0 to numbers less than 10
var mn = d.getMinutes(); // minutes
mn = mn < 10 ? '0' + mn : mn; // add a preceding 0 to numbers less than 10
return h + ':' + mn;
}
function convert12HrToDateTime(fixtureDate, twelveHrTime) {
var d = new Date(fixtureDate); // now
var y = d.getFullYear(); // the full year (4 digits)
var m = d.getMonth() + 1; // 0-based month
var dt = d.getDate(); // 0-based day of the month
dt = dt < 10 ? '0' + dt : dt; // add a preceding 0 to numbers less than 10
return m + '/' + dt + '/' + y + ' ' + twelveHrTime;
}
function convertToDayMonthTimeOnly(fixtureDate) {
var d = new Date(fixtureDate); // now
var y = d.getFullYear(); // the full year (4 digits)
var m = d.getMonth() + 1; // 0-based month
var dt = d.getDate(); // 0-based day of the month
dt = dt < 10 ? '0' + dt : dt; // add a preceding 0 to numbers less than 10
var h = d.getHours(); // 0-based hours
h = h < 10 ? '0' + h : h; // add a preceding 0 to numbers less than 10
var mn = d.getMinutes(); // minutes
mn = mn < 10 ? '0' + mn : mn; // add a preceding 0 to numbers less than 10
return dt + '/' + m + ' ' + h + ':' + mn;
}
Upvotes: 0
Views: 1085
Reputation: 2079
Looking at the data returned from the ajax call in the page http://brasil2014.azurewebsites.net/Team/Brazil I was able to reproduce the observation using the following test (written using QUnit):
test("convertUTCTimeToLocal", function(assert) {
var expected = "12/6 22:00",
actual = convertUTCTimeToLocal("2014-06-12T20:00:00");
assert.equal(actual, expected);
});
(My time zone is GMT+1, but with daylight savings, hence I am expecting the time to be offset +2 hours).
I was able to further drill down the problem using the following test case:
test("convertDateToTime", function(assert) {
var expected = "20:00",
actual = convertDateToTime("2014-06-12T20:00:00");
assert.equal(actual, expected);
});
Changing the first lines of the function convertDateToTime
to:
function convertDateToTime(fixtureDate) {
var d = new Date(fixtureDate); // now
console.log(d);
...
}
showed me that the value of d
already was converted from UTC to local time.
Some investigation showed that the underlying cause is the fact that JavaScript engines are free to interpret the date in any timezone it wants. See the following answer for more details.
Using this knowledge I rewritten and simplified the the code as follows:
function convertUTCTimeToLocal(fixtureDate) {
function zeroPad(num) {
return num<10 ? '0'+num : num;
}
var d = new Date(fixtureDate + "Z"),
m = d.getMonth() + 1,
dt = zeroPad(d.getDate()),
h = zeroPad(d.getHours()),
mn = zeroPad(d.getMinutes());
return dt + '/' + m + ' ' + h + ':' + mn;
}
The following test case shows that it works correctly on both Chrome and Firefox:
test("convertUTCTimeToLocal", function(assert) {
var expected = "12/6 22:00",
actual = convertUTCTimeToLocal2("2014-06-12T20:00:00");
assert.equal(actual, expected);
})
Upvotes: 1