Javascript 为什么Date.parse会给出错误的结果? 案例一: 输出:
2005年7月8日星期五00:00:00 GMT-0700(太平洋标准时间) 案例二: 输出: 2005年7月7日星期四17:00:00 GMT-0700(太平洋标准时间)Javascript 为什么Date.parse会给出错误的结果? 案例一: 输出:,javascript,date,Javascript,Date,2005年7月8日星期五00:00:00 GMT-0700(太平洋标准时间) 案例二: 输出: 2005年7月7日星期四17:00:00 GMT-0700(太平洋标准时间) 为什么第二个解析不正确?在第五版规范出台之前,该方法完全依赖于实现(newdate(string)等同于,只是后者返回的是一个数字而不是一个Date)。在第5版规范中,增加了支持a的要求(另请参见)。但除此之外,对Date.parse/newdate(string)应该接受的内容没有任何要求,除了他们必须接受任何Date#
为什么第二个解析不正确?在第五版规范出台之前,该方法完全依赖于实现(
newdate(string)
等同于,只是后者返回的是一个数字而不是一个Date
)。在第5版规范中,增加了支持a的要求(另请参见)。但除此之外,对Date.parse
/newdate(string)
应该接受的内容没有任何要求,除了他们必须接受任何Date#toString
输出(不说是什么)
从ECMAScript 2017(第8版)开始,需要实现解析其输出的Date#toString
和Date#toutString
,但未指定这些字符串的格式
自ECMAScript 2019(第9版)起,和的格式已分别指定为:
例如2018年7月10日星期二18:39:58 GMT+0530(IST)
例如2018年7月10日星期二13:09:58 GMT
Date.parse
应该在新的实现中可靠地解析(注意,支持并不普遍,不兼容的实现将在一段时间内继续使用)
我建议手动解析日期字符串,并与年、月和日参数一起使用,以避免歧义:
//以yyyy-mm-dd格式解析日期
函数解析日期(输入){
让parts=input.split('-');
//新日期(年、月[、日[、小时[、分钟[、秒[、毫秒]])
返回新日期(部件[0],部件[1]-1,部件[2]);//注意:月份以0为基础
}
虽然将字符串传递到解析方法通常是不安全的,但第15.9.4.2节中的新(也称ES5)规范建议Date.parse()
实际上应该处理ISO格式的日期。旧规范没有提出这样的要求。当然,旧的浏览器和一些当前的浏览器仍然不提供这种ES5功能
你的第二个例子没有错。它是UTC中指定的日期,如
date.prototype.toISOString()
所示,但在您的本地时区中表示。有一些方法可以解决这个问题。作为一般规则,如果浏览器可以将日期解释为ISO-8601,则它会。“2005-07-08”属于这个阵营,因此被解析为UTC。“2005年7月8日”不能,因此在本地时间对其进行解析
有关更多信息,请参见。根据格式“yyyy/mm/dd”解决了常见问题。
他说:“只要有可能,你的日期字符串就坚持使用“YYYY/MM/DD”。这是一种普遍支持且明确的格式。使用这种格式,所有时间都是本地的。”
我设置了测试:
此格式:
+通过使用y-m-d排序和4位年份,避免了日和月订单的模糊性
+通过使用斜杠避免UTC与本地不符合ISO格式的问题
+danvk说这种格式在所有浏览器中都很好 另一种解决方案是使用日期格式构建关联数组,然后重新格式化数据 此方法对于以不常见方式格式化的日期非常有用 例如:
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'];
mydate='01.02.12 10:20:43':
myformat='dd/mm/yy HH:mm:ss';
dtsplit=mydate.split(/[\/.:]/);
dfsplit=myformat.split(/[\/.:]/);
//为日期创建关联数组
df=新数组();
对于(dc=0;dc这应该可以解决所有类似的问题。我喜欢这个库,因为它很容易扩展。它也可以i18n它(不是很直接,但不是那么难)
解析示例:
var caseOne = Date.parseDate("Jul 8, 2005", "M d, Y");
var caseTwo = Date.parseDate("2005-07-08", "Y-m-d");
并格式化回字符串(您会注意到这两种情况给出的结果完全相同):
在最近编写JS解释器的经历中,我对ECMA/JS日期的内部工作进行了大量的思考。因此,我想我会在这里投入2美分。希望分享这些东西能帮助其他人了解浏览器在处理日期方面的差异
输入端
所有实现都将其日期值在内部存储为64位数字,表示自1970-01-01 UTC(GMT与UTC相同)以来的毫秒数(ms)。此日期是ECMAScript纪元,其他语言(如Java)和POSIX系统(如UNIX)也使用此日期。纪元之后的日期为正数,之前的日期为负数
以下代码在所有当前浏览器中都被解释为相同的日期,但带有本地时区偏移:
Date.parse('1/1/1970'); // 1 January, 1970
在我的时区(EST,即-05:00),结果是18000000,因为这是5小时内的毫秒数(夏令时月份只有4小时)。不同时区的值不同。ECMA-262中指定了此行为,因此所有浏览器都以相同的方式执行此操作
虽然主要浏览器将输入字符串格式解析为日期时存在一些差异,但就时区和夏令时而言,它们基本上对它们的解释是相同的,尽管解析在很大程度上依赖于实现
但是,ISO 8601格式是不同的。它是ECMAScript 2015(第6版)中明确列出的所有实现必须以相同方式解析的仅有两种格式之一(另一种是指定的格式)
但是,即使对于ISO 8601格式字符串,一些实现也会出错。以下是Chrome和Firefox的比较输出,当我的机器上最初使用ISO 8601格式字符串为1970年1月1日(纪元)编写此答案时,所有实现都应将其解析为完全相同的值:
Date.parse('1970-01-01T00:00:00Z'); // Chrome: 0 FF: 0
Date.parse('1970-01-01T00:00:00-0500'); // Chrome: 18000000 FF: 18000000
Date.parse('1970-01-01T00:00:00'); // Chrome: 0 FF: 18000000
- 在第一种情况下,“Z”说明符表示输入为UTC时间,因此不偏离历元,结果为0
- 在第二种情况下,“-0500”说明符表示输入以GMT-05:00为单位,并且两种浏览器都解释输入
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") );
Date.parse('1/1/1970'); // 1 January, 1970
Date.parse('1970-01-01T00:00:00Z'); // Chrome: 0 FF: 0
Date.parse('1970-01-01T00:00:00-0500'); // Chrome: 18000000 FF: 18000000
Date.parse('1970-01-01T00:00:00'); // Chrome: 0 FF: 18000000
Date.parse('1970-01-01T00:00:00'); // 18000000
Date.parse('1970-01-01'); // 0
console.log(new Date(Date.parse("Jul 8, 2005")).toString()); // Local
console.log(new Date(Date.parse("2005-07-08")).toString()); // UTC
console.log(new Date(Date.parse("Jul 8, 2005")).toString());
console.log(new Date(Date.parse("2005-07-08T00:00:00")).toString());
console.log(new Date(Date.parse("2005-07-08T00:00:00Z")).toString());
console.log(Date.parse("1/1/1970"));
console.log(Date.parse("1/1/1970 12:00:00 AM"));
console.log(Date.parse("Thu Jan 01 1970"));
console.log(Date.parse("Thu Jan 01 1970 00:00:00"));
console.log(Date.parse("Thu Jan 01 1970 00:00:00 GMT-0500"));
let m = moment('1/1/1970', 'M/D/YYYY');
- toString
- toDateString
- toTimeString
- toLocaleString
- toLocaleDateString
- toLocaleTimeString
- toUTCString
- toISOString
In Chrome
toString Thu Jan 01 1970 00:00:00 GMT-05:00 (Eastern Standard Time)
toDateString Thu Jan 01 1970
toTimeString 00:00:00 GMT-05:00 (Eastern Standard Time)
toLocaleString 1/1/1970 12:00:00 AM
toLocaleDateString 1/1/1970
toLocaleTimeString 00:00:00 AM
toUTCString Thu, 01 Jan 1970 05:00:00 GMT
toISOString 1970-01-01T05:00:00.000Z
In Firefox
toString Thu Jan 01 1970 00:00:00 GMT-05:00 (Eastern Standard Time)
toDateString Thu Jan 01 1970
toTimeString 00:00:00 GMT-0500 (Eastern Standard Time)
toLocaleString Thursday, January 01, 1970 12:00:00 AM
toLocaleDateString Thursday, January 01, 1970
toLocaleTimeString 12:00:00 AM
toUTCString Thu, 01 Jan 1970 05:00:00 GMT
toISOString 1970-01-01T05:00:00.000Z
"12/4/2013" -> toUCT -> [storage] -> toLocal -> print "12/4/2013"
var inputTimestamp = "2014-04-29 13:00:15"; //example
var partsTimestamp = inputTimestamp.split(/[ \/:-]/g);
if(partsTimestamp.length < 6) {
partsTimestamp = partsTimestamp.concat(['00', '00', '00'].slice(0, 6 - partsTimestamp.length));
}
//if your string-format is something like '7/02/2014'...
//use: var tstring = partsTimestamp.slice(0, 3).reverse().join('-');
var tstring = partsTimestamp.slice(0, 3).join('-');
tstring += 'T' + partsTimestamp.slice(3).join(':') + 'Z'; //configure as needed
var timestamp = Date.parse(tstring);
(new Date(tstring)).getTime()
var caseOne = moment("Jul 8, 2005", "MMM D, YYYY", true).toDate();
var caseTwo = moment("2005-07-08", "YYYY-MM-DD", true).toDate();
// 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"
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"
// 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
}