Phát hiện một ngày không hợp lệ của phiên bản Ngày tháng ngày trong JavaScript


1494

Tôi muốn nói sự khác biệt giữa các đối tượng ngày hợp lệ và không hợp lệ trong JS, nhưng không thể tìm ra cách:

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'

Bất kỳ ý tưởng để viết một isValidDatechức năng?

  • Ash khuyên Date.parsedùng để phân tích chuỗi ngày, đưa ra một cách có thẩm quyền để kiểm tra xem chuỗi ngày có hợp lệ không.
  • Điều tôi muốn, nếu có thể, là để API của tôi chấp nhận một thể hiện Ngày và để có thể kiểm tra / xác nhận xem nó có hợp lệ hay không. Giải pháp của Borgar thực hiện điều đó, nhưng tôi cần kiểm tra nó trên các trình duyệt. Tôi cũng tự hỏi liệu có một cách thanh lịch hơn.
  • Ash khiến tôi cân nhắc việc không có API chấp nhận các Datetrường hợp nào cả, điều này sẽ dễ xác thực nhất.
  • Borgar đề nghị thử nghiệm một Dateví dụ, và sau đó thử nghiệm Dategiá trị thời gian của. Nếu ngày không hợp lệ, giá trị thời gian là NaN. Tôi đã kiểm tra với ECMA-262 và hành vi này là trong tiêu chuẩn, đó chính xác là những gì tôi đang tìm kiếm.

18
Bạn có thể xóa câu lệnh if bằng cách thay đổi phần thân của hàm thành:return ( Object.prototype.toString.call(d) === "[object Date]" && !isNaN(d.getTime()) );
styfle

3
@styfle - đoán đó là một sở thích về phong cách: Tôi thấy rõ ràng hơn khi tách kiểm tra loại khỏi logic bằng.
orip

26
diễn ngôn @orip chính xác là những gì được khuyến khích nặng nề trong các câu hỏi. Vui lòng tham khảo các chủ đề meta có liên quan để tìm hiểu lý do đằng sau nó. Đặt một câu trả lời cho câu hỏi của riêng mình trong chính câu hỏi là trái với chính sách của trang web. OTOH, cảm ơn bạn đã trả lời và có "EDIT" trong câu trả lời của bạn là điển hình. Nếu bạn muốn bạn đặt câu hỏi hàng đầu để xác định bạn là một người không biết SO là gì và sử dụng nó như thế nào và không muốn tìm hiểu điều đó - hãy là khách của tôi.

14
@orip: Nó không "mất"; nó vẫn còn làm xáo trộn lịch sử sửa đổi của câu hỏi nếu bạn muốn gặp lại nó. Nhưng nó không thuộc về một câu hỏi. Ở đại diện 37k bạn nên biết điều này.
Các cuộc đua nhẹ nhàng trong quỹ đạo

6
Vui lòng dừng cuộc chiến chỉnh sửa. Các chỉnh sửa về câu hỏi này được thảo luận trên meta . Xin vui lòng không chỉnh sửa / rollback bài này hơn nữa. Nếu bạn không đồng ý với các chỉnh sửa / rollback trước đó hoặc có bất kỳ nhận xét nào liên quan đến chúng, vui lòng đăng lên chủ đề meta đó chứ không phải ở đây.
Lundin

Câu trả lời:


1303

Đây là cách tôi sẽ làm điều đó:

if (Object.prototype.toString.call(d) === "[object Date]") {
  // it is a date
  if (isNaN(d.getTime())) {  // d.valueOf() could also work
    // date is not valid
  } else {
    // date is valid
  }
} else {
  // not a date
}

Cập nhật [2018-05-31] : Nếu bạn không quan tâm đến các đối tượng Date từ các bối cảnh JS khác (cửa sổ bên ngoài, khung hoặc iframe), hình thức đơn giản hơn này có thể được ưa thích:

function isValidDate(d) {
  return d instanceof Date && !isNaN(d);
}

21
thể hiện phá vỡ trên các khung. Gõ vịt cũng có thể hoạt động tốt: validDate == d && d.getTime &&! IsNaN (d.getTime ()); - Vì câu hỏi dành cho một chức năng tiện ích chung, tôi thích nghiêm ngặt hơn.
Borgar

11
@Borgar, vừa tìm thấy câu trả lời của tôi: "Các vấn đề phát sinh khi nói đến kịch bản trong môi trường DOM đa khung. Tóm lại, các đối tượng Array được tạo trong một iframe không chia sẻ [[Prototype]] với các mảng được tạo trong một iframe khác Các hàm tạo của chúng là các đối tượng khác nhau và do đó cả kiểm tra thể hiện và hàm tạo đều thất bại. "
Tro

64
bạn thậm chí không cần d.getTimechỉisNan(d)
TecHunter

8
Có thể được đơn giản hóa như thế này:d instanceof Date && !isNaN(d.getTime())
Zorgatone

5
Cảm ơn câu trả lời, nhưng tôi muốn nhấn mạnh ý kiến ​​của @Borgar và @blueprintChris: nếu tôi phân tích chữ số 1chẳng hạn, tôi vẫn sẽ có một ngày hợp lệ dẫn đến Mon Jan 01 2001 00:00:00đó thực sự là một ngày, tuy nhiên với mục đích ứng dụng của tôi thì nó hoàn toàn vô dụng . Vì vậy, ít nhất có một số xác nhận đầu vào cần thiết trong trường hợp của tôi. Câu trả lời này xác nhận dateObjectkhông a Date!
dnhyde

264

Thay vì sử dụng, new Date()bạn nên sử dụng:

var timestamp = Date.parse('foo');

if (isNaN(timestamp) == false) {
  var d = new Date(timestamp);
}

Date.parse()trả về dấu thời gian, một số nguyên biểu thị số mili giây kể từ ngày 01/1/1970. Nó sẽ trả về NaNnếu không thể phân tích chuỗi ngày được cung cấp.


119
-1 Dunno tại sao điều này có quá nhiều phiếu bầu, Date.parsephụ thuộc vào việc triển khai và chắc chắn không được tin tưởng để phân tích chuỗi ngày chung. Không có định dạng duy nhất được phân tích cú pháp chính xác trong các trình duyệt phổ biến, ít hơn tất cả những định dạng đang sử dụng (mặc dù cuối cùng định dạng ISO8601 được chỉ định trong ES5 sẽ ổn).
RobG

1
Nếu bạn sử dụng new Date('foo')cơ bản tương đương với Date.parse('foo')phương pháp. Xem: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/NH Vì vậy, những gì @RobG đã nói, nó cũng áp dụng cho nó.
golddragon007

2
Thử nghiệm này sẽ thất bại trong Chrome. Ví dụ: Date.parse ('AAA-0001') trong Chrome cung cấp cho tôi một số.
Nick

không thành công ... phát hiện tất cả các giá trị số
Hos Mercury

109

Bạn có thể kiểm tra tính hợp lệ của một Dateđối tượng dthông qua

d instanceof Date && isFinite(d)

Để tránh các vấn đề khung chéo, người ta có thể thay thế instanceofkiểm tra bằng

Object.prototype.toString.call(d) === '[object Date]'

Một cuộc gọi đến getTime()như trong câu trả lời của Borgar là không cần thiết isNaN()isFinite()cả hai đều chuyển đổi thành số.


Hãy thử điều này trong chrome - Object.prototype.toString.call (Ngày mới ("2013-07-09T19: 07: 9Z")). Nó sẽ trả về "[ngày đối tượng]". Theo bạn, do đó, "2013-07-09T19: 07: 9Z", phải là một ngày hợp lệ. Nhưng nó không phải như vậy. Bạn có thể xác minh nó, một lần nữa bằng chrome, bằng cách thực hiện var dateStr = new Date ("2013-07-09T19: 07: 9Z"); dateStr Nó sẽ trả về ngày không hợp lệ.
Tintin

2
@Tintin: đó là những gì isFinite()dành cho - toString.call()chỉ là sự thay thế cho instanceofmột phần của tấm séc
Christoph

Sẽ so sánh với '[ngày đối tượng]' hoạt động với các trình duyệt không phải tiếng Anh? Tôi nghi ngờ điều đó.
kristianp

2
@kristianp thực sự nó có thể sẽ và thậm chí có thể là một phần của thông số ECMAScript. Nhưng, vâng, nó có vẻ xấu.
b Liệu

Đối với tôi cách tiếp cận đầu tiên ở đây là lựa chọn tốt nhất, mặc dù tôi không chắc chắn nếu có bất kỳ lợi thế thực tế của việc sử dụng isFinitehơn isNaN(cả hai đều chỉ làm việc tốt với Date(Infinity)). Hơn nữa, nếu bạn muốn điều kiện ngược lại, nó sẽ đơn giản hơn một chút : if (!(date instanceof Date) || isNaN(date)).
Andrew

86

Giải pháp của tôi chỉ đơn giản là kiểm tra xem bạn có nhận được một đối tượng ngày hợp lệ hay không:

Thực hiện

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();
};  

Sử dụng

var d = new Date("lol");

console.log(d.isValid()); // false

d = new Date("2012/09/11");

console.log(d.isValid()); // true

28
isNaNlà một cách rõ ràng hơn để kiểm tra NaN
orip

1
Chưa hết, bạn luôn thấy mọi người viết các phiên bản của riêng họ :) documentcloud.github.com/underscore/docs/iêu
Ash Clarke

4
vì tôi tôn trọng underscore.js, điều này đã thúc đẩy một số nghiên cứu. isNaN("a") === true, trong khi ("a" !== "a") === false. Thật đáng để suy nghĩ. +1
orip

8
Tôi đã thử nghiệm hiệu suất cho 3 giải pháp chính tôi đã tìm thấy ở đây. Xin chúc mừng, bạn là người chiến thắng! jsperf.com/detecting-an-invalid-date
zVictor

2
@Ali Đó là một đối tượng ngày hợp lệ. new Date("02-31-2000") // Thu Mar 02 2000 00:00:00 GMT+0000 (GMT Standard Time). Nếu bạn chuyển một chuỗi đến hàm tạo ngày, bạn phải chuyển trong một chuỗi được tiêu chuẩn hóa để có kết quả đáng tin cậy. Cụ thể, "Chuỗi phải ở định dạng được nhận dạng bởi phương thức Date.parse ()". developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/,
Ash Clarke

71

câu trả lời ngắn nhất để kiểm tra ngày hợp lệ

if(!isNaN(date.getTime()))

2
Vấn đề duy nhất là nếu ngày không thuộc loại Ngày; bạn gặp lỗi JS.
Andrew

@Andrew bạn cần tạo Đối tượng ngày và nếu bạn đã có một đối tượng thì hãy sử dụngdate && !isNaN(date.getTime())
abhirathore2006

Điều đó vẫn cung cấp cho bạn một lỗi JS nếu datekhông thuộc loại Ngày. Ví dụ : var date = 4; date && !isNaN(date.getTime());.
Andrew

date instanceof Date && !isNaN(date.getTime())
@Andrew

3
Phải, giống như các câu trả lời khác từ 8 năm trước. : P stackoverflow.com/a/1353945/2321042
Andrew

45

Bạn chỉ có thể sử dụng khoảnh khắc

Đây là một ví dụ:

var m = moment('2015-11-32', 'YYYY-MM-DD');
m.isValid(); // false

Phần xác nhận trong tài liệu khá rõ ràng.

Ngoài ra, các cờ phân tích sau đây dẫn đến một ngày không hợp lệ:

  • overflow: Tràn của trường ngày, chẳng hạn như tháng thứ 13, ngày thứ 32 của tháng (hoặc ngày 29 tháng 2 vào các năm không nhảy vọt), ngày thứ 367 của năm, v.v. để khớp với #invalidAt (xem bên dưới); -1 có nghĩa là không tràn.
  • invalidMonth: Tên tháng không hợp lệ, chẳng hạn như khoảnh khắc ('Marbremony', 'MMMM');. Chứa chính chuỗi tháng không hợp lệ hoặc không.
  • empty: Chuỗi đầu vào không chứa gì có thể phân tích cú pháp, chẳng hạn như khoảnh khắc ('điều này là vô nghĩa');. Boolean.
  • Vân vân.

Nguồn: http://momentjs.com/docs/


6
Giải pháp tốt nhất, cực kỳ dễ thực hiện, hoạt động với mọi định dạng (trường hợp của tôi là dd / MM / yyyy), cũng biết năm nhuận và không chuyển đổi ngày không hợp lệ (ví dụ: 29/02/2015) thành ngày hợp lệ (nghĩa là 30/03/2015). Để kiểm tra một ngày trong formad dd / MM / yyyy tôi vừa phải sử dụngmoment("11/06/1986", "DD/MM/YYYY").isValid();
Rafael Merlin

3
Việc sử dụng Khoảnh khắc này đã không được chấp nhận :(
James Sumners

2
Việc sử dụng này đã không được khấu hao. Thời điểm gọi (đầu vào) không có chuỗi định dạng sẽ bị khấu hao (trừ khi đầu vào được định dạng ISO).
Chet

2
Phương pháp này có thể cực kỳ chậm khi xử lý nhiều ngày. Tốt hơn để sử dụng một regex trong những trường hợp.
Lưới Trekkor

2
Việc sử dụng khoảnh khắc.js có thể đơn giản, nhưng là một chi phí rất lớn. Thư viện này là LỚN. Tôi đánh giá thấp câu trả lời của bạn.
Mick

38

Muốn đề cập rằng tiện ích DatePicker của UI UI có một phương thức tiện ích trình xác thực ngày rất tốt để kiểm tra định dạng và tính hợp lệ (ví dụ: không cho phép ngày 01 tháng 3 năm 2013).

Ngay cả khi bạn không muốn sử dụng tiện ích hẹn hò trên trang của mình làm thành phần UI, bạn luôn có thể thêm thư viện .js của nó vào trang của mình và sau đó gọi phương thức trình xác thực, chuyển giá trị bạn muốn xác thực vào nó. Để làm cho cuộc sống dễ dàng hơn nữa, phải lấy một chuỗi làm đầu vào, không phải là đối tượng Ngày JavaScript.

Xem: http://api.jqueryui.com/datepicker/

Nó không được liệt kê như một phương thức, nhưng nó ở đó - như là một hàm tiện ích. Tìm kiếm trang "phân tích cú pháp" và bạn sẽ tìm thấy:

$ .datepicker.parseDate (định dạng, giá trị, cài đặt) - Trích xuất một ngày từ một giá trị chuỗi với định dạng được chỉ định.

Ví dụ sử dụng:

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.';
}

(Thông tin thêm xác định lại định dạng ngày được tìm thấy tại http://api.jqueryui.com/datepicker/#utility-parseDate )

Trong ví dụ trên, bạn sẽ không thấy thông báo cảnh báo vì '01 / 03/2012 'là ngày hợp lệ theo lịch ở định dạng đã chỉ định. Tuy nhiên, nếu bạn đã tạo 'chuỗi giá trị' bằng '13 / 04/2013 ', chẳng hạn, bạn sẽ nhận được thông báo cảnh báo, vì giá trị '13 / 04/2013' không hợp lệ theo lịch.

Nếu một giá trị chuỗi được truyền vào được phân tích thành công, giá trị của 'testdate' sẽ là một đối tượng Ngày Javascript biểu thị giá trị chuỗi được truyền vào. Nếu không, nó sẽ không được xác định.


3
Upvote là câu trả lời đầu tiên làm việc với các định dạng ngày không phải tiếng Anh / ngôn ngữ.
rìu.

26

Tôi thực sự thích cách tiếp cận của Christoph (nhưng không có đủ danh tiếng để bỏ phiếu). Để sử dụng, tôi biết tôi sẽ luôn có một đối tượng Date vì vậy tôi chỉ mở rộng ngày với phương thức hợp lệ ().

Date.prototype.valid = function() {
  return isFinite(this);
}

Bây giờ tôi chỉ có thể viết cái này và nó mô tả nhiều hơn là chỉ kiểm tra isFinite trong mã ...

d = new Date(userDate);
if (d.valid()) { /* do stuff */ }

10
Mở rộng nguyên mẫu? Đó là một JavaScript lớn không không!
Jasdeep Khalsa

Nâng cao vì isFinitelàm việc cho tôi hoàn hảo. Nhưng có, vô nghĩa để mở rộng nguyên mẫu. !isFinitetrên một Datesẽ bắt thực tế DateInvalid Date. Cũng đáng chú ý bối cảnh của tôi là trong Node.
Staghouse

23
// check whether date is valid
var t = new Date('2011-07-07T11:20:00.000+00:00x');
valid = !isNaN(t.valueOf());

5
Nó giống như @Borgar đã viết cách đây 2 năm ... Có gì mới ??
xanh

11
Đó là hai dòng thay vì lồng nhau xấu xí nếu câu lệnh.
Cypher

17

bạn có thể kiểm tra định dạng hợp lệ của txDate.value với scirpt này. nếu nó ở định dạng không chính xác, ngày obejct không được kích hoạt và trả về null cho dt.

 var dt = new Date(txtDate.value)
 if (isNaN(dt))

Và như @ MiF đề xuất theo cách ngắn gọn

 if(isNaN(new Date(...)))

isNaN (Ngày mới (...)) - phương pháp đơn giản và ngắn gọn
MiF

1
@MiF vâng, tôi cập nhật câu trả lời của tôi với đề xuất của bạn;) cảm ơn
Yuseferi

16

Tôi sử dụng mã sau đây để xác thực các giá trị cho năm, tháng và ngày.

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;
}

Để biết chi tiết, tham khảo Kiểm tra ngày trong javascript


strkhông được sử dụng.
samis

12

Quá nhiều câu trả lời phức tạp ở đây đã có, nhưng một dòng đơn giản là đủ (ES5):

Date.prototype.isValid = function (d) { return !isNaN(Date.parse(d)) } ;

hoặc thậm chí trong ES6:

Date.prototype.isValid = d => !isNaN(Date.parse(d));

1
Từ MDN: "Phương thức Date.parse () phân tích cú pháp chuỗi đại diện của một ngày và trả về số mili giây kể từ ngày 1 tháng 1 năm 1970, 00:00:00 UTC hoặc NaN ..." Vì vậy, hãy chạy một ngày tiềm năng thông qua điều này hàm trả về một số nguyên hoặc NaN. Sau đó, hàm isNaN () sẽ cung cấp một boolean sạch cho bạn biết giá trị ban đầu có phải là một đối tượng ngày hợp lệ hay không. Điều này là đủ để thực hiện kiểm tra tại chỗ, nhưng ví dụ trên sau đó gắn phương thức này vào đối tượng Date để làm cho chức năng có sẵn dễ dàng và có thể đọc được trong suốt chương trình của bạn.
Max Wilder

nếu d là boolean, bạn sẽ nhận được 0 hoặc 1 mà không phải là Nan !!
davcup

@davcup vừa thử nghiệm bằng cách sử dụng Date.parse(true), tôi nhận được một NaN chính xác.
Sebastien H.

12

Tôi thấy một số câu trả lời thực sự gần với đoạn trích nhỏ này.

Cách JavaScript:

function isValidDate(dateObject){ return new Date(dateObject).toString() !== 'Invalid Date'; }
isValidDate(new Date('WTH'));

Cách TypeScript:

const isValidDate = dateObject => new Date(dateObject ).toString() !== 'Invalid Date';
isValidDate(new Date('WTH'));

1
Không chắc chắn nếu tôi thiếu thứ gì đó nhưng không thực hiện Ngày mới () hai lần vô nghĩa?
Jon Catmull

2
Cái sau không có gì để làm với TypeScript. Nó là hoàn toàn hợp lệ JS.
hackel

9

Giải pháp tốt đẹp! Bao gồm trong thư viện các chức năng phụ trợ của tôi, bây giờ nó trông như thế này:

Object.isDate = function(obj) {
/// <summary>
/// Determines if the passed object is an instance of Date.
/// </summary>
/// <param name="obj">The object to test.</param>

    return Object.prototype.toString.call(obj) === '[object Date]';
}

Object.isValidDate = function(obj) {
/// <summary>
/// Determines if the passed object is a Date object, containing an actual date.
/// </summary>
/// <param name="obj">The object to test.</param>

    return Object.isDate(obj) && !isNaN(obj.getTime());
}

9

Điều này chỉ làm việc cho tôi

new Date('foo') == 'Invalid Date'; //is true

Tuy nhiên điều này đã không làm việc

new Date('foo') === 'Invalid Date'; //is false

5
Tôi tin rằng đây là phụ thuộc vào trình duyệt.
barrypicker

@barrypicker Ý bạn là gì phụ thuộc vào trình duyệt?
Ajil O.

Bạn có thể làm: `${new Date('foo')}` === 'Invalid Date'
Daniele Vrut

9

Đối với các dự án Angular.js bạn có thể sử dụng:

angular.isDate(myDate);

3
Điều này trả về đúng khi kiểm tra một đối tượng ngày đã được khởi tạo với Ngày không hợp lệ.
dchhetri

6

Không có câu trả lời nào trong số này làm việc cho tôi (được thử nghiệm trong Safari 6.0) khi cố gắng xác thực một ngày như ngày 31/2/2012, tuy nhiên, chúng hoạt động tốt khi thử bất kỳ ngày nào lớn hơn 31.

Vì vậy, tôi đã phải vũ phu một chút. Giả sử ngày tháng ở định dạng mm/dd/yyyy. Tôi đang sử dụng câu trả lời @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

(Ngày mới ('2/30/2014')). hợp lệ () trả về đúng
Andre Figueiredo

1
Đã được một thời gian kể từ khi tôi trả lời nhưng bạn có thể cần cả hai điều kiện hoàn trả, bao gồm&& value.split('/')[0] == (d.getMonth()+1);
Dex

Việc sử dụng new Date('string date')tương đương với Date.parse('string date'), xem: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/, để bạn có thể nhận được các giá trị sai hoặc sai.
golddragon007

5

Không có giải pháp nào ở trên làm việc cho tôi, tuy nhiên, công việc là gì

function validDate (d) {
        var date = new Date(d);
        var day = ""+date.getDate();
        if( day.length == 1)day = "0"+day;
        var month = "" +( date.getMonth() + 1);
        if( month.length == 1)month = "0"+month;
        var year = "" + date.getFullYear();

        return ((month + "/" + day + "/" + year) == d);
    }

đoạn mã trên sẽ thấy khi JS thực hiện ngày 31/2/2012 thành ngày 03/02/2012.


3
Ok, nhưng điều này kiểm tra nếu một chuỗi là một ngày ở định dạng M / D / Y, không phải là "sự khác biệt giữa các đối tượng ngày hợp lệ và không hợp lệ". Nó không thực sự là những gì câu hỏi về.
Borgar

lý do tại sao nó được kiểm tra theo định dạng là để kiểm tra xem ngày đã thay đổi sau khi được phân tích cú pháp chưa
John

Không phải OP yêu cầu một phương thức trả về Boolean, không phải là một chuỗi được định dạng?
barrypicker

1
Mã mẫu không trả về boolean, việc định dạng đóng một phần trong kiểm tra một số trường hợp không hợp lệ.
John

5
IsValidDate: function(date) {
        var regex = /\d{1,2}\/\d{1,2}\/\d{4}/;
        if (!regex.test(date)) return false;
        var day = Number(date.split("/")[1]);
        date = new Date(date);
        if (date && date.getDate() != day) return false;
        return true;
}

4

Tôi đã viết chức năng này. Truyền cho nó một tham số chuỗi và nó sẽ xác định xem đó có phải là ngày hợp lệ hay không dựa trên định dạng này "dd / MM / yyyy".

đây là một bài kiểm tra

đầu vào: "hahaha", đầu ra: sai.

đầu vào: "29/2/2000", đầu ra: đúng.

đầu vào: "29/2/2001", đầu ra: sai.

function isValidDate(str) {
    var parts = str.split('/');
    if (parts.length < 3)
        return false;
    else {
        var day = parseInt(parts[0]);
        var month = parseInt(parts[1]);
        var year = parseInt(parts[2]);
        if (isNaN(day) || isNaN(month) || isNaN(year)) {
            return false;
        }
        if (day < 1 || year < 1)
            return false;
        if(month>12||month<1)
            return false;
        if ((month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) && day > 31)
            return false;
        if ((month == 4 || month == 6 || month == 9 || month == 11 ) && day > 30)
            return false;
        if (month == 2) {
            if (((year % 4) == 0 && (year % 100) != 0) || ((year % 400) == 0 && (year % 100) == 0)) {
                if (day > 29)
                    return false;
            } else {
                if (day > 28)
                    return false;
            }      
        }
        return true;
    }
}

4

Date.prototype.toISOStringném RangeError(ít nhất là trong Chromium và Firefox) vào những ngày không hợp lệ. Bạn có thể sử dụng nó như một phương tiện xác nhận và có thể không cần isValidDatenhư vậy (EAFP). Nếu không thì đó là:

function isValidDate(d)
{
  try
  {
    d.toISOString();
    return true;
  }
  catch(ex)
  {
    return false;    
  }    
}

1
Có vẻ như đây là chức năng duy nhất đưa ra lỗi theo định nghĩa ECMA-262. 15.9.5.43 Date.prototype.toISOString () Hàm này trả về giá trị Chuỗi đại diện cho thể hiện trong thời gian được đại diện bởi đối tượng Date này. Định dạng của Chuỗi là định dạng chuỗi Ngày Thời gian được xác định trong 15.9.1.15. Tất cả các trường có mặt trong Chuỗi. Múi giờ luôn là UTC, ký hiệu là hậu tố Z. Nếu giá trị thời gian của đối tượng này không phải là Số hữu hạn, một ngoại lệ RangeError được ném.
Henry Liu

3

Lấy cảm hứng từ cách tiếp cận của Borgar Tôi đã đảm bảo rằng mã không chỉ xác nhận ngày mà còn thực sự đảm bảo ngày đó là ngày thực, có nghĩa là các ngày như 31/09/2011 và 29/02/2011 không được phép.

function(dateStr) {
    s = dateStr.split('/');
    d = new Date(+s[2], s[1]-1, +s[0]);
    if (Object.prototype.toString.call(d) === "[object Date]") {
        if (!isNaN(d.getTime()) && d.getDate() == s[0] && 
            d.getMonth() == (s[1] - 1)) {
            return true;
        }
    }
    return "Invalid date!";
}

Nhưng ... các phương pháp ở trên (@ Borgar's và các phương pháp khác) đã kiểm tra loại hợp lệ này ... Tôi không thể hiểu được vấn đề.
xanh

Của Borgar không - xem bình luận của riêng mình cho câu trả lời của mình.
EML

1
Giải pháp này chỉ hoạt động khi quốc gia của bạn sử dụng dd/MM/yyyyký hiệu. Ngoài ra, nó trả về truekhi nó hợp lệ và 'Invalid date!'nếu không, tốt hơn là chỉ trả về 1 loại.
A1rPun

3

Tôi đã kết hợp các kết quả hoạt động tốt nhất mà tôi tìm thấy xung quanh việc kiểm tra nếu một đối tượng nhất định:

Kết quả là như sau:

function isValidDate(input) {
  if(!(input && input.getTimezoneOffset && input.setUTCFullYear))
    return false;

  var time = input.getTime();
  return time === time;
};

2

Đối tượng ngày thành chuỗi là cách đơn giản và đáng tin cậy hơn để phát hiện nếu cả hai trường là ngày hợp lệ. ví dụ: Nếu bạn nhập "-------" này vào trường nhập ngày. Một số câu trả lời ở trên sẽ không hoạt động.

jQuery.validator.addMethod("greaterThan", 

    function(value, element, params) {
        var startDate = new Date($(params).val());
        var endDate = new Date(value);

        if(startDate.toString() === 'Invalid Date' || endDate.toString() === 'Invalid Date') {
            return false;
        } else {
            return endDate > startDate;
        }
    },'Must be greater than {0}.');

2

Câu trả lời được chọn là tuyệt vời và tôi cũng đang sử dụng nó. Tuy nhiên, nếu bạn đang tìm cách xác thực đầu vào ngày của người dùng, bạn nên lưu ý rằng đối tượng Date rất kiên trì về việc biến những gì có vẻ là đối số xây dựng không hợp lệ thành đối số hợp lệ. Mã kiểm tra đơn vị sau đây minh họa điểm:

QUnit.test( "valid date test", function( assert ) {
  //The following are counter-examples showing how the Date object will 
  //wrangle several 'bad' dates into a valid date anyway
  assert.equal(isValidDate(new Date(1980, 12, 15)), true);
  d = new Date();
  d.setFullYear(1980);
  d.setMonth(1);
  d.setDate(33);
  assert.equal(isValidDate(d), true);
  assert.equal(isValidDate(new Date(1980, 100, 150)), true);
  //If you go to this exterme, then the checker will fail
  assert.equal(isValidDate(new Date("This is junk")), false);
  //This is a valid date string
  assert.equal(isValidDate(new Date("November 17, 1989")), true);
  //but is this?
  assert.equal(isValidDate(new Date("November 35, 1989")), false);  
  //Ha!  It's not.  So, the secret to working with this version of 
  //isValidDate is to pass in dates as text strings... Hooboy
  //alert(d.toString());
});

2
function isValidDate(strDate) {
    var myDateStr= new Date(strDate);
    if( ! isNaN ( myDateStr.getMonth() ) ) {
       return true;
    }
    return false;
}

Gọi nó như thế này

isValidDate(""2015/5/2""); // => true
isValidDate(""2015/5/2a""); // => false

2

Một chức năng sẵn sàng dựa trên câu trả lời được xếp hạng hàng đầu:

  /**
   * Check if date exists and is valid.
   *
   * @param {String} dateString Date in YYYY-mm-dd format.
   */
  function isValidDate(dateString) {
  var isValid = false;
  var date;

  date =
    new Date(
      dateString);

  if (
    Object.prototype.toString.call(
      date) === "[object Date]") {

    if (isNaN(date.getTime())) {

      // Date is unreal.

    } else {
      // Date is real if month and day match each other in date and string (otherwise may be shifted):
      isValid =
        date.getUTCMonth() + 1 === dateString.split("-")[1] * 1 &&
        date.getUTCDate() === dateString.split("-")[2] * 1;
    }
  } else {
    // It's not a date.
  }

  return isValid;
}

2

Giải pháp đơn giản và thanh lịch:

const date = new Date(`${year}-${month}-${day} 00:00`)
const isValidDate = (Boolean(+date) && date.getDate() == day)

nguồn:

[1] https://medium.com/@esganzerla/simple-date-validation-with-javascript-caea0f71883c

[2] Ngày không chính xác được hiển thị trong Ngày mới () trong JavaScript


1
date.getDate() == daykhông đủ để xác định xem ngày có hợp lệ không. Định dạng ngày ban đầu sẽ trả về một ngày không hợp lệ trong một số triển khai bất kể ngày đó có hợp lệ hay không. Ngoài ra "1970-01-01 00:00" nếu được phân tích cú pháp chính xác sẽ trả về false (tức là Boolean(+new Date("1970-01-01"))trả về false).
RobG

CẢNH BÁO: Điều này sẽ không hoạt động trong Safari
Vigrant

Nó sẽ hoạt động trong Safari nếu bạn sử dụng định dạng const date = new Date(year, month, day); Lưu ý rằng tháng đó được lập chỉ mục 0 theo cách này để bạn có thể phải trừ đi một thứ để sắp xếp chính xác.
Vigrant

1

Tôi nghĩ rằng một số điều này là một quá trình lâu dài. Chúng ta có thể cắt nó ngắn như hình dưới đây:

 function isValidDate(dateString) {
        debugger;
        var dateStringSplit;
        var formatDate;

        if (dateString.length >= 8 && dateString.length<=10) {
            try {
                dateStringSplit = dateString.split('/');
                var date = new Date();
                date.setYear(parseInt(dateStringSplit[2]), 10);
                date.setMonth(parseInt(dateStringSplit[0], 10) - 1);
                date.setDate(parseInt(dateStringSplit[1], 10));

                if (date.getYear() == parseInt(dateStringSplit[2],10) && date.getMonth()+1 == parseInt(dateStringSplit[0],10) && date.getDate() == parseInt(dateStringSplit[1],10)) {
                    return true;
                }
                else {
                    return false;
                }

            } catch (e) {
                return false;
            }
        }
        return false;
    }

3
Câu hỏi được hỏi về cách tìm phiên bản Ngày không hợp lệ, không phải chuỗi và bên cạnh đó: ai nói ngày không thể được phân định bởi một thứ khác ngoài dấu gạch chéo?
Jon z

1

Đối với các thành phần dựa trên int 1 của một ngày:

var is_valid_date = function(year, month, day) {
    var d = new Date(year, month - 1, day);
    return d.getFullYear() === year && (d.getMonth() + 1) === month && d.getDate() === day
};

Các xét nghiệm:

    is_valid_date(2013, 02, 28)
&&  is_valid_date(2016, 02, 29)
&& !is_valid_date(2013, 02, 29)
&& !is_valid_date(0000, 00, 00)
&& !is_valid_date(2013, 14, 01)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.