user517406
user517406

Reputation: 13763

Javascript to convert UTC to local time does not work in Chrome

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

Answers (1)

TAS
TAS

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

Related Questions