การตรวจสอบอินสแตนซ์วันที่“ ไม่ถูกต้อง” ใน JavaScript


1493

ฉันต้องการบอกความแตกต่างระหว่างวัตถุวันที่ที่ถูกต้องและไม่ถูกต้องใน 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 ของฉันยอมรับอินสแตนซ์วันที่และเพื่อให้สามารถตรวจสอบ / ยืนยันว่ามันถูกต้องหรือไม่ โซลูชันของ Borgar ทำเช่นนั้น แต่ฉันต้องการทดสอบในเบราว์เซอร์ ฉันยังสงสัยว่ามีวิธีที่สง่างามกว่านี้หรือไม่
  • Ash ทำให้ฉันพิจารณาว่าไม่ให้ API ของฉันยอมรับDateอินสแตนซ์เลยนี่เป็นการตรวจสอบที่ง่ายที่สุด
  • Borgar แนะนำการทดสอบสำหรับDateอินสแตนซ์แล้วทดสอบDateค่าเวลาของ NaNถ้าวันที่ไม่ถูกต้องคุ้มค่าเวลาที่ ฉันตรวจสอบกับECMA-262และพฤติกรรมนี้อยู่ในมาตรฐานซึ่งเป็นสิ่งที่ฉันกำลังมองหา

18
คุณสามารถลบคำสั่ง if โดยการเปลี่ยนเนื้อหาของฟังก์ชั่นเป็น:return ( Object.prototype.toString.call(d) === "[object Date]" && !isNaN(d.getTime()) );
styfle

3
@styfle - เดาว่ามันเป็นสไตล์ที่ชอบ: ฉันคิดว่ามันชัดเจนกว่าที่จะแยกการตรวจสอบประเภทออกจากตรรกะความเท่าเทียมกัน
orip

26
วาทกรรม @orip เป็นสิ่งที่ท้อใจอย่างหนักในคำถาม โปรดดูหัวข้อเมตาที่เกี่ยวข้องเพื่อเรียนรู้เหตุผลเบื้องหลัง การวางคำตอบให้กับคำถามของตัวเองในคำถามนั้นขัดกับนโยบายเว็บไซต์ OTOH ขอบคุณสำหรับการตอบกลับและการมี "แก้ไข" ในคำตอบของคุณเป็นเรื่องปกติ หากคุณต้องการให้คุณติดอันดับคำถามเพื่อระบุว่าคุณเป็นคนที่ไม่รู้ว่า SO คืออะไรและจะใช้อย่างไรและไม่ต้องการที่จะเรียนรู้ - เป็นแขกของฉัน

14
@orip: มันไม่ได้ "หลงทาง"; มันยังคงสับสนอยู่กับประวัติการแก้ไขของคำถามหากคุณต้องการดูอีกครั้ง แต่มันไม่ได้อยู่ในคำถาม ที่ตัวแทน 37k คุณควรรู้สิ่งนี้
การแข่งขัน Lightness ใน Orbit

6
กรุณาหยุดสงครามแก้ไข การแก้ไขกับคำถามนี้จะกล่าวถึงในเมตา โปรดอย่าแก้ไข / ย้อนกลับโพสต์นี้เพิ่มเติม หากคุณไม่เห็นด้วยกับการแก้ไข / ย้อนกลับก่อนหน้านี้หรือมีความคิดเห็นใด ๆ เกี่ยวกับพวกเขาโปรดโพสต์บนเธรดเมตานั้นไม่ใช่ที่นี่
Lundin

คำตอบ:


1301

นี่คือวิธีที่ฉันจะทำ:

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
}

อัปเดต [2018-05-31] : หากคุณไม่เกี่ยวข้องกับวัตถุวันที่จากบริบท JS อื่น ๆ (windows, กรอบหรือ iframes ภายนอก) รูปแบบที่ง่ายกว่านี้อาจเป็นที่ต้องการ:

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

21
instanceof แบ่งข้ามเฟรม การพิมพ์เป็ดสามารถใช้ได้เช่นกัน: validDate == d && d.getTime &&! isNaN (d.getTime ()); - เนื่องจากคำถามสำหรับฟังก์ชั่นยูทิลิตี้ทั่วไปฉันชอบที่จะเข้มงวดมากขึ้น
Borgar

11
@ Borgar เพิ่งพบคำตอบของฉัน: "ปัญหาเกิดขึ้นเมื่อมันมาถึงการเขียนสคริปต์ในสภาพแวดล้อม DOM หลายเฟรมในสรุปวัตถุ Array ที่สร้างขึ้นภายใน iframe หนึ่งไม่แบ่งปัน [[Prototype]] กับอาร์เรย์ที่สร้างขึ้นภายใน iframe อื่น คอนสตรัคเตอร์ของพวกเขาเป็นวัตถุที่แตกต่างกันดังนั้นอินสแตนซ์ทั้งสองและตัวตรวจสอบคอนสตรัคเตอร์จึงล้มเหลว "
Ash

64
คุณไม่ต้องการd.getTimeเพียงแค่isNan(d)
TecHunter

8
อาจทำให้เข้าใจง่ายเช่นนี้:d instanceof Date && !isNaN(d.getTime())
Zorgatone

5
ขอบคุณสำหรับคำตอบ แต่ฉันต้องการเน้นความคิดเห็น @Borgar และ @blueprintChris: หากฉันแยกตัวเลข1เช่นฉันจะยังคงมีวันที่ที่ถูกต้องMon Jan 01 2001 00:00:00ซึ่งเป็นวันที่แน่นอน . ดังนั้นจึงจำเป็นต้องมีการตรวจสอบอินพุตเพิ่มเติมอีกอย่างน้อยในกรณีของฉัน คำตอบนี้ตรวจสอบdateObjectไม่ได้Date!
dnhyde

264

แทนที่จะใช้new Date()คุณควรใช้:

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

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

Date.parse()ส่งคืนการประทับเวลาซึ่งเป็นจำนวนเต็มแทนจำนวนมิลลิวินาทีตั้งแต่ 01 / Jan / 1970 มันจะกลับมาNaNถ้ามันไม่สามารถแยกสตริงวันที่ให้มา


119
-1 Dunno เหตุใดจึงมีการโหวตมากขึ้นขึ้นDate.parseอยู่กับการใช้งานและแน่นอนว่าไม่ควรเชื่อถือในการแยกสตริงวันที่ทั่วไป ไม่มีรูปแบบเดียวที่มีการแยกวิเคราะห์อย่างถูกต้องในเบราว์เซอร์ที่เป็นที่นิยมน้อยกว่าทุกรูปแบบที่ใช้ (แม้ว่าในที่สุดรูปแบบ ISO8601 ที่ระบุใน ES5ควรจะโอเค)
RobG

1
หากคุณใช้วิธีการnew Date('foo')ที่เทียบเท่ากับDate.parse('foo')วิธีการทั่วไป ดูที่: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/ ...... ดังนั้นสิ่งที่ @RobG กล่าวว่ามันใช้กับมันด้วย
golddragon007

2
การทดสอบนี้จะล้มเหลวใน Chrome ตัวอย่างเช่น Date.parse ('AAA-0001') ใน Chrome ให้ตัวเลข
Nick

ล้มเหลว ... ตรวจพบค่าตัวเลขทั้งหมด
Hos Mercury

109

คุณสามารถตรวจสอบความถูกต้องของDateวัตถุdผ่าน

d instanceof Date && isFinite(d)

เพื่อหลีกเลี่ยงปัญหาข้ามเฟรมคุณสามารถแทนที่การinstanceofตรวจสอบด้วย

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

การโทรไปยังgetTime()ที่อยู่ในคำตอบของ Borgarนั้นไม่จำเป็นisNaN()และisFinite()ทั้งคู่ก็แปลงเป็นหมายเลข


ลองใช้โครเมี่ยม - Object.prototype.toString.call (วันที่ใหม่ ("2013-07-09T19: 07: 9Z")) มันจะส่งคืน "[วันที่วัตถุ]" ตามที่คุณดังนั้น "2013-07-09T19: 07: 9Z" ควรเป็นวันที่ที่ถูกต้อง แต่มันไม่ใช่ คุณสามารถตรวจสอบได้อีกครั้งด้วยโครเมี่ยมโดยทำ var dateStr = new Date ("2013-07-09T19: 07: 9Z"); dateStr มันจะกลับวันที่ไม่ถูกต้อง
ตินติน

2
@ ตินติน: นั่นคือสิ่งที่isFinite()มีไว้เพื่อ - toString.call()เป็นเพียงการแทนที่instanceofส่วนหนึ่งของการตรวจสอบ
Christoph

การเปรียบเทียบกับ '[object Date]' จะทำงานกับเบราว์เซอร์ที่ไม่ใช่ภาษาอังกฤษได้หรือไม่ ฉันสงสัยมัน.
Kristianp

2
@ Kristianp จริง ๆ แล้วมันอาจจะเป็นและอาจเป็นส่วนหนึ่งของข้อมูลจำเพาะ ECMAScript แต่ดูเหมือนว่าน่าเกลียด
binki

สำหรับฉันวิธีแรกที่นี่เป็นตัวเลือกที่ดีที่สุดถึงแม้ว่าฉันไม่แน่ใจว่ามีข้อได้เปรียบใด ๆ ในโลกแห่งความเป็นจริงในการใช้งานisFiniteมากกว่าisNaN(ใช้ได้ดีกับทั้งคู่Date(Infinity)) if (!(date instanceof Date) || isNaN(date))นอกจากนี้หากคุณต้องการสภาพตรงข้ามจะได้รับบิตง่าย:
Andrew

86

โซลูชันของฉันใช้สำหรับตรวจสอบว่าคุณได้รับวัตถุวันที่ที่ถูกต้องหรือไม่:

การดำเนินงาน

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

28
isNaNเป็นวิธีที่ชัดเจนยิ่งขึ้นในการทดสอบ NaN
orip

1
และคุณจะพบว่าคนเขียนเวอร์ชันของตัวเองอยู่เสมอ :) documentcloud.github.com/underscore/docs/…
Ash Clarke

4
เนื่องจากฉันเคารพ underscore.js สิ่งนี้ทำให้เกิดการวิจัย ในขณะที่isNaN("a") === true ("a" !== "a") === falseมันคุ้มค่าที่จะคิด +1
orip

8
ฉันทดสอบประสิทธิภาพสำหรับโซลูชันหลัก 3 ข้อที่ฉันพบที่นี่ ยินดีด้วยคุณเป็นผู้ชนะ! jsperf.com/detecting-an-invalid-date
zVictor

2
@Ali นั่นคือวัตถุวันที่ที่ถูกต้อง new Date("02-31-2000") // Thu Mar 02 2000 00:00:00 GMT+0000 (GMT Standard Time). หากคุณกำลังส่งผ่านสตริงไปยังตัวสร้างวันที่คุณต้องผ่านสตริงมาตรฐานเพื่อให้ได้ผลลัพธ์ที่เชื่อถือได้ โดยเฉพาะ "สตริงควรอยู่ในรูปแบบที่รู้จักโดยวิธี Date.parse ()" developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/
......

71

คำตอบที่สั้นที่สุดเพื่อตรวจสอบวันที่ที่ถูกต้อง

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

2
ปัญหาเดียวคือถ้าวันที่ไม่ได้เป็นประเภทวันที่; คุณได้รับข้อผิดพลาด JS
แอนดรู

@Andrew คุณต้องสร้างวัตถุวันที่และถ้าคุณมีวัตถุอยู่แล้วให้ใช้date && !isNaN(date.getTime())
abhirathore2006

ยังคงให้ข้อผิดพลาด JS แก่คุณหากdateไม่ใช่ประเภทวันที่ ตัวอย่างเช่นvar date = 4; date && !isNaN(date.getTime());.
Andrew

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

3
ใช่เหมือนคำตอบอื่น ๆ เมื่อ 8 ปีที่แล้ว : P stackoverflow.com/a/1353945/2321042
แอนดรูว์

45

คุณสามารถใช้moment.js

นี่คือตัวอย่าง:

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

ส่วนการตรวจสอบในเอกสารค่อนข้างชัดเจน

และการแยกวิเคราะห์ค่าสถานะต่อไปนี้ส่งผลให้วันที่ไม่ถูกต้อง:

  • overflow: การล้นของเขตข้อมูลวันที่เช่นเดือนที่ 13, วันที่ 32 ของเดือน (หรือวันที่ 29 กุมภาพันธ์ในปีที่ไม่ได้ก้าวกระโดด), วันที่ 367 ของปี ฯลฯ การล้นมีดัชนีของหน่วยที่ไม่ถูกต้อง เพื่อจับคู่ #invalidAt (ดูด้านล่าง); -1 หมายถึงไม่มีการล้น
  • invalidMonth: ชื่อเดือนไม่ถูกต้องเช่นช่วงเวลา ('Marbruary', 'MMMM'); มีสตริงเดือนที่ไม่ถูกต้องหรืออื่น ๆ เป็นโมฆะ
  • empty: สตริงอินพุตที่ไม่มีการแยกวิเคราะห์อะไรเช่นเดี๋ยว ('this is ไร้สาระ'); บูลีน
  • เป็นต้น

ที่มา: http://momentjs.com/docs/


6
ทางออกที่ดีที่สุดใช้งานง่ายมากทำงานกับการจัดรูปแบบใด ๆ (กรณีของฉันคือ dd / MM / yyyy) ก็รู้ปีอธิกสุรทินและไม่ได้แปลงวันที่ไม่ถูกต้อง (เช่น 29/02/2015) เป็นตัวที่ถูกต้องด้วยตัวเอง (เช่น 30/03/2015) ในการตรวจสอบวันที่ในรูปแบบวว / ดด / ปปปปฉันมีเพียงใช้moment("11/06/1986", "DD/MM/YYYY").isValid();
Rafael Merlin

3
การใช้ช่วงเวลานี้เลิกใช้แล้ว :(
James Sumners

2
การใช้งานนี้ไม่ได้รับการคิดค่าเสื่อมราคา ช่วงเวลาการโทร (อินพุต) โดยไม่มีสตริงรูปแบบจะถูกคิดค่าเสื่อมราคา (เว้นแต่อินพุตจะจัดรูปแบบ ISO)
เจตน์

2
วิธีนี้อาจช้ามากเมื่อประมวลผลหลายวัน ดีกว่าที่จะใช้ regex ในกรณีเหล่านั้น
ตาราง Trekkor

2
การใช้งานของ moment.js อาจง่าย แต่เป็นค่าใช้จ่ายมหาศาล ห้องสมุดนี้มีขนาดใหญ่มาก ฉันลงคะแนนคำตอบของคุณ
มิก

38

ต้องการพูดถึงว่าวิดเจ็ต jQuery UI DatePicker มีวิธียูทิลิตี้ตัวตรวจสอบวันที่ที่ดีมากที่ตรวจสอบรูปแบบและความถูกต้อง (เช่นไม่อนุญาตวันที่ 01/33/2013)

แม้ว่าคุณไม่ต้องการใช้วิดเจ็ต datepicker บนหน้าของคุณเป็นองค์ประกอบ UI คุณสามารถเพิ่มไลบรารี. js ในหน้าของคุณจากนั้นเรียกวิธีการตรวจสอบความถูกต้องผ่านค่าที่คุณต้องการตรวจสอบ เพื่อทำให้ชีวิตง่ายขึ้นใช้สตริงเป็นอินพุตไม่ใช่วัตถุวันที่ของ JavaScript

ดู: http://api.jqueryui.com/datepicker/

มันไม่ได้ระบุว่าเป็นวิธีการ แต่มี - เป็นฟังก์ชั่นยูทิลิตี้ ค้นหาหน้าสำหรับ "แยกวิเคราะห์" และคุณจะพบ:

$ .datepicker.parseDate (รูปแบบค่าการตั้งค่า) - แยกวันที่จากค่าสตริงด้วยรูปแบบที่ระบุ

ตัวอย่างการใช้งาน:

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 ซึ่งแสดงถึงค่าสตริงที่ผ่านเข้ามา ถ้าไม่มันจะไม่ได้กำหนด


3
โหวตขึ้นเป็นคำตอบแรกที่ทำงานกับรูปแบบวันที่ที่ไม่ใช่ภาษาอังกฤษ / ภาษา
ขวาน

26

ฉันชอบแนวทางของคริสโตฟจริงๆ (แต่มีชื่อเสียงไม่มากพอที่จะลงคะแนน) สำหรับการใช้งานของฉันฉันรู้ว่าฉันจะมีวัตถุวันที่เสมอดังนั้นฉันเพิ่งขยายวันที่ด้วยวิธีการที่ถูกต้อง ()

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

ตอนนี้ฉันสามารถเขียนและอธิบายได้มากกว่าแค่การตรวจสอบ isFinite ในรหัส ...

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

10
ขยายต้นแบบหรือไม่ นั่นเป็นจาวาสคริปต์ตัวใหญ่ที่ไม่!
Jasdeep Khalsa

Upvoting เนื่องจากการisFiniteทำงานสำหรับฉันอย่างสมบูรณ์แบบ แต่ใช่ไม่มีจุดหมายที่จะขยายต้นแบบ !isFiniteบนDateจะจับความจริงที่ว่าคือDate Invalid Dateนอกจากนี้ยังควรสังเกตบริบทของฉันอยู่ในโหนด
Staghouse


17

คุณสามารถตรวจสอบรูปแบบที่ถูกต้องของ txDate.value ด้วย scirpt นี้ ถ้ามันอยู่ในรูปแบบที่ไม่ถูกต้อง Date obejct จะไม่อินสแตนซ์และส่งคืน null เป็น dt

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

และตามที่ @ MiF แนะนำไว้ในระยะสั้น

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

isNaN (วันที่ใหม่ (... )) - วิธีที่ง่ายและสั้น
MiF

1
@MiF ใช่ฉันอัปเดตคำตอบด้วยคำแนะนำของคุณ;) ขอบคุณ
Yuseferi

16

ฉันใช้รหัสต่อไปนี้เพื่อตรวจสอบค่าสำหรับปีเดือนและวันที่

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

สำหรับรายละเอียดโปรดดูวันที่ตรวจสอบในจาวาสคริปต์


strไม่ได้ใช้งาน
samis

12

มีคำตอบที่ซับซ้อนมากเกินไปแล้วที่นี่ แต่บรรทัดง่ายพอ (ES5):

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

หรือแม้กระทั่งใน ES6:

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

1
จาก MDN: "วิธี Date.parse () แยกวิเคราะห์การแสดงสตริงของวันที่และส่งกลับจำนวนมิลลิวินาทีตั้งแต่ 1 มกราคม 1970, 00:00:00 UTC หรือ NaN ... " ดังนั้นการเรียกใช้วันที่ที่มีศักยภาพผ่านสิ่งนี้ ฟังก์ชั่นส่งกลับทั้งจำนวนเต็มหรือ NaN จากนั้นฟังก์ชั่น isNaN () จะให้บูลีนที่สะอาดซึ่งบอกคุณว่าค่าดั้งเดิมเป็นวัตถุวันที่ที่ถูกต้องหรือไม่ นี่เพียงพอที่จะทำการตรวจสอบเฉพาะจุด แต่ตัวอย่างข้างต้นแล้วแนบเมธอดนี้กับวัตถุ Date เพื่อให้การทำงานง่ายขึ้นและอ่านง่ายตลอดทั้งโปรแกรมของคุณ
Max Wilder

ถ้า d เป็นบูลีนคุณจะได้รับ 0 หรือ 1 นั่นไม่ใช่น่าน !!
davcup

@davcup เพิ่งทดสอบโดยใช้Date.parse(true)ฉันได้รับ NaN อย่างถูกต้อง
เซบาสเตียนเอช.

12

ฉันเห็นคำตอบบางคำที่ใกล้เคียงกับตัวอย่างเล็กน้อยนี้จริง

วิธี JavaScript:

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

วิธีพิมพ์อักษร:

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

1
ไม่แน่ใจว่าฉันทำอะไรบางอย่างขาดหายไป แต่ไม่ทำ Date ใหม่ () ไม่มีจุดหมายสองครั้งใช่ไหม
Jon Catmull

2
หลังมีอะไรจะทำอย่างไรกับ TypeScript มันเป็น JS ที่ถูกต้องสมบูรณ์
hackel

9

ทางออกที่ดี! รวมอยู่ในห้องสมุดของฟังก์ชั่นเสริมตอนนี้ดูเหมือนว่า:

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

มันใช้งานได้สำหรับฉัน

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

อย่างไรก็ตามสิ่งนี้ไม่ได้ผล

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

5
ฉันเชื่อว่านี่ขึ้นอยู่กับเบราว์เซอร์
barrypicker

@barrypicker คุณหมายความว่าอะไรขึ้นอยู่กับเบราว์เซอร์
Ajil O.

คุณสามารถทำได้: `${new Date('foo')}` === 'Invalid Date'
Daniele Vrut

9

สำหรับโครงการ Angular.js คุณสามารถใช้:

angular.isDate(myDate);

3
สิ่งนี้จะคืนค่าจริงเมื่อทำการทดสอบวัตถุวันที่ซึ่งถูกกำหนดค่าเริ่มต้นด้วยวันที่ไม่ถูกต้อง
dchhetri

6

ไม่มีคำตอบใด ๆ ที่ใช้ได้สำหรับฉัน (ทดสอบใน Safari 6.0) เมื่อพยายามตรวจสอบวันที่เช่น 2/31/2012 แต่ก็ใช้ได้ดีเมื่อพยายามวันที่ใด ๆ ที่มากกว่า 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

(วันที่ใหม่ ('2/30/2014')) ถูกต้อง () ผลตอบแทนจริง
Andre Figueiredo

1
นานมาแล้วที่ฉันได้ตอบคำถามนี้ แต่คุณอาจจำเป็นต้องมีเงื่อนไขการคืนสินค้ารวมถึง&& value.split('/')[0] == (d.getMonth()+1);
Dex

การใช้new Date('string date')เทียบเท่ากับDate.parse('string date')ดู: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/ ......ดังนั้นคุณอาจได้รับค่าจริงหรือเท็จ
golddragon007

5

วิธีการแก้ปัญหาข้างต้นไม่เหมาะกับฉัน

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

รหัสข้างต้นจะเห็นเมื่อ JS ทำให้ 02/31/2012 เป็น 03/02/2012 ที่ไม่ถูกต้อง


3
ตกลง แต่เป็นการทดสอบว่าสตริงเป็นวันที่ในรูปแบบ M / D / Y ไม่ใช่ "ความแตกต่างระหว่างวัตถุวันที่ที่ถูกต้องและไม่ถูกต้อง" มันไม่ใช่คำถามที่ถาม
Borgar

เหตุผลที่การตรวจสอบกับรูปแบบคือการตรวจสอบว่าวันที่มีการเปลี่ยนแปลงหลังจากที่ได้รับการแยกวิเคราะห์
จอห์น

OP ขอวิธีการส่งคืนบูลีนไม่ใช่สตริงที่จัดรูปแบบใช่หรือไม่
barrypicker

1
โค้ดตัวอย่างส่งคืนบูลีนการจัดรูปแบบมีส่วนในการทดสอบกรณีที่ไม่ถูกต้อง
จอห์น

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

ฉันได้เขียนฟังก์ชันนี้ ส่งผ่านพารามิเตอร์สตริงและจะพิจารณาว่าเป็นวันที่ที่ถูกต้องหรือไม่ตามรูปแบบ "dd / MM / yyyy"

นี่คือการทดสอบ

อินพุต: "hahaha", เอาต์พุต: false

อินพุต: "29/2/2000", เอาต์พุต: จริง

อินพุต: "29/2/2001", เอาต์พุต: false

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.toISOStringพ่นRangeError(อย่างน้อยใน Chromium และ Firefox) ในวันที่ไม่ถูกต้อง คุณสามารถใช้มันเป็นวิธีการตรวจสอบและอาจไม่จำเป็นisValidDateเช่น (EAFP) มิฉะนั้นมันคือ:

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

1
ดูเหมือนว่ามันเป็นฟังก์ชั่นเดียวที่ส่งข้อผิดพลาดตามข้อกำหนด ECMA-262 15.9.5.43 Date.prototype.toISOString () ฟังก์ชั่นนี้จะส่งกลับค่าสตริงแสดงอินสแตนซ์ในเวลาที่แสดงโดยวัตถุวันที่นี้ รูปแบบของสตริงเป็นรูปแบบสตริงวันที่เวลาที่กำหนดใน 15.9.1.15 ฟิลด์ทั้งหมดมีอยู่ในสตริง เขตเวลาเป็น UTC เสมอซึ่งแสดงโดยคำต่อท้าย Z หากค่าเวลาของวัตถุนี้ไม่ใช่จำนวนที่แน่นอนจะมีการโยนข้อยกเว้น RangeError
Henry Liu

3

ได้รับแรงบันดาลใจจากแนวทางของ Borgar ฉันตรวจสอบให้แน่ใจว่ารหัสไม่เพียง แต่ตรวจสอบวันที่ แต่จริง ๆ แล้วทำให้แน่ใจว่าวันที่เป็นวันที่จริงซึ่งหมายความว่าไม่อนุญาตให้ใช้วันที่เช่น 31/09/2011 และ 29/02/2011

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

แต่ ... วิธีการด้านบน (@ Borgar และคนอื่น ๆ ) ตรวจสอบความถูกต้องของประเภทนี้แล้ว ... ฉันไม่สามารถรับปัญหาได้
สีน้ำเงิน

Borgar ไม่ได้ - ดูความเห็นของเขาต่อคำตอบของเขา
EML

1
วิธีนี้ใช้ได้เฉพาะเมื่อประเทศของคุณใช้dd/MM/yyyyสัญลักษณ์ นอกจากนี้มันจะกลับมาtrueเมื่อมันถูกต้อง & 'Invalid date!'ถ้ามันไม่ได้ผลตอบแทนที่ดีกว่า 1 ประเภทเท่านั้น
A1rPun

3

ฉันรวมผลลัพธ์ประสิทธิภาพที่ดีที่สุดที่ฉันพบรอบ ๆ การตรวจสอบว่าวัตถุที่กำหนด:

ผลที่ได้คือ:

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

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

2

วันที่วัตถุกับสตริงเป็นวิธีที่ง่ายและเชื่อถือได้มากขึ้นในการตรวจสอบว่าทั้งสองเขตข้อมูลเป็นวันที่ที่ถูกต้อง เช่นถ้าคุณป้อน "-------" นี้ลงในช่องป้อนวันที่ คำตอบข้างต้นบางคำอาจไม่ทำงาน

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

คำตอบที่เลือกนั้นยอดเยี่ยมและฉันก็ใช้มันเช่นกัน อย่างไรก็ตามหากคุณกำลังมองหาวิธีในการตรวจสอบความถูกต้องของการป้อนข้อมูลวันที่ของผู้ใช้คุณควรทราบว่าวัตถุ Date นั้นมีความคงทนมากเกี่ยวกับการทำให้สิ่งที่อาจดูเหมือนว่าจะเป็นข้อโต้แย้งการก่อสร้างที่ไม่ถูกต้อง รหัสการทดสอบหน่วยต่อไปนี้แสดงให้เห็นถึงจุด:

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

เรียกว่าเป็นแบบนี้

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

2

ฟังก์ชั่นพร้อมใช้ขึ้นอยู่กับคำตอบที่ได้รับความนิยมสูงสุด:

  /**
   * 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

วิธีที่ง่ายและสง่างาม:

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

แหล่งที่มา:

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

[2] วันที่ไม่ถูกต้องแสดงในวันที่ใหม่ () ใน JavaScript


1
date.getDate() == dayไม่เพียงพอที่จะตรวจสอบว่าวันที่ถูกต้อง รูปแบบวันที่ดั้งเดิมจะส่งคืนวันที่ที่ไม่ถูกต้องในการใช้งานบางอย่างโดยไม่คำนึงว่าวันนั้นจะถูกต้องหรือไม่ นอกจากนี้ "1970-01-01 00:00" หากการแยกวิเคราะห์อย่างถูกต้องจะกลับเท็จ (เช่นBoolean(+new Date("1970-01-01"))กลับเท็จ)
RobG

คำเตือน: สิ่งนี้จะไม่ทำงานใน Safari
Vigrant

มันจะทำงานใน Safari ถ้าคุณใช้รูปแบบconst date = new Date(year, month, day); โปรดทราบว่าเดือนนี้เป็น 0 ดัชนีด้วยวิธีนี้ดังนั้นคุณอาจต้องลบหนึ่งบรรทัดเพื่อให้เข้ากันได้อย่างถูกต้อง
Vigrant

1

ฉันคิดว่าบางอย่างนี้เป็นกระบวนการที่ยาวนาน เราสามารถตัดสั้นตามที่แสดงด้านล่าง:

 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
คำถามถามถึงวิธีการค้นหาอินสแตนซ์วันที่ที่ไม่ถูกต้องไม่ใช่สตริงและอื่น ๆ : ใครบอกว่าวันที่ไม่สามารถคั่นด้วยบางอย่างที่ไม่ใช่สแลชฟอร์เวิร์ด
Jon z

1

สำหรับส่วนประกอบพื้นฐานของวันที่:

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

แบบทดสอบ:

    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)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.