2016-07-22 158 views
2

我一直在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

回答

1

我確定你的方法應該適用於任何有效的輸入。你的問題是最有可能的是,你的正則表達式有效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