Search code examples
javascriptdatedatetimehighchartsmilliseconds

Parsing to milliseconds changes date


I'm having trouble parsing a date from a json fetched from a server. The format of the date is "YYYY-MM-dd HH-mm-ss CST" (with the timezone at the end), this is the first entry:

2015-01-06 00:00:00 CST

I'm using Highcharts for plotting the data, and I need to parse that into milliseconds for the a correct use in the x-axis (datetime). I'm not very familiar with date conversions in javascript, so I keep getting strange results (the parsed value in milliseconds is always wrong, therefore plotting the graph in incorrect points).

//obj['Time'] has the time value received = "2015-01-06 00:00:00 CST"

var fecha=obj['Time'].split(" ")[0].split("-"),
    hora=obj['Time'].split(" ")[1].split(":")[0];

var from = Date.parse( new Date(fecha[0], fecha[1], fecha[2], hora) );

So, I've tried the following: 1) Parsing the obj['Time'] directly. 2) Creating a new date object (stored in the 'from' variable) with the explicit values from the "manual splitting of the input date" and parsing that.

console.log("Original: " + obj['Time'] );
console.log("1) " + Date.parse(obj['Time']));
console.log("2) " + from);

console.log("Response 1: " + new Date( Date.parse(obj['Time']) ) );
console.log("Response 2: " + new Date( from ) );

These are the results:

Original: 2015-01-06 00:00:00 CST
1) 1420524000000
2) 1423177200000

Response 1: Tue Jan 06 2015 07:00:00 GMT+0100 (CET)
Response 2: Fri Feb 06 2015 00:00:00 GMT+0100 (CET)    

I believe that new Date() is using my local timezone and making a conversion because the value has an offset of 1 hour (GMT+0100 ???)... So everything has an "offset" that shouldn't be there. Maybe someone can give me a heads up on what is the correct way to parse this :)

Thanks!

Note: I don't need to show the timezone in the charts, I just need to have the correct datetime value.

Also, I'm aware of the 0-index of the month when creating the new Date object, that's why it shows Feb instead of Jan, but it's still not correct with that fix


Solution

  • var date = "2015-01-06 00:00:00 CST".replace(/-/g, "/");
    var orgDate = new Date(date);
    var dateParsed = Date.parse(orgDate); //parse to timestamp. (In milliseconds)
    
    document.write("Timestamp CST: " + dateParsed);
    document.write("<br />");
    document.write("<br />"); 
    var dateToUTC = new Date(dateParsed);
    
    document.write("UTC/GMT: " + dateToUTC.toUTCString());
    document.write("<br />");
    document.write("Local: " + dateToUTC.toString());
    var timeStringUTC = Date.parse(new Date(dateToUTC.toUTCString()));
    document.write("<br />"); 
    document.write("<br />"); 
    
    var UTCthen = orgDate.getUTCFullYear()+"-"+(parseInt(orgDate.getUTCMonth())+1 < 10 ? "0"+(parseInt(orgDate.getUTCMonth())+1) : orgDate.getUTCMonth()+1) + "-" + (orgDate.getUTCDate() < 10 ? "0"+orgDate.getUTCDate() : orgDate.getUTCDate())+"T00:00:00.000Z"
    document.write("Timestamp UTC: " + Date.parse(UTCthen) );
    document.write("<br />");   
    document.write("Difference (milliseconds): " + (dateParsed - Date.parse(UTCthen)) + " // = 6 hours");  //6 hours

    Do not parse via split. Just replace the dashes with /. This will make it a valid date for Date.parse. As you can see in the snippet. The date is sent in the CST time, which converted to UTC shows us that it's actually six in the morning in London. The example also shows the difference in milliseconds between both of them. I convert the parsed date back to it's original UTC timestamp. This is done in this line:

     var UTCthen = orgDate.getUTCFullYear()+"-"+(parseInt(orgDate.getUTCMonth())+1 < 10 ? "0"+(parseInt(orgDate.getUTCMonth())+1) : orgDate.getUTCMonth()+1) + "-" + (orgDate.getUTCDate() < 10 ? "0"+orgDate.getUTCDate() : orgDate.getUTCDate())+"T00:00:00.000Z";
    

    This line gets the UTC date back and appends the time after it "T00:00:00.000Z" forcing the Date.parse to think that this is a ISO string using Z (Zulu) is GMT/UTC time.

    So using Date.parse on UTCthen should get you the normalized version of your timestamp.