情况一:
new Date(Date.parse("Jul 8, 2005"));
输出:
2005年7月8日星期五00:00:00 GMT-0700(PST)
案例二:
new Date(Date.parse("2005-07-08"));
输出:
Thu Jul 07 2005 17:00:00 GMT-0700(PST)
为什么第二次解析不正确?
new Date(Date.parse("Jul 8, 2005"));
2005年7月8日星期五00:00:00 GMT-0700(PST)
new Date(Date.parse("2005-07-08"));
Thu Jul 07 2005 17:00:00 GMT-0700(PST)
为什么第二次解析不正确?
Both are correct, but they are being interpreted as dates with two different timezones. So you compared apples and oranges:
// local dates
new Date("Jul 8, 2005").toISOString() // "2005-07-08T07:00:00.000Z"
new Date("2005-07-08T00:00-07:00").toISOString() // "2005-07-08T07:00:00.000Z"
// UTC dates
new Date("Jul 8, 2005 UTC").toISOString() // "2005-07-08T00:00:00.000Z"
new Date("2005-07-08").toISOString() // "2005-07-08T00:00:00.000Z"
我删除了该Date.parse()
调用,因为它已自动用于字符串参数。我还使用ISO8601格式比较了日期,因此您可以直观地比较本地日期和UTC日期之间的日期。时间相隔7个小时,这是时区差异,也是为什么测试显示两个不同的日期。
创建这些相同的本地/ UTC日期的另一种方法是:
new Date(2005, 7-1, 8) // "2005-07-08T07:00:00.000Z"
new Date(Date.UTC(2005, 7-1, 8)) // "2005-07-08T00:00:00.000Z"
// parse string
moment("2005-07-08").format() // "2005-07-08T00:00:00+02:00"
moment.utc("2005-07-08").format() // "2005-07-08T00:00:00Z"
// year, month, day, etc.
moment([2005, 7-1, 8]).format() // "2005-07-08T00:00:00+02:00"
moment.utc([2005, 7-1, 8]).format() // "2005-07-08T00:00:00Z"
这个轻量级的日期解析库应该解决所有类似的问题。我喜欢该库,因为它很容易扩展。也有可能(不是很简单,但是就不那么难了)。
解析示例:
var caseOne = Date.parseDate("Jul 8, 2005", "M d, Y");
var caseTwo = Date.parseDate("2005-07-08", "Y-m-d");
然后格式化回字符串(您会注意到两种情况给出的结果完全相同):
console.log( caseOne.dateFormat("M d, Y") );
console.log( caseTwo.dateFormat("M d, Y") );
console.log( caseOne.dateFormat("Y-m-d") );
console.log( caseTwo.dateFormat("Y-m-d") );
尽管CMS是正确的,认为将字符串传递到parse方法通常是不安全的,但15.9.4.2节中的新ECMA-262第5版(也称为ES5)规范建议Date.parse()
实际上应该处理ISO格式的日期。旧的规范没有这样的要求。当然,旧的浏览器和某些当前的浏览器仍然不提供此ES5功能。
您的第二个示例没有错。它是UTC中指定的日期,由Date.prototype.toISOString()
表示,但是以您当地的时区表示。
根据http://blog.dygraphs.com/2012/03/javascript-and-dates-what-mess.html的格式,“ yyyy / mm / dd”解决了常见问题。他说:“请尽可能将日期字符串粘贴到“ YYYY / MM / DD”。它被普遍支持且明确。使用这种格式,所有时间都在本地。我已经设置了测试:http : //jsfiddle.net/jlanus/ND2Qg/432/ 此格式:+通过使用ymd排序和4位数字的年份避免了日和月顺序的歧义+避免了UTC与本地问题的冲突dygraphs的家伙通过使用斜杠+ danvk来符合ISO格式,他说这种格式在所有浏览器中都很好。
使用moment.js解析日期:
var caseOne = moment("Jul 8, 2005", "MMM D, YYYY", true).toDate();
var caseTwo = moment("2005-07-08", "YYYY-MM-DD", true).toDate();
第三个参数确定严格的解析(从2.3.0版本开始可用)。没有它,moment.js可能还会给出错误的结果。
疯狂是有办法的。通常,如果浏览器可以将日期解释为ISO-8601,它将被解释为日期。“ 2005-07-08”属于此阵营,因此被解析为UTC。“ 2005年7月8日”不能,因此在当地时间进行了解析。
看到JavaScript和日期,真是麻烦!更多。
在第5版规范发布之前,该Date.parse
方法完全依赖于实现(除后者返回数字而不是a之外,其他方法new Date(string)
等效)。在第5版规范中,添加了该要求以支持简化的(并且略有错误) ISO-8601(另请参见JavaScript中有效的日期时间字符串是什么?)。但是除此之外,除了必须接受任何输出(不说那是什么)之外,对什么/ 应该接受没有任何要求。Date.parse(string)
Date
Date.parse
new Date(string)
Date#toString
如2017年的ECMAScript(版本8)的,被要求的实现来解析其输出Date#toString
和Date#toUTCString
,但是未指定这些字符串的格式。
从ECMAScript 2019(版本9)开始,Date#toString
和的格式Date#toUTCString
分别指定为:
提供了2种Date.parse
应在新的实现中可靠解析的格式(请注意,支持并不普遍,并且不兼容的实现将在一段时间内继续使用)。
我建议手动解析日期字符串,并将Date构造函数与年,月和日参数一起使用,以避免产生歧义:
// parse a date in yyyy-mm-dd format
function parseDate(input) {
let parts = input.split('-');
// new Date(year, month [, day [, hours[, minutes[, seconds[, ms]]]]])
return new Date(parts[0], parts[1]-1, parts[2]); // Note: months are 0-based
}
在从CMS接受的答案是正确的,我刚才已经增加了一些功能: