案例一:

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)


为什么第二个解析不正确?


当前回答

虽然CMS是正确的,将字符串传递到解析方法通常是不安全的,但新的ECMA-262第5版(又名ES5)规范在15.9.4.2节中建议Date.parse()实际上应该处理iso格式的日期。旧的规范没有这样的要求。当然,旧的浏览器和一些当前的浏览器仍然不提供这种ES5功能。

你的第二个例子没有错。正如date .prototype. toisostring()所暗示的那样,它是以UTC为单位指定的日期,但以本地时区表示。

其他回答

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
}

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
}

使用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是正确的,将字符串传递到解析方法通常是不安全的,但新的ECMA-262第5版(又名ES5)规范在15.9.4.2节中建议Date.parse()实际上应该处理iso格式的日期。旧的规范没有这样的要求。当然,旧的浏览器和一些当前的浏览器仍然不提供这种ES5功能。

你的第二个例子没有错。正如date .prototype. toisostring()所暗示的那样,它是以UTC为单位指定的日期,但以本地时区表示。

另一种解决方案是构建具有日期格式的关联数组,然后重新格式化数据。

此方法对于以不寻常的方式格式化的日期非常有用。

一个例子:

    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'];