在 JavaScript 中檢測「無效日期」的 Date 實例
我想區分 JS 中有效和無效的日期物件,但找不到方法如下:
var d = new Date("foo");
console.log(d.toString()); // shows 'Invalid Date'
console.log(typeof d); // shows 'object'
console.log(d instanceof Date); // shows 'true'
有關編寫 isValidDate 函數的任何想法嗎?
- Ash 建議使用
Date.parse來解析日期字串,這提供了一種權威的方法來檢查日期字串是否有效。 - 如果可能的話,我比較希望我的 API 可以接受一個 Date 實例,並且能夠檢查或斷言它是否有效。Borgar 的解決方案可以做到這一點,但我需要在不同瀏覽器中測試它。我也想知道是否有更優雅的方法。
- Ash 讓我考慮是否完全不讓我的 API 接受
Date實例,這樣會最容易驗證。 - Borgar 建議先測試
Date實例,然後再測試Date的時間值。如果日期無效,時間值為NaN。我查過 ECMA-262,這種行為在標準中有規定,這正是我所尋找的。
答案#1
這就是我會做的方法:
if (Object.prototype.toString.call(d) === "[object Date]") {
// it is a date
if (isNaN(d)) { // d.getTime() or d.valueOf() will also work
// date object is not valid
} else {
// date object is valid
}
} else {
// not a date object
}
更新 [2018-05-31]:如果您不關心來自其他 JS 上下文(外部窗口、框架或 iframe)的 Date 對象,這種較簡單的形式可能更受青睞:
function isValidDate(d) {
return d instanceof Date && !isNaN(d);
}
更新 [2021-02-01]:請注意,「無效日期」(2013-13-32)與「無效的日期 對象」(new Date('foo'))之間有根本區別。本答案 不處理日期輸入的驗證,只涉及 Date 實例是否有效。
答案#2
你應該使用以下方式,而不是使用 new Date() :
var timestamp = Date.parse('foo');
if (isNaN(timestamp) == false) {
var d = new Date(timestamp);
}
Date.parse() 返回一個時間戳,整數表示自 1970 年 1 月 1 日以來的毫秒數。如果無法解析提供的日期字符串,則會返回 NaN。
答案#3
檢查有效日期的最短答案
if(!isNaN(date.getTime()))
答案#4
你可以透過 Date 物件 d 來檢查其有效性
d instanceof Date && isFinite(d)
為了避免跨框架問題,可以用以下方式取代 instanceof 檢查
Object.prototype.toString.call(d) === '[object Date]'
如 Borgar 的回答所示,調用 getTime() 是不必要的,因為 isNaN() 和 isFinite() 都會隱式轉換為數字。
答案#5
我的解決方案是用來簡單檢查你是否得到一個有效的日期物件:
實施
Date.prototype.isValid = function () {
// An invalid date object returns NaN for getTime() and NaN is the only
// object not strictly equal to itself.
return this.getTime() === this.getTime();
};
使用
var d = new Date("lol");
console.log(d.isValid()); // false
d = new Date("2012/09/11");
console.log(d.isValid()); // true
答案#6
在閱讀了到目前為止的每個答案之後,我將提供最簡單的答案。
這裡的每個解決方案都提到要調用 date.getTime()。不過,這其實不需要,因為從 Date 轉換為 Number 的默認方式就是使用 getTime() 的值。是的,你的類型檢查會抱怨。:) 而且發帖者顯然知道他們有一個 Date 對象,所以也不需要測試這個。
要測試一個無效的日期:
isNaN(date)
要測試一個有效的日期:
!isNaN(date)
或者(感謝 icc97 提供的這個替代方案)
isFinite(date)
或 TypeScript(感謝 pat-migliaccio)
isFinite(+date)
答案#7
我見過一些答案與這小片段非常接近。
JavaScript 方法:
function isValidDate(dateObject){
return new Date(dateObject).toString() !== 'Invalid Date';
}
console.log(isValidDate('WTH')); // -> false
console.log(isValidDate(new Date('WTH'))); // -> false
console.log(isValidDate(new Date())); // -> trueES2015 方式:
const isValidDate = dateObject => new Date(dateObject)
.toString() !== 'Invalid Date';
console.log(isValidDate('WTH')); // -> false
console.log(isValidDate(new Date('WTH'))); // -> false
console.log(isValidDate(new Date())); // -> true答案#8
你可以直接使用 moment.js
這裡是一個例子:
var m = moment('2015-11-32', 'YYYY-MM-DD');
m.isValid(); // false
文件中的驗證部分相當清楚。
而且,以下解析標誌會導致無效日期:
overflow:日期欄位的溢位,例如第 13 個月、每月第 32 天(或非閏年的 2 月 29 日)、第 367 天等。overflow 包含與 #invalidAt(見下文)相對應的無效單位索引;-1 表示沒有溢位。invalidMonth:無效的月份名稱,例如 moment('Marbruary', 'MMMM');。包含無效的月份字串本身,否則為 null。empty:一個不包含任何可解析內容的輸入字串,例如 moment('this is nonsense');。布林值。- 等等
來源:http://momentjs.com/docs/
答案#9
想提一下,jQuery UI DatePicker 小工具有一個非常好的日期驗證實用方法,可以檢查格式和有效性(例如,不允許使用 01/33/2013 這樣的日期)。
即使你不想將日期選擇器小工具作為頁面上的用戶界面元素使用,你仍然可以將其 .js 庫添加到頁面中,然後調用驗證方法,將你想驗證的值傳入其中。為了使操作更簡單,它接受的是字串作為輸入,而不是 JavaScript Date 對象。
請參見:http://api.jqueryui.com/datepicker/
它並沒有被列為一個方法,但它確實存在——作為一個工具函數。在頁面上搜尋「parsedate」你就會找到:
$.datepicker.parseDate( format, value, settings ) - 從具有指定格式的字串值中提取日期。
範例用法:
var stringval = '01/03/2012';
var testdate;
try {
testdate = $.datepicker.parseDate('mm/dd/yy', stringval);
// Notice 'yy' indicates a 4-digit year value
} catch (e)
{
alert(stringval + ' is not valid. Format must be MM/DD/YYYY ' +
'and the date value must be valid for the calendar.';
}
(更多關於指定日期格式的資訊可見於 http://api.jqueryui.com/datepicker/#utility-parseDate)
在上述例子中,你不會看到警示訊息,因為 '01/03/2012' 是指定格式中有效的日曆日期。然而,如果你將 'stringval' 設為 '13/04/2013',例如,你會看到警示訊息,因為值 '13/04/2013' 不是有效的日曆日期。
如果傳入的字串值被成功解析,'testdate' 的值將會是一個 Javascript Date 物件,表示傳入的字串值。如果解析不成功,它將是 undefined。
答案#10
// check whether date is valid
var t = new Date('2011-07-07T11:20:00.000+00:00x');
valid = !isNaN(t.valueOf());
答案#11
我真的很喜歡 Christoph 的方法(但名氣不夠大,無法投票支持)。對於我的使用情況,我知道我總會有一個 Date 物件,所以我只是給 date 擴充了一個 valid() 方法。
Date.prototype.valid = function() {
return isFinite(this);
}
現在我可以直接寫這個,這比在程式碼中僅檢查 isFinite 要描述得更清楚…
d = new Date(userDate);
if (d.valid()) { /* do stuff */ }
答案#12
我使用以下程式碼來驗證年份、月份和日期的值。
function createDate(year, month, _date) {
var d = new Date(year, month, _date);
if (d.getFullYear() != year
|| d.getMonth() != month
|| d.getDate() != _date) {
throw "invalid date";
}
return d;
}
詳情請參考 JavaScript 中的檢查日期
答案#13
你可以使用此腳本檢查 txDate.value 的有效格式。如果格式不正確,Date 物件將不會被實例化,並返回 null 給 dt。
var dt = new Date(txtDate.value)
if (isNaN(dt))
正如 @MiF 所建議的,簡而言之
if(isNaN(new Date(...)))
答案#14
為什麼在這麼多人嘗試過之後,我還要寫第48個答案?大多數答案部分正確,但並不適用於每種情況,而其他一些答案則不必要地冗長且複雜。下面是一個非常簡潔的解決方案。這將先檢查它是否為Date類型,然後檢查是否為有效的日期對象:
return x instanceof Date && !!x.getDate();
現在來解析日期文字:大多數解決方案使用 Date.parse() 或 "new Date()" -- 這兩者在某些情況下都會失敗,並且可能危險。JavaScript 可以解析各種格式,並且還依賴於本地化。例如,像 "1" 和 "blah-123" 這樣的字串也會被解析為有效日期。
然後有些貼文要麼使用大量程式碼,要麼使用長得像一英里長的正則表達式,要麼使用第三方框架。
這是一個非常簡單的方法來驗證日期字串。
function isDate(txt) {
var matches = txt.match(/^\d?\d\/(\d?\d)\/\d{4}$/); //Note: "Day" in the RegEx is parenthesized
return !!matches && !!Date.parse(txt) && new Date(txt).getDate()==matches[1];
}TEST THE FUNCTION
<br /><br />
<input id="dt" value = "12/21/2020">
<input type="button" value="validate" id="btnAction" onclick="document.getElementById('rslt').innerText = isDate(document.getElementById('dt').value)">
<br /><br />
Result: <span id="rslt"></span>isDate 的第一行使用簡單的正則表達式解析輸入文本,以驗證日期格式 mm/dd/yyyy 或 m/d/yyyy。對於其他格式,您需要相應地更改正則表達式,例如對於 dd-mm-yyyy,正則表達式變為 /^(\d?\d)-\d?\d-\d{4}$/
如果解析失敗,"matches" 為 null,否則它會存儲月份中的日期。第二行進一步測試以確保它是有效日期,並排除像 9/31/2021(JavaScript 允許的)這樣的情況。最後注意雙驚嘆號 (!!) 將 "falsy" 轉換為布林值 false。
答案#15
這裡已經有太多複雜的答案,但一行簡單的程式碼就足夠了(ES5):
Date.prototype.isValid = function (d) { return !isNaN(Date.parse(d)) } ;
甚至在 ES6 中:
Date.prototype.isValid = d => !isNaN(Date.parse(d));
答案#16
這對我剛好有效
new Date('foo') == 'Invalid Date'; //is true
然而這並沒有奏效
new Date('foo') === 'Invalid Date'; //is false
答案#17
當我嘗試驗證像 2/31/2012 這樣的日期時(在 Safari 6.0 中測試),這些答案都不適用,但在嘗試任何大於 31 的日期時,它們卻能正常工作。
所以我不得不稍微用點蛮力。假設日期的格式是 mm/dd/yyyy。我正在使用 @broox 的答案:
Date.prototype.valid = function() {
return isFinite(this);
}
function validStringDate(value){
var d = new Date(value);
return d.valid() && value.split('/')[0] == (d.getMonth()+1);
}
validStringDate("2/29/2012"); // true (leap year)
validStringDate("2/29/2013"); // false
validStringDate("2/30/2012"); // false
答案#18
對於 Angular.js 項目,你可以使用:
angular.isDate(myDate);
答案#19
我很少會推薦使用函式庫,尤其是在沒有必要的情況下。但考慮到目前大量的答案,似乎值得指出流行的函式庫「date-fns」有一個函數 isValid。以下文件摘自他們的官網:
| 有效的參數 | 在 v2.0.0 之前 | 從 v2.0.0 開始 |
|---|---|---|
| new Date() | 真 | 真 |
| new Date('2016-01-01') | 真 | 真 |
| new Date('') | 假 | 假 |
| new Date(1488370835081) | 真 | 真 |
| new Date(NaN) | 假 | 假 |
| '2016-01-01' | TypeError | 假 |
| '' | TypeError | 假 |
| 1488370835081 | TypeError | 真 |
| 非數值 | TypeError | 假 |
