我知道有很多关于这个主题的答案(太多不能阅读所有这些),但我不理解为什么Date.parse
正在返回
'Sun Oct 21 2018 00:00:00 GMT+0100 (GMT Summer Time)'
来自字符串'2018-10-20T23:00:00Z'
所有时间都返回+ 1小时
我错过了明显的事吗?可能这与+0100 GMT
有关,但我需要做些什么才能确保它正确解析?
由于
答案 0 :(得分:1)
首先,我强烈建议你从不使用 Date 构造函数(或 Date.parse ,它们等同于解析)到解析字符串。始终使用小功能或合适的库(建议及以下链接)。
如果根据ECMA-262解析,那么' 2018-10-20T23:00:00Z'将被解析为UTC。如果使用 toString (或通过调用 toString 的方法,如console.log(new Date())
)将结果日期发送到输出,则通常使用主机时区来计算& #34;本地"值。
toString 生成的字符串格式取决于实现,因此可能不包含时区,或者可能以意外方式显示,并且可能在不同主机中有所不同。
根据ECMA-262,如果你想要' 2018-10-20T23:00:00Z'要被视为本地,请删除" Z":
var s = '2018-10-20T23:00:00Z';
var t = s.replace(/z$/i,'');
console.log(t);
console.log(new Date(t).toString());

但是,在我的第一条评论之后,即使省略了Z,Safari 10.0.3也似乎将字符串视为UTC,因此您的结果可能不正确,具体取决于主机。 Firefox似乎做对了。
我不能强调你不应该依赖 Date 或 Date.parse 进行解析。如初。
虽然为特定格式编写自己的解析器很容易,但有些人使用库感觉更好。考虑fecha.js(这是一个小的,解析和格式化)或moment.js(这不是很小,但也有助于算术,可以包括时区功能)。
E.g。这是一个小的ISO扩展格式解析器,尽可能兼容并尽可能少地使用Date方法:
/* Parse ISO date string in format yyyy-mm-ddThh:mm:ss.sss+hh:mm or Z
** @param (string} s - string to parse in ISO 8601 extended format
** yyyy-mm-ddThh:mm:ss.sss+/-hh:mm or z
** time zone can omit separator, so +05:30 or +0530
** @returns {Date} - returns a Date object. If any value out of range,
** returns an invalid date.
*/
function parseISO(s) {
// Create base Date object
var date = new Date();
var invalidDate = new Date(NaN);
// Set some defaults
var sign = -1, tzMins = 0;
var tzHr, tzMin;
// Trim leading and trailing whitespace
s = s.replace(/^\s*|\s*$/g,'').toUpperCase();
// Get parts of string and split into numbers
var d = (s.match(/^\d+(-\d+){0,2}/) || [''])[0].split(/\D/);
var t = (s.match(/[\sT]\d+(:\d+){0,2}(\.\d+)?/) || [''])[0].split(/\D/);
var tz = (s.match(/Z|[+\-]\d\d:?\d\d$/) || [''])[0];
// Resolve timezone to minutes, may be Z, +hh:mm or +hhmm
// substr is old school but more compatible than slice
// Don't need to split into parts but makes validation easier
if (tz) {
sign = /^-/.test(tz)? 1 : -1;
tzHr = tz == 'Z'? 0 : tz.substr(1,2);
tzMin = tz == 'Z'? 0 : tz.substr(tz.length - 2, 2)*1;
tzMins = sign * (tzHr*60 + tzMin);
}
// Validation
function isLeap(year){return year % 4 != 0 || year % 100 == 0 && year % 400 != 0}
// Check number of date parts and month is valid
if (d.length > 3 || d[1] < 1 || d[1] > 12) return invalidDate;
// Test day is valid
var monthDays = [,31,28,31,30,31,30,31,31,30,31,30,31];
var monthMax = isLeap(d[0]) && d[1] == 2? 29 : monthDays[d[1]];
if (d[2] < 1 || d[1] > monthMax) return invalidDate;
// Test time parts
if (t.length > 5 || t[1] > 23 || t[2] > 59 || t[3] > 59 || t[4] > 999) return invalidDate;
// Test tz within bounds
if (tzHr > 12 || tzMin > 59) return invalidDate;
// If there's a timezone, use UTC methods, otherwise local
var method = tz? 'UTC' : '';
// Set date values
date['set' + method + 'FullYear'](d[0], (d[1]? d[1]-1 : 0), d[2]||1);
// Set time values - first member is '' from separator \s or T
date['set' + method + 'Hours'](t[1] || 0, (+t[2]||0) + tzMins, t[3]||0, t[4]||0);
return date;
}
console.log('UTC : ' + parseISO('2018-10-20T23:00:00Z').toString());
console.log('Local: ' + parseISO('2018-10-20T23:00:00').toString());
&#13;