When I use the Date() function to convert a date that comes from DB the conversion works as expected.
This is my code:
$.get(masterUri + "/odata/ViewAppointments")
.done(function (data) {
clubAppointments = new DevExpress.data.ArrayStore({
key: "id"
});
var start, end;
for (var x = 0; x < data.value.length; x++) {
start = new Date(data.value[x].Start_Datetime);
end = new Date(data.value[x].End_DateTime);
clubAppointments.insert({
id: x,
text: data.value[x].Client_Name,
SportId: parseInt(data.value[x].Sport_ID_ref),
Court_ID: parseInt(data.value[x].Court_ID),
startDate: start,
endDate: end,
status: data.value[x].TYPE
});
}
debugger;
});
The clubAppointments variable is just an ArrayStore from DevExtreme JS framework. [NOT IMPORTANT]
If you notice, I take every value from the array called "data.value" and insert the values into a new ArrayStore variable.
Before I do, I have to convert the date to javascript date so that my dxScheduler (Dextreme UI Widget) can read it.
Internet Explorer and FireFox works great. Look at the results of just viewing the last appointment:
FROM DATABASE [Using the Visual Studio debugger]:
data.value[11].End_DateTime = "2016-05-24T11:30:00"
AFTER CONVERSION [Using the Visual Studio debugger]:
clubAppointments._array[11].endDate = Tue May 24 2016 11:30:00 GMT-0400 (SA Western Standard Time)
This occurs on both IE and FireFox.
Sadly, this date conversion does not work well in Google Chrome at my side. Please watch the results once again here:
FROM DATABASE: [Using the Google Chrome debugger]:
End_DateTime:"2016-05-24T11:30:00"
AFTER CONVERSION [Using the Google Chrome debugger]:
endDate:Tue May 24 2016 07:30:00 GMT-0400 (SA Western Standard Time)
Please watch the following attachment for a clear view of whats going on: Image
You should parse date strings manually, do not leave it to the Date constructor (or Date.parse, they are equivalent). According to ECMAScript 2015, a date and time string in ISO 8601 format with no time zone should be treated as local, however some browsers will treat it as UTC (as you've discovered).
The only reliable way to parse date strings is to do it manually. If you only have one format, a small function is all that's required. If you have more requirements, a small library can help, there are plenty to chose from.
E.g. here's a function to parse an ISO 8601 format date and time string according the to current spec (though I disagree with how date only strings are treated as UTC, which is inconsistent with ISO 8601 and common sense).
/**
* Parse an ISO string with or without an offset
* e.g. '2014-04-02T20:00:00-0600'
* '2014-04-02T20:00:00Z'
* '2014-02'
*
* Allows decimal seconds if supplied
* e.g. '2014-04-02T20:00:00.123-0600'
*
* If the string is time and date with no offset, treat as local (per ECMA-262 ed 6)
* If date only, e.g. '2014-04-02' or '2014-02', treat as UTC date (per ECMA-262 ed 6)
*
* All parts after year are optional
* Don't allow two digit years to be converted to 20th century years
* @param {string} s - ISO 860 date string
*/
function parseISOString(s) {
var t = s.split(/\D+/g);
var hasOffset = /[-+]\d{4}$/.test(s);
var isZulu = /z$/i.test(s);
// Whether decimal seconds are present changes the offset field and ms value
var hasDecimalSeconds = /[T ]\d{2}:\d{2}:\d{2}\.\d+/i.test(s);
var offset = hasDecimalSeconds? t[7] : t[6];
var offSign;
var yr = +t[0],
mo = t[1]? --t[1] : 0,
da = +t[2] || 1,
hr = +t[3] || 0,
min = +t[4] || 0,
sec = +t[5] || 0,
ms = hasDecimalSeconds? +t[6] : 0,
// Reverse the sign of the offset
offSign = hasOffset? /-\d{4}$/.test(s)? 1 : -1 : 0,
offHr = hasOffset? offset/100 | 0 : 0,
offMin = hasOffset? offset%100 : 0;
// Ensure time values are in range, otherwise invalid date.
// Values can't be -ve as splitting on non-digit character
if (hr > 24 || min > 59 || sec > 59 || ms > 1000 || offHr > 24 || offMin > 59){
return NaN;
}
// Create a date object from date parts, check for validity
// Avoid two digit years being converted to 20th century
var d = new Date();
d.setUTCFullYear(yr, mo, da);
// Check that date values are valid
if (d.getUTCFullYear() != yr || d.getUTCDate() != da) {
return NaN;
}
// It there's no offset and there are time parts, use local date methods
if (!hasOffset && !isZulu && t[3] && t[4] && t[5]) {
d.setHours(hr, min, sec, ms);
// Otherwise, apply offset to minutes to use UTC date methods
} else {
min = hasOffset? +min + offSign * (offHr * 60 + offMin) : min;
d.setUTCHours(hr, min, sec, ms);
}
return d;
}
['2016-05-24T11:30:00','2016-05-24T11:30:00Z','2016-05-24T11:30:00+0530',
'2016-12-04']
.forEach(function(s) {
document.write('<br>' + s + '<br>' + parseISOString(s) + '<br>');
});