假设我有两种不同类型的日期字符串 - 一个mysql日期戳和一个mysql日期+时间戳。
"2015-12-25"
"2015-12-25 00:00:00"
当我在JavaScript中解析这些时,我得到:
new Date("2015-12-25");
Thu Dec 24 2015 19:00:00 GMT-0500 (Eastern Standard Time)
new Date("2015-12-25 00:00:00");
Fri Dec 25 2015 00:00:00 GMT-0500 (Eastern Standard Time)
或者,在UTC中:
new Date("2015-12-25").toUTCString();
"Fri, 25 Dec 2015 00:00:00 GMT"
new Date("2015-12-25 00:00:00").toUTCString();
"Fri, 25 Dec 2015 05:00:00 GMT"
以某种方式添加时间会使日期解析成为我的时区小时。我想要的是某种功能,使这些都解析为同一个东西--GMT或不,我可以调整,只要结果已知是一个或另一个,无论传递的日期字符串。
我在实现一个涉及正则表达式和检测日期格式的解决方案之前,我认为可能有更好的方法来解决这个问题。
我找到了一些涉及Date.prototype.getTimezoneOffset()
的解决方案,但是对于这两个日期都会返回相同的内容,因为它们被解析为处于同一时区。
有什么想法吗?
答案 0 :(得分:2)
ECMAScript ed 5.1(又名ES5)要求将ISO 8601日期字符串解析为UTC,但ISO要求将它们解析为本地字符串。现在,当前的ECMAScript标准(版本6)与ISO一致,需要符合ISO标准的字符串,没有时区可以解析为本地。
<更新> ECMAScript 2016(第7版)再次更改,以便将YYYY-MM-DD格式的日期字符串解析为UTC,因此不再符合ISO 8601。< / update>。
因此,无论您是一个行为还是另一个行为取决于浏览器(如果您使用IE 8尝试它,您将获得NaN)。在ES5之前,解析所有字符串是依赖于实现的。
" 2015年12月25日"是一个没有时区的有效ISO 8601字符串,因此应根据ES5规则处理为UTC,并按照第6条规则处理。
" 2015-12-25 00:00:00"不是有效的ISO字符串(缺少" T"日期和时间之间),因此浏览器可以解析它们(非ISO字符串的解析在所有版本的ECMAScript中都依赖于实现)。
底线是不要使用Date构造函数来解析字符串(或 Date.parse )。自己解析它们。
要解析类似ISO的字符串,请使用以下内容。它将没有偏移的字符串视为UTC(每ES5),但现在可能应该更改为本地:
/**
* 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 no offset is supplied (or it's Z), treat as UTC (per ECMA-262)
*
* If date only, e.g. '2014-04-02' or '2014-02', treat as UTC date (per ECMA-262)
* 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 invalidDate = new Date(NaN);
var t = s.split(/\D+/g);
var hasOffset = /[-+]\d{4}$/.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,
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 invalidDate;
}
// 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 invalidDate;
}
// If there's an offset, apply it to minutes to get a UTC time value
min = hasOffset? +min + offSign * (offHr * 60 + offMin) : min;
// Set UTC time values of d
d.setUTCHours(hr, min, sec, ms);
return d;
}
它可以减少到不到一半,但它的编写易于阅读和维护。