案例一:
new Date(Date.parse("Jul 8, 2005"));
输出:
2005年7月08日上午00:00 GMT-0700 (PST)
案例二:
new Date(Date.parse("2005-07-08"));
输出:
2005 年 7 月 7 日星期四 17:00:00 GMT-0700 (PST)
为什么第二个解析不正确?
案例一:
new Date(Date.parse("Jul 8, 2005"));
输出:
2005年7月08日上午00:00 GMT-0700 (PST)
案例二:
new Date(Date.parse("2005-07-08"));
输出:
2005 年 7 月 7 日星期四 17:00:00 GMT-0700 (PST)
为什么第二个解析不正确?
当前回答
这个轻量级的数据解析库应该可以解决所有类似的问题。我喜欢图书馆,因为它很容易扩展。也有可能i18n它(不是很直接,但不是那么难)。
解析的例子:
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") );
其他回答
Until the 5th edition spec came out, the Date.parse method was completely implementation dependent (new Date(string) is equivalent to Date.parse(string) except the latter returns a number rather than a Date). In the 5th edition spec the requirement was added to support a simplified (and slightly incorrect) ISO-8601 (also see What are valid Date Time Strings in JavaScript?). But other than that, there was no requirement for what Date.parse / new Date(string) should accept other than that they had to accept whatever Date#toString output (without saying what that was).
从ECMAScript 2017 (edition 8)开始,实现需要解析dat# toString和dat# toUTCString的输出,但没有指定这些字符串的格式。
截至ECMAScript 2019(版本9),日期#toString和日期#toUTCString的格式已被指定为(分别):
ddd MMM DD YYYY HH:mm:ss ZZ[(时区名)]2018年7月10日星期二18:39:58 GMT+0530(美国标准时间) ddd, DD MMM YYYY HH:mm:ss Ze.g。2018年7月10日星期二13:09:58 GMT
提供2个以上的格式,日期。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
}
另一种解决方案是构建具有日期格式的关联数组,然后重新格式化数据。
此方法对于以不寻常的方式格式化的日期非常有用。
一个例子:
mydate='01.02.12 10:20:43':
myformat='dd/mm/yy HH:MM:ss';
dtsplit=mydate.split(/[\/ .:]/);
dfsplit=myformat.split(/[\/ .:]/);
// creates assoc array for date
df = new Array();
for(dc=0;dc<6;dc++) {
df[dfsplit[dc]]=dtsplit[dc];
}
// uses assc array for standard mysql format
dstring[r] = '20'+df['yy']+'-'+df['mm']+'-'+df['dd'];
dstring[r] += ' '+df['HH']+':'+df['MM']+':'+df['ss'];
两者都是正确的,但它们被解释为两个不同时区的日期。所以你比较了苹果和橘子:
// 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"
但我仍然强烈推荐Moment.js,它简单而强大:
// 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"
使用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也可能会给出不正确的结果。
CMS接受的答案是正确的,我刚刚添加了一些功能:
修剪和清洁输入空间 解析斜杠、破折号、冒号和空格 有默认的日期和时间
// parse a date time that can contains spaces, dashes, slashes, colons
function parseDate(input) {
// trimes and remove multiple spaces and split by expected characters
var parts = input.trim().replace(/ +(?= )/g,'').split(/[\s-\/:]/)
// new Date(year, month [, day [, hours[, minutes[, seconds[, ms]]]]])
return new Date(parts[0], parts[1]-1, parts[2] || 1, parts[3] || 0, parts[4] || 0, parts[5] || 0); // Note: months are 0-based
}