Javascript没有正确解析日期

问题描述:

我一直在Date原型上使用一些扩展来执行一些操作(建议:不要这样做,它会使日期对象失效;对于我而言,我当前的项目太晚了),最近一直有比平常更多的问题。Javascript没有正确解析日期

为H中解析字符串:M格式,我做了一个自定义函数,并将其分配到日期原型是这样的:

Date.__parse = Date.parse; 

Date.parse = function(string){ 
    var pattern = /^\d{1,2}:\d{1,2}/ig; 

    var today = new Date(); 

    if (pattern.exec(string)){ 
     var year = today.getFullYear(); 
     var month = today.getMonth()+1; 
     var day = today.getDate(); 

     var t = year+"-"+month+"-"+day+" "+string; 
     var timestamp = Date.__parse(t); 

     return new Date(timestamp); 
    } 
    else{ 
     return new Date(Date.__parse(string)); 
    } 
} 

丑陋当你尝试登录的日期对象,但工作直到最近。

有一段时间,Date.parse似乎与“d-m-Y”格式的日期一起工作,但最近它在我做它时返回“无效日期”。

在主要浏览器解析日期或对规格进行某些更改的方式上做了某些更改,或者我必须假定错误出现之前,并且它没有触发“无效日期”,因为我很幸运? (我主要使用函数来验证输入字段,所以它可能很容易被忽视)。

猜测我将不得不编写自己的日期脚本,完全忘记了js Date对象,它非常可怕(试图使用moment.js,但是在使用它的组件中的性能非常差,这就是为什么我必须自定义功能)。

编辑

为了更好的理解;

我在做什么,似乎工作:

Date.parse("23-7-2016") // Never got an error, expected 23 Jul 2016 

我跟踪验证错误之后发现了什么:

var startDate = Date.parse("23-7-2016"); 
console.log(startDate.toISOString()); //Got Invalid Date 

我觉得可能已经发生

var startDate = Date.parse("12-7-2016"); 
// expected 12 Jul 2016, got 7 Dec 2016, silently fails, everyone is happy 

为什么我认为上一个。情况并非如此:我使用交互式调度程序并对其执行了数千次测试,几乎不会忽略这样的错误。

最糟糕的情况:chrome更新并更改了它分析日期的方式。

不知道......希望有人能启发我。

+0

你可以给你提供这个功能值一些输入的例子吗?另外一个普遍的问题 - 为什么你要将日期转换为字符串,反之亦然?是因为你从某个外部来源得到日期字符串,还是你做了客户端 - 服务器通信? –

+0

我认为你应该使用pattern.test根据你的例子而不是pattern.exec –

+0

对不起,但是这个例子太广泛了。我为它所做的主要用途是一个事件调度程序,可以将其视为月历,一周时间表或每日时间表。例如,在周视图中,我必须循环周几,然后超过几个小时来勾选事件并稍后绘制它们。部分功能是添加事件,因此,当它迭代日期时,我必须将它们转换为可读的本地化字符串(我不会发布大量文本分析器),反之亦然。当点击一天时,它必须存储日期值......等等。 – sergio0983

我确定你的方法应该适用于任何有效的输入。你的问题是最有可能的是,你的正则表达式有效23小时以上,59分钟以上。

看到我的jsfiddle,枚举所有有效的输入。 https://jsfiddle.net/kLngLL72/4/

我没有覆盖我的例子中的Date.parse函数,以防止函数的无限嵌套。

Date.__parse = Date.parse; 

var dparse = function(string){ 
    var pattern = /^\d{1,2}:\d{1,2}/ig; 

    var today = new Date(); 

    if (pattern.exec(string)){ 
     var year = today.getFullYear(); 
     var month = today.getMonth()+1; 
     var day = today.getDate(); 

     var t = year+"-"+month+"-"+day+" "+string; 
     var timestamp = Date.__parse(t); 

     return new Date(timestamp); 
    } 
    else{ 
     return new Date(Date.__parse(string)); 
    } 
} 

$("#data").append("<tr><td>" + dparse("01-01-2016 1:31") + "</td></tr>"); 
$("#data").append("<tr><td>" + dparse("1-1-2016 0:0") + "</td></tr>"); 
$("#data").append("<tr><td>" + dparse("1-1-2016 12:59") + "</td></tr>"); 
$("#data").append("<tr><td>" + dparse("1-1-2016 23:59") + "</td></tr>"); 
$("#data").append("<tr><td>" + dparse("12-31-2016 1:1") + "</td></tr>"); 
$("#data").append("<tr><td>" + dparse("12-31-2016") + "</td></tr>"); 
$("#data").append("<tr><td>" + dparse("12-31-2016 24:0") + "</td></tr>"); 
$("#data").append("<tr><td>" + dparse("12-31-2016 99:99") + "</td></tr>"); 

for (var i = 0; i < 24; i++) 
{ 
    for (var j = 0; j < 60; j++) 
    { 
    $("#data").append("<tr><td>" + dparse("12-31-2016 " + i + ":" + j) + "</td></tr>"); 
    } 
} 

更新 - 新的JS FIDDLE https://jsfiddle.net/mfe55xun/2/ 这个新的例子,只传递小时和分钟的字符串。

Date.__parse = Date.parse; 

var dparse = function(string){ 
    var pattern = /^\d{1,2}:\d{1,2}/ig; 

    var today = new Date(); 

    if (pattern.exec(string)){ 
     var year = today.getFullYear(); 
     var month = today.getMonth()+1; 
     var day = today.getDate(); 

     var t = year+"-"+month+"-"+day+" "+string; 
     var timestamp = Date.__parse(t); 

     return new Date(timestamp); 
    } 
    else{ 
     return new Date(Date.__parse(string)); 
    } 
} 

$("#data").append("<tr><td>" + dparse("99:99") + "</td></tr>"); 

for (var i = 0; i < 24; i++) 
{ 
    for (var j = 0; j < 60; j++) 
    { 
    $("#data").append("<tr><td>" + dparse(i + ":" + j) + "</td></tr>"); 
    } 
} 

UPDATE

应当注意的是,如果您的输入字符串包括日期,定期Date.parse将与您的H字符串工作:M格式:

Date.parse("1/2/2016 4:3") 

你只需要将你的“4:3”附加到当前日期字符串,并且你可以删除你的自定义Date.parse函数。

另一个更新更新的问题

我不认为格式正确曾经工作过你。它有它会工作的情况,但它总是将“23日”的日期解释为一个月,并给你一个无效的日期。这里有另一个jsfiddle例子,循环所有可以设想的日期格式,注意只有1-12天工作。 https://jsfiddle.net/mfe55xun/6/

Date.__parse = Date.parse; 

var dparse = function(string){ 
    var pattern = /^\d{1,2}:\d{1,2}/ig; 

    var today = new Date(); 

    if (pattern.exec(string)){ 
     var year = today.getFullYear(); 
     var month = today.getMonth()+1; 
     var day = today.getDate(); 

     var t = year+"-"+month+"-"+day+" "+string; 
     var timestamp = Date.__parse(t); 

     return new Date(timestamp); 
    } 
    else{ 
     return new Date(Date.__parse(string)); 
    } 
} 

for (var i = 0; i <= 31; i++) 
{ 
    for (var j = 0; j <= 12; j++) 
    { 
    $("#data").append("<tr><td>" + i + "-" + j + "-2016 = " + dparse(i + "-" + j + "-2016") + "</td></tr>"); 
    } 
} 

看看效果循环:

test results 

0-0-2016 = Invalid Date 
0-1-2016 = Invalid Date 
0-2-2016 = Invalid Date 
0-3-2016 = Invalid Date 
0-4-2016 = Invalid Date 
0-5-2016 = Invalid Date 
0-6-2016 = Invalid Date 
0-7-2016 = Invalid Date 
0-8-2016 = Invalid Date 
0-9-2016 = Invalid Date 
0-10-2016 = Invalid Date 
0-11-2016 = Invalid Date 
0-12-2016 = Invalid Date 
1-0-2016 = Invalid Date 
1-1-2016 = Fri Jan 01 2016 00:00:00 GMT-0500 (Eastern Standard Time) 
1-2-2016 = Sat Jan 02 2016 00:00:00 GMT-0500 (Eastern Standard Time) 
1-3-2016 = Sun Jan 03 2016 00:00:00 GMT-0500 (Eastern Standard Time) 
1-4-2016 = Mon Jan 04 2016 00:00:00 GMT-0500 (Eastern Standard Time) 
1-5-2016 = Tue Jan 05 2016 00:00:00 GMT-0500 (Eastern Standard Time) 
1-6-2016 = Wed Jan 06 2016 00:00:00 GMT-0500 (Eastern Standard Time) 
1-7-2016 = Thu Jan 07 2016 00:00:00 GMT-0500 (Eastern Standard Time) 
1-8-2016 = Fri Jan 08 2016 00:00:00 GMT-0500 (Eastern Standard Time) 
1-9-2016 = Sat Jan 09 2016 00:00:00 GMT-0500 (Eastern Standard Time) 
1-10-2016 = Sun Jan 10 2016 00:00:00 GMT-0500 (Eastern Standard Time) 
1-11-2016 = Mon Jan 11 2016 00:00:00 GMT-0500 (Eastern Standard Time) 
1-12-2016 = Tue Jan 12 2016 00:00:00 GMT-0500 (Eastern Standard Time) 

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse

The Date.parse() method parses a string representation of a date, and returns the number of milliseconds since January 1, 1970, 00:00:00 UTC or NaN if the string is unrecognised or, in some cases, contains illegal date values (e.g. 2015-02-31).

It is not recommended to use Date.parse as until ES5, parsing of strings was entirely implementation dependent. There are still many differences in how different hosts parse date strings, therefore date strings should be manually parsed (a library can help if many different formats are to be accommodated).

+0

很好的例子,但我很确定小时/分钟不会引起问题。这些输入值来自下拉菜单,无法发送错误的值,显示的值来自迭代器,如您所写的。无论如何,我已经计划按照您的建议更改所有日期解析内容,更改Date对象是一个非常糟糕的主意。 – sergio0983