Javascript: Date() 函数在 Google Chrome 中不能完全工作
Javascript: Date() function does not fully work in Google Chrome
当我使用 Date() 函数转换来自数据库的日期时,转换按预期进行。
这是我的代码:
$.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]
如果您注意到,我从名为 "data.value" 的数组中取出每个值并将这些值插入到一个新的 ArrayStore 变量中。
在我这样做之前,我必须将日期转换为 javascript 日期,以便我的 dxScheduler(Dextreme UI 小部件)可以读取它。
Internet Explorer 和 FireFox 运行良好。查看刚刚查看上次约会的结果:
来自数据库
[使用 Visual Studio 调试器]:
data.value[11].End_DateTime = "2016-05-24T11:30:00"
转换后
[使用 Visual Studio 调试器]:
clubAppointments._array[11].endDate = Tue May 24 2016 11:30:00
GMT-0400 (SA Western Standard Time)
这在 IE 和 FireFox 上都会发生。
遗憾的是,这个日期转换在我这边的 Google Chrome 中效果不佳。请在这里再次观看结果:
来自数据库:
[使用 Google Chrome 调试器]:
End_DateTime:"2016-05-24T11:30:00"
转换后
[使用 Google Chrome 调试器]:
endDate:Tue May 24 2016 07:30:00 GMT-0400 (SA Western Standard Time)
请观看以下附件以清楚地了解发生了什么:
Image
您应该手动解析日期字符串,不要将其留给 Date 构造函数(或 Date.parse,它们是等价的)。根据 ECMAScript 2015,没有时区的 ISO 8601 格式的日期和时间字符串应被视为本地日期和时间字符串,但是某些浏览器会将其视为 UTC(如您所见)。
唯一 解析日期字符串的可靠方法是手动进行。如果您只有一种格式,那么只需要一个小函数即可。如果你有更多的要求,小图书馆可以提供帮助,有很多可供选择。
例如这是一个根据当前规范解析 ISO 8601 格式日期和时间字符串的函数(尽管我不同意将日期字符串视为 UTC 的方式,这与 ISO 8601 和常识不一致)。
/**
* 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>');
});
当我使用 Date() 函数转换来自数据库的日期时,转换按预期进行。
这是我的代码:
$.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]
如果您注意到,我从名为 "data.value" 的数组中取出每个值并将这些值插入到一个新的 ArrayStore 变量中。
在我这样做之前,我必须将日期转换为 javascript 日期,以便我的 dxScheduler(Dextreme UI 小部件)可以读取它。
Internet Explorer 和 FireFox 运行良好。查看刚刚查看上次约会的结果:
来自数据库 [使用 Visual Studio 调试器]:
data.value[11].End_DateTime = "2016-05-24T11:30:00"
转换后 [使用 Visual Studio 调试器]:
clubAppointments._array[11].endDate = Tue May 24 2016 11:30:00 GMT-0400 (SA Western Standard Time)
这在 IE 和 FireFox 上都会发生。
遗憾的是,这个日期转换在我这边的 Google Chrome 中效果不佳。请在这里再次观看结果:
来自数据库: [使用 Google Chrome 调试器]:
End_DateTime:"2016-05-24T11:30:00"
转换后 [使用 Google Chrome 调试器]:
endDate:Tue May 24 2016 07:30:00 GMT-0400 (SA Western Standard Time)
请观看以下附件以清楚地了解发生了什么: Image
您应该手动解析日期字符串,不要将其留给 Date 构造函数(或 Date.parse,它们是等价的)。根据 ECMAScript 2015,没有时区的 ISO 8601 格式的日期和时间字符串应被视为本地日期和时间字符串,但是某些浏览器会将其视为 UTC(如您所见)。
唯一 解析日期字符串的可靠方法是手动进行。如果您只有一种格式,那么只需要一个小函数即可。如果你有更多的要求,小图书馆可以提供帮助,有很多可供选择。
例如这是一个根据当前规范解析 ISO 8601 格式日期和时间字符串的函数(尽管我不同意将日期字符串视为 UTC 的方式,这与 ISO 8601 和常识不一致)。
/**
* 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>');
});