web-dev-qa-db-ja.com

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 で確認しましたが、これは標準の動作です。まさに私が探しているものです。
1254
orip

これが私のやり方です。

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コンテキスト(外部ウィンドウ、フレーム、またはiframe)からのDateオブジェクトを気にしないのであれば、この単純な形式が好ましいかもしれません:

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

new Date()を使う代わりに、あなたは使うべきです:

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

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

Date.parse()はタイムスタンプを返します。これは1970年1月1日からのミリ秒数を表す整数です。指定された日付文字列を解析できない場合はNaNを返します。

233
Ash

Dateオブジェクトdの妥当性は、次の方法で確認できます。

d instanceof Date && isFinite(d)

クロスフレームの問題を回避するために、instanceofチェックを次のように置き換えます。

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

Borgarの答え のようにgetTime()を呼び出すことは、isNaN()isFinite()の両方が暗黙的に数値に変換されるので不要です。

97
Christoph

私の解決策は単にあなたが有効な日付オブジェクトを取得しているかどうかをチェックすることです:

実装

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
75
Ash Clarke

有効な日付を確認するための最短回答

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

moment.jsを使用するだけです。

これが一例です。

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

ドキュメントの 検証セクション は、はっきりしています。

また、次の解析フラグは無効な日付になります。

  • overflow:13日、32日(うるう年以外の場合は2月29日)、367日など、日付フィールドのオーバーフローに無効なインデックスが含まれる#invalidAtと一致する単位(下記参照)。 -1はオーバーフローなしを意味します。
  • invalidMonth:moment( 'Marbruary'、 'MMMM');のような無効な月名無効な月の文字列自体を含むか、それ以外の場合はnullを含みます。
  • empty:moment( 'this is nonsense');のように解析可能なものが何も含まれていない入力文字列。ブール値。
  • 等。

ソース: http://momentjs.com/docs/

42
Yves M.

JQuery UI DatePickerウィジェットには、形式と有効性をチェックする非常に優れた日付検証ユーティリティメソッドがあります(2013年1月33日には許可されていないなど)。

ページ上の日付ピッカーウィジェットをUI要素として使用したくない場合でも、いつでも.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オブジェクトになります。そうでなければ、それは未定義であろう。

37
Matt Campbell

私はChristophのアプローチが本当に好きでした(しかしそれを投票するのに十分な評判がありませんでした)。私の使用のために、私は常にDateオブジェクトを持つことを知っているので、私はvalid()メソッドでdateを拡張しただけです。

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

今、私はこれを書くことができます、そしてそれは単にコードでisFiniteをチェックするよりはるかに説明的です...

d = new Date(userDate);
if (d.valid()) { /* do stuff */ }
22
broox
// check whether date is valid
var t = new Date('2011-07-07T11:20:00.000+00:00x');
valid = !isNaN(t.valueOf());
19
faridz

年、月、日の値を検証するために次のコードを使用します。

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で日付を確認 を参照してください。

15
Jingguo Yao

ここではすでに複雑すぎる答えが多すぎますが、単純な行で十分です(ES5)

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

あるいはES6でも:

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

あなたはこのスクリプトでtxDate.valueの有効なフォーマットをチェックすることができます。形式が正しくない場合、Dateオブジェクトはインスタンス化されず、dtにnullが返されます。

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

そして@ MiFが手短に示唆したように

 if(isNaN(new Date(...)))
12
Yusef Mohamadi

いい解決策!私の補助関数ライブラリに含まれるようになりましたが、現在は次のようになっています。

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

Angular.jsプロジェクトの場合は、次のものを使用できます。

angular.isDate(myDate);
9
Nick Taras

これはちょうど私のために働いた

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

しかしこれはうまくいきませんでした

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

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
6
Dex

上記の解決策のどれも私にとってうまくいきませんでした

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が2012年2月31日に2012年3月2日になったときに有効ではないことがわかります。

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

私はこの機能を書きました。文字列パラメータを渡すと、このフォーマット "dd/MM/yyyy"に基づいて、それが有効な日付かどうかを判断します。

これがテストです

入力: "ははは"、出力:false.

入力: "29/2/2000"、出力:true.

入力: "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
Yaseen

Borgarのアプローチに触発された私は、コードが日付を検証するだけでなく、実際に日付が実際の日付であることを確認したことを確認しました。

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

与えられたオブジェクトがあるかどうか、そのチェックに関して見つけた最高のパフォーマンス結果を組み合わせました。

結果は次のとおりです。

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

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

最高と評価された答えに基づく準備ができている機能:

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

選択された答えは素晴らしいです、そして私はそれも使っています。しかし、ユーザーの日付入力を検証する方法を探しているのであれば、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
dolphus333

文字列への日付オブジェクトは両方のフィールドが有効な日付であるかどうかを検出するためのより簡単で信頼性の高い方法です。例えば日付入力欄にこの「-------」を入力すると。上記の答えのいくつかはうまくいきません。

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
kam
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
kiranvj

あなたはあなたの日付と時間をミリ秒に変換することができます getTime()

this getTime()メソッドは無効な場合は数ではないNaNを返します

if(!isNaN(new Date("2012/25/255").getTime()))
  return 'valid date time';
  return 'Not a valid date time';
2
Mina Gabriel
function isValidDate(date) {
  return !! (Object.prototype.toString.call(date) === "[object Date]" && +date);
}
1
Joel Kornbluh

日付のint 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)
1
Denis Ryzhkov

私はこれのいくつかは長いプロセスだと思います。以下のように短くすることができます。

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

Date.prototype.toISOStringは無効な日付にRangeErrorをスローします(少なくともChromiumとFirefoxでは)。検証の手段としてそれを使うことができ、そのようにisValidDateを必要としないかもしれません(EAFP)。それ以外の場合:

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

シンプルでエレガントなソリューション:

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の新しいDate()に誤った日付が表示されます

1
Soubriquet

私はこの小さなスニペットに本当に近づいたいくつかの答えを見ました。

JavaScriptの方法:

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

TypeScriptの方法:

const isValidDate = dateString => new Date(dateString).toString() !== 'Invalid Date';
isValidDate(new Date('WTH'));
1
Jason Foglia

一般的に、私はブラウザスタックにDateの埋め込みがあるものは何でも固執します。つまり、Chrome、Firefox、およびSafariで toDateString() を呼び出すと、この返信の日付の時点で常に "Invalid Date"が表示されます。

if(!Date.prototype.isValidDate){
  Date.prototype.isValidDate = function(){
    return this.toDateString().toLowerCase().lastIndexOf('invalid') == -1;
  };
}

私はこれをIEでテストしませんでした。

1
pixelbacon

だから私は@ dskを通過することはできません日付のためのtry catchブロックを追加することによって少し改善して@Ask Clarkeの答えが好きd = new Date(d) -

function checkIfDateNotValid(d) {
        try{
            var d = new Date(d);
            return !(d.getTime() === d.getTime()); //NAN is the only type which is not equal to itself.
        }catch (e){
            return true;
        }

    }
1
Saurabh Gupta

必要なのはdate.parse(valueToBeTested) > 0だけです。有効な日付はEpoch値を返し、無効な値はNaNを返します。これは数値でなくても> 0テストに失敗します。

これは非常に単純なので、ヘルパー関数はコードを節約できませんが、もう少し読みやすいかもしれません。あなたがそれを望んだならば:

String.prototype.isDate = function() {
  return !Number.isNaN(Date.parse(this));
}

OR

使用するには:

"StringToTest".isDate();
0
rainabba

日付が有効な日付オブジェクトかどうかを調べるさらに別の方法:

const isValidDate = (date) => 
  typeof date === 'object' && 
  typeof date.getTime === 'function' && 
  !isNaN(date.getTime())
0
iwatakeshi
Date.valid = function(str){
  var d = new Date(str);
  return (Object.prototype.toString.call(d) === "[object Date]" && !isNaN(d.getTime()));
}

https://Gist.github.com/dustinpoissant/b83750d8671f10c414b346b16e290ecf

0
Dustin Poissant

このisValidDateは、うるう年を処理する正規表現を使用します。

function isValidDate(value)
{
    return /((^(10|12|0?[13578])([/])(3[01]|[12][0-9]|0?[1-9])([/])((1[8-9]\d{2})|([2-9]\d{3}))$)|(^(11|0?[469])([/])(30|[12][0-9]|0?[1-9])([/])((1[8-9]\d{2})|([2-9]\d{3}))$)|(^(0?2)([/])(2[0-8]|1[0-9]|0?[1-9])([/])((1[8-9]\d{2})|([2-9]\d{3}))$)|(^(0?2)([/])(29)([/])([2468][048]00)$)|(^(0?2)([/])(29)([/])([3579][26]00)$)|(^(0?2)([/])(29)([/])([1][89][0][48])$)|(^(0?2)([/])(29)([/])([2-9][0-9][0][48])$)|(^(0?2)([/])(29)([/])([1][89][2468][048])$)|(^(0?2)([/])(29)([/])([2-9][0-9][2468][048])$)|(^(0?2)([/])(29)([/])([1][89][13579][26])$)|(^(0?2)([/])(29)([/])([2-9][0-9][13579][26])$))/.test(value)
}
0
Greg Finzer
var isDate_ = function(input) {
        var status = false;
        if (!input || input.length <= 0) {
          status = false;
        } else {
          var result = new Date(input);
          if (result == 'Invalid Date') {
            status = false;
          } else {
            status = true;
          }
        }
        return status;
      }
0
Dhayalan

この関数は、文字で区切られた数字形式の文字列日付を検証します。 dd/mm/yyyy、mm/dd/yyyy

/*
Param  : 
1)the date in string data type 
2)[optional - string - default is "/"] the date delimiter, most likely "/" or "-"
3)[optional - int - default is 0] the position of the day component when the date string is broken up via the String.split function (into arrays)
4)[optional - int - default is 1] the position of the month component when the date string is broken up via the String.split function (into arrays)
5)[optional - int - default is 2] the position of the year component when the date string is broken up via the String.split function (into arrays)

Return : a javascript date is returned if the params are OK else null
*/
function IsValidDate(strDate, strDelimiter, iDayPosInArray, iMonthPosInArray, iYearPosInArray) {
    var strDateArr; //a string array to hold constituents day, month, and year components
    var dtDate; //our internal converted date
    var iDay, iMonth, iYear;


    //sanity check 
    //no integer checks are performed on day, month, and year tokens as parsing them below will result in NaN if they're invalid
    if (null == strDate || typeof strDate != "string")
        return null;

    //defaults
    strDelimiter = strDelimiter || "/";
    iDayPosInArray = undefined == iDayPosInArray ? 0 : iDayPosInArray;
    iMonthPosInArray = undefined == iMonthPosInArray ? 1 : iMonthPosInArray;
    iYearPosInArray = undefined == iYearPosInArray ? 2 : iYearPosInArray;

    strDateArr = strDate.split(strDelimiter);

    iDay = parseInt(strDateArr[iDayPosInArray],10);
    iMonth = parseInt(strDateArr[iMonthPosInArray],10) - 1; // Note: months are 0-based
    iYear = parseInt(strDateArr[iYearPosInArray],10);

    dtDate = new Date(
        iYear,
        iMonth, // Note: months are 0-based
        iDay);

    return (!isNaN(dtDate) && dtDate.getFullYear() == iYear && dtDate.getMonth() == iMonth && dtDate.getDate() == iDay) ? dtDate : null; // Note: months are 0-based
}

呼び出し例

var strDate="18-01-1971";

if (null == IsValidDate(strDate)) {

  alert("invalid date");
}
0
wanglabs