วิธีตรวจสอบว่าวัตถุเป็นวันที่หรือไม่


601

ฉันมีข้อผิดพลาดที่น่ารำคาญในหน้าเว็บ:

date.GetMonth () ไม่ใช่ฟังก์ชัน

ดังนั้นฉันคิดว่าฉันกำลังทำอะไรผิด ตัวแปรไม่ได้เป็นวัตถุของการพิมพ์date ฉันจะตรวจสอบประเภทข้อมูลใน Javascript ได้อย่างไร ฉันพยายามเพิ่ม a แต่มันใช้งานไม่ได้Dateif (date)

function getFormatedDate(date) {
    if (date) {
       var month = date.GetMonth();
    }
}

ดังนั้นหากฉันต้องการเขียนรหัสป้องกันและป้องกันไม่ให้จัดรูปแบบวันที่ (ซึ่งไม่ใช่หนึ่ง) ฉันจะทำอย่างไร

ขอบคุณ!

UPDATE:ฉันไม่ต้องการที่จะตรวจสอบรูปแบบของวันที่ แต่ฉันต้องการให้แน่ใจว่าพารามิเตอร์ส่งผ่านไปยังวิธีการที่เป็นประเภทgetFormatedDate()Date


ในกรณีที่ควรได้รับการตรวจสอบว่าเป็นวันที่ไม่ใช่Invalid Date: stackoverflow.com/a/44198641/5846045
Boghyon Hoffmann

คำตอบ:


1109

เป็นอีกทางเลือกหนึ่งในการพิมพ์เป็ดผ่าน

typeof date.getMonth === 'function'

คุณสามารถใช้instanceofโอเปอเรเตอร์ได้ แต่มันจะคืนค่าจริงสำหรับวันที่ที่ไม่ถูกต้องเช่นกันเช่นnew Date('random_string')อินสแตนซ์ของวันที่

date instanceof Date

สิ่งนี้จะล้มเหลวหากวัตถุถูกส่งผ่านข้ามขอบเขตของเฟรม

การทำงานนี้คือการตรวจสอบคลาสของวัตถุผ่าน

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

28
คุณรู้สาเหตุของความล้มเหลวนี้เมื่อสนใจผ่านขอบเขตของเฟรมหรือไม่?
Simon Lieschke

85
@Simon: JS globals อยู่ในท้องถิ่นกับวัตถุทั่วโลกในปัจจุบัน (aka windowหรือself); เฟรมที่แตกต่างมีวัตถุทั่วโลกของตัวเองและคุณสมบัติของพวกเขา (เช่นกลม) หมายถึงวัตถุที่แตกต่าง: Dateใน frame1 เป็นวัตถุฟังก์ชั่นที่แตกต่างกว่าDateในเฟรม 2; เดียวกันเป็นจริงสำหรับDate.prototypeซึ่งเป็นเหตุผลในการที่instanceofล้มเหลว: Date.prototypeจากเฟรม 1 ไม่ได้เป็นส่วนหนึ่งของห่วงโซ่ต้นแบบของDateอินสแตนซ์จาก frame2
คริสโต

9
Christoph คุณเรียกว่า "frame" คืออะไร? IFRAME แต่ละเฟรมใน FRAMESET หรืออย่างอื่น (ฉันหมายถึงเฉพาะ JS ไม่ใช่ของ HTML)
พอล

12
new Date('something') instanceof Dateส่งคืนtrueใน Chrome แต่นั่นไม่ได้ผล
krillgar

12
การตรวจจับวัตถุประเภทวันที่ (ตรงข้ามกับวัตถุธรรมดาหรือสตริง) และการตรวจสอบวัตถุที่คุณคาดว่าจะเป็นวันที่มีสองงานที่แตกต่างกัน มีหลายสถานการณ์ที่อินพุตของฟังก์ชันของคุณอาจเป็นหนึ่งในจำนวนชนิดข้อมูลที่แตกต่างกัน ในกรณีของฉันฉันสามารถเชื่อถือได้ว่าวัตถุ Date ใด ๆ ที่ฉันได้รับนั้นถูกต้อง (ไม่ได้มาจากลูกค้าโดยตรง) หากการตรวจสอบเป็นเรื่องที่น่ากังวลนี่เป็นบทความที่มีตัวเลือกมากมาย stackoverflow.com/questions/1353684/…
Michael Blackburn

125

คุณสามารถใช้รหัสต่อไปนี้:

(myvar instanceof Date) // returns true or false

6
ทำไมนี่ไม่ใช่คำตอบที่ได้รับการยอมรับ เพียงตรวจสอบว่าวันที่มีคุณสมบัติ. getMonth อาจทำให้เกิดการบวกผิด
doremi

24
อินสแตนซ์สามารถเรียกใช้ฟิล์มเนกาทีฟปลอมดูความคิดเห็นของคริสโตฟกับคำตอบของเขาเอง
Marco Mariani

2
@doremi ต่อไปนี้เป็นตัวอย่างของการinstanceofเรียกการลบที่เป็นเท็จ: jsbin.com/vufufoq/edit?html,js,console
Boghyon Hoffmann

68

เพื่อตรวจสอบว่าค่าเป็นประเภทที่ถูกต้องของวัตถุวันที่ JS มาตรฐานคุณสามารถใช้คำกริยานี้:

function isValidDate(date) {
  return date && Object.prototype.toString.call(date) === "[object Date]" && !isNaN(date);
}
  1. dateตรวจสอบว่าพารามิเตอร์ไม่ได้เป็นค่า falsy ( undefined, null, 0, ""ฯลฯ .. )
  2. Object.prototype.toString.call(date)ส่งกลับแสดงสตริงพื้นเมืองของชนิดของวัตถุที่กำหนด - "[object Date]"ในกรณีของเรา เนื่องจากdate.toString()แทนที่เมธอดพาเรนต์เราจำเป็นต้อง.callหรือ.applyเมธอดObject.prototypeโดยตรงซึ่ง ..
    • ข้ามประเภทวัตถุที่ผู้ใช้กำหนดด้วยชื่อคอนสตรัคเตอร์เดียวกัน (เช่น: "วันที่")
    • สามารถทำงานได้ทั้งบริบท JS ที่แตกต่างกัน (เช่น iframes) ในทางตรงกันข้ามกับinstanceofDate.prototype.isPrototypeOfหรือ
  3. !isNaN(date)Invalid Dateการตรวจสอบในที่สุดไม่ว่าจะเป็นค่าที่ไม่ได้เป็น

1
ว้าวสามารถใช้ในการตรวจสอบisNaN Dateนั่นเป็นระดับ PHP ที่ไม่ปกติ
Nick

@Nick วันที่เป็นตัวเลขแม้ว่า
Josiah

@Josiah ดีนั่นเองเอาบริบททั้งหมดมีการประทับเวลาที่นั่นแต่:typeof Date.now() === "number" typeof new Date() === "object"แม้ว่าที่จริงแล้ววันที่จะเป็นเวลาและสถานที่ในอวกาศ
Nick

39

ฟังก์ชั่นไม่ได้getMonth()GetMonth()

อย่างไรก็ตามคุณสามารถตรวจสอบว่าวัตถุมีคุณสมบัติ getMonth หรือไม่โดยทำสิ่งนี้ มันไม่ได้แปลว่าวัตถุนั้นเป็น Date แต่เป็นวัตถุใด ๆ ที่มีคุณสมบัติ getMonth

if (date.getMonth) {
    var month = date.getMonth();
}

3
ตรวจสอบว่ามัน callable:if (date.getMonth && typeof date.getMonth === "function") {...}
Aloso

20

ตามที่ระบุไว้ข้างต้นอาจเป็นเรื่องง่ายที่สุดที่จะตรวจสอบว่ามีฟังก์ชันอยู่ก่อนใช้งานหรือไม่ หากคุณสนใจจริง ๆ ว่ามันเป็นDateและไม่ใช่แค่วัตถุที่มีgetMonth()ฟังก์ชั่นลองทำสิ่งนี้:

function isValidDate(value) {
    var dateWrapper = new Date(value);
    return !isNaN(dateWrapper.getDate());
}

สิ่งนี้จะสร้างโคลนของค่าหากเป็นDateหรือสร้างวันที่ไม่ถูกต้อง จากนั้นคุณสามารถตรวจสอบว่าค่าวันที่ใหม่ไม่ถูกต้องหรือไม่


1
ขอบคุณสำหรับสิ่งนี้ อย่างไรก็ตามหากคุณผ่านตัวเลขหนึ่งหลักเช่น 0 หรือ 1 มันจะถือว่าเป็นวันที่ที่ถูกต้อง ... คิดอะไรบ้าง?
Ricardo Sanchez

ถูกต้อง @RicardoSanchez คุณอาจต้องการใช้คำตอบที่ยอมรับ ( Object.prototype.toString.call(value) === '[object Date]') ถ้าเป็นไปได้คุณจะได้รับตัวเลข วิธีการในคำตอบนี้จะบอกคุณจริงๆว่าvalueสามารถแปลงเป็น a Dateหรือไม่
bdukes

18

สำหรับทุกประเภทฉันปรุงวัตถุต้นแบบให้ทำงาน อาจเป็นประโยชน์กับคุณ

Object.prototype.typof = function(chkType){
      var inp        = String(this.constructor),
          customObj  = (inp.split(/\({1}/))[0].replace(/^\n/,'').substr(9),
          regularObj = Object.prototype.toString.apply(this),
          thisType   = regularObj.toLowerCase()
                        .match(new RegExp(customObj.toLowerCase()))
                       ? regularObj : '[object '+customObj+']';
     return chkType
            ? thisType.toLowerCase().match(chkType.toLowerCase()) 
               ? true : false
            : thisType;
}

ตอนนี้คุณสามารถตรวจสอบประเภทใด ๆเช่นนี้:

var myDate     = new Date().toString(),
    myRealDate = new Date();
if (myRealDate.typof('Date')) { /* do things */ }
alert( myDate.typof() ); //=> String

[ แก้ไขมีนาคม 2013 ] โดยยึดตามข้อมูลเชิงลึกที่ก้าวหน้านี้เป็นวิธีที่ดีกว่า:

Object.prototype.is = function() {
        var test = arguments.length ? [].slice.call(arguments) : null
           ,self = this.constructor;
        return test ? !!(test.filter(function(a){return a === self}).length)
               : (this.constructor.name ||
                  (String(self).match ( /^function\s*([^\s(]+)/im)
                    || [0,'ANONYMOUS_CONSTRUCTOR']) [1] );
}
// usage
var Some = function(){ /* ... */}
   ,Other = function(){ /* ... */}
   ,some = new Some;
2..is(String,Function,RegExp);        //=> false
2..is(String,Function,Number,RegExp); //=> true
'hello'.is(String);                   //=> true
'hello'.is();                         //-> String
/[a-z]/i.is();                        //-> RegExp
some.is();                            //=> 'ANONYMOUS_CONSTRUCTOR'
some.is(Other);                       //=> false
some.is(Some);                        //=> true
// note: you can't use this for NaN (NaN === Number)
(+'ab2').is(Number);                 //=> true

10

ขีดล่าง JSและLodashมีฟังก์ชันที่เรียกว่า.isDate()ซึ่งดูเหมือนจะเป็นสิ่งที่คุณต้องการ มันคุ้มค่าที่จะดูการใช้งานที่เกี่ยวข้อง: Lodash isDate , UnderscoreJs


8

วิธีที่ดีที่สุดที่ฉันพบคือ:

!isNaN(Date.parse("some date test"))
//
!isNaN(Date.parse("22/05/2001"))  // true
!isNaN(Date.parse("blabla"))  // false

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

1
@jspassov คำตอบนั้นแม่นยำยิ่งขึ้นถ้าสตริงเป็นวันที่หรือไม่ ที่ฉันกำลังมองหา ขอบคุณ !!
Anant

นี่เป็นคำตอบที่ดีที่สุดในการตรวจสอบว่าสตริงเป็นวันที่หรือไม่
James Gentes

3

คุณสามารถตรวจสอบว่ามีฟังก์ชั่นเฉพาะสำหรับวัตถุวันที่อยู่หรือไม่:

function getFormatedDate(date) {
    if (date.getMonth) {
        var month = date.getMonth();
    }
}

3

แทนที่จะใช้วิธีแก้ปัญหาทั้งหมดคุณสามารถใช้วิธีการต่อไปนี้:

dateVariable = new Date(date);
if (dateVariable == 'Invalid Date') console.log('Invalid Date!');

ฉันพบแฮ็คนี้ดีกว่า!


2

นอกจากนี้คุณสามารถใช้แบบสั้น

function getClass(obj) {
  return {}.toString.call(obj).slice(8, -1);
}
alert( getClass(new Date) ); //Date

หรืออะไรเช่นนี้

(toString.call(date)) == 'Date'

2

ฉันใช้วิธีที่ง่ายกว่านี้มาก แต่ไม่แน่ใจว่าจะมีเฉพาะใน ES6 หรือไม่

let a = {name: "a", age: 1, date: new Date("1/2/2017"), arr: [], obj: {} };
console.log(a.name.constructor.name); // "String"
console.log(a.age.constructor.name);  // "Number"
console.log(a.date.constructor.name); // "Date"
console.log(a.arr.constructor.name);  // "Array"
console.log(a.obj.constructor.name);  // "Object"

อย่างไรก็ตามสิ่งนี้จะใช้งานไม่ได้กับค่า Null หรือ undefined เนื่องจากไม่มี Constructor


วัตถุที่กำหนดเองใด ๆ ที่มีชื่อตัวสร้าง "วันที่" จะส่งคืน"Date"ซึ่งมีความเสี่ยงเช่นเดียวกับการตรวจสอบว่าพารามิเตอร์มีgetMonthคุณสมบัติหรือไม่
Boghyon Hoffmann

2
@boghyon ดูเหมือนว่าคนใดคนหนึ่งสร้างวัตถุที่มีชื่อตัวสร้างของไลบรารีมาตรฐาน Javascript ที่กำหนดไว้ล่วงหน้าแล้วไม่ปฏิบัติตามแนวทางปฏิบัติที่ดีที่สุดในตอนแรก ที่จะเป็นเหมือนการดาวน์โหลด lodash จากนั้นสร้างโมดูล lodash ของคุณเองและคาดหวังสิ่งต่าง ๆ ให้ใช้งานได้
mjwrazor

1

ฟังก์ชั่นนี้จะกลับมาtrueถ้าเป็นวันที่หรือfalseอย่างอื่น:

function isDate(myDate) {
    return myDate.constructor.toString().indexOf("Date") > -1;
} 

1
isDate(new (function AnythingButNotDate(){ })())ผลตอบแทนtrue
Boghyon Hoffmann

1

อีกรุ่นหนึ่ง:

Date.prototype.isPrototypeOf(myDateObject)

ดีและสั้น! แต่น่าเสียดายที่มันมีปัญหาเช่นเดียวกับ instanceof
Boghyon Hoffmann

@BoghyonHoffmann ในกรณีของ iFrame มันอาจมีลักษณะ: iWindow.Date.prototype.isPrototypeOf(iWindow.date); // true iWindow.date instanceof iWindow.Date; // true
Vadim

1

วิธีการที่ใช้ลอง / จับ

function getFormatedDate(date = new Date()) {
  try {
    date.toISOString();
  } catch (e) {
    date = new Date();
  }
  return date;
}

console.log(getFormatedDate());
console.log(getFormatedDate('AAAA'));
console.log(getFormatedDate(new Date('AAAA')));
console.log(getFormatedDate(new Date(2018, 2, 10)));


0

Objectวันจริงจะเป็นประเภท แต่คุณสามารถตรวจสอบว่าวัตถุมีgetMonthวิธีการและถ้ามันเป็น callable

function getFormatedDate(date) {
    if (date && date.getMonth && date.getMonth.call) {
       var month = date.getMonth();
    }
}

2
คำตอบของ Christoph นั้นแม่นยำกว่า การมีคุณสมบัติ 'โทร' ไม่ได้แปลว่าเป็นฟังก์ชั่น!
Chetan Sastry

-1

นอกจากนี้เรายังสามารถตรวจสอบได้โดยรหัสด้านล่าง

var a = new Date();
a.constructor === Date
/*
true
*/

ป้อนคำอธิบายรูปภาพที่นี่


ตัวสร้างของนอกจากนี้ยังมีfunction Date() {/*...*/} Dateเช่นการเปรียบเทียบฟังก์ชั่นคอนสตรัคเตอร์นั้นผิดพลาดง่ายเกินไปซึ่งมักส่งผลให้เกิดผลบวกปลอม บายพาสชนิดของวัตถุที่ผู้ใช้กำหนดด้วยstackoverflow.com/a/44198641/5/5606045
Boghyon Hoffmann

-1

ได้รับแรงบันดาลใจจากคำตอบนี้โซลูชันนี้ทำงานในกรณีของฉัน (ฉันต้องการตรวจสอบว่าค่าที่ได้รับจาก API เป็นวันที่หรือไม่):

!isNaN(Date.parse(new Date(YourVariable)))

วิธีนี้ถ้ามันเป็นสตริงสุ่มบางส่วนที่มาจากลูกค้าหรือวัตถุอื่น ๆ คุณสามารถค้นหาว่ามันเป็นวัตถุคล้ายวันที่


-2

คุณไม่สามารถใช้

function getFormatedDate(date) {
    if (date.isValid()) {
       var month = date.GetMonth();
    }
}

1
ไม่เฉพาะวัตถุวันที่เท่านั้นที่มีisValidเมธอด
nikk wong

2
@grumpy @nikkwong ไม่และไม่ isValidวัตถุวันที่มาตรฐานไม่ได้ moment.jsเท่านั้นที่มี API ดังกล่าว
Boghyon Hoffmann
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.