Обнаружение «неверной даты» Дата экземпляра в JavaScript

Я хотел бы сказать разницу между действительными и недействительными объектами даты в 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?

  • Ясень рекомендовал Date.parse для анализа строк даты, что дает надежный способ проверить, является ли строка даты действительной.
  • То, что я бы предпочел, если это возможно, это чтобы мой API принимал экземпляр Date и мог проверять / утверждать, действителен ли он или нет. Решение Боргара делает это, но мне нужно протестировать его в разных браузерах. Мне также интересно, есть ли более элегантный способ.
  • Эш заставил меня подумать о том, чтобы мой API вообще не принимал Date экземпляров, это было бы проще всего проверить.
  • Боргар предложил проверить экземпляр Date, а затем проверить значение времени Date Если дата недействительна, значение времени составляет NaN. Я проверил с ECMA-262 , и это стандартное поведение, которое именно то, что я ищу.
вопрос задан 30.08.2009
orip
45654 репутация

37 ответов


  • 916 рейтинг

    Вот как бы я это сделал:

    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] : Если вас не интересуют объекты Date из других контекстов JS (внешних окон, фреймов или фреймов), эта более простая форма может оказаться предпочтительной:

    function isValidDate(d) {
      return d instanceof Date && !isNaN(d);
    }
    
    ответ дан Borgar, с репутацией 25529, 30.08.2009
  • 214 рейтинг

    Вместо new Date() вы должны использовать:

    var timestamp = Date.parse('foo');
    
    if (isNaN(timestamp) == false) {
      var d = new Date(timestamp);
    }
    

    Date.parse() возвращает отметку времени, целое число, представляющее количество миллисекунд с 01 января 1970 года. Он вернет NaN, если не сможет проанализировать предоставленную строку даты.

    ответ дан Ash, с репутацией 46079, 30.08.2009
  • 91 рейтинг

    Вы можете проверить действительность объекта Date d через

    d instanceof Date && isFinite(d)
    

    Чтобы избежать проблем с кросс-кадрами, можно заменить проверку instanceof на

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

    Вызов getTime(), как в Ответ Боргара не нужен, так как isNaN() и isFinite() оба неявно преобразуются в число.

    ответ дан Christoph, с репутацией 125604, 30.08.2009
  • 68 рейтинг

    Мое решение - просто проверить, есть ли у вас действительный объект даты:

    Реализация

    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
    
    ответ дан Ash Clarke, с репутацией 3682, 11.09.2012
  • 56 рейтинг

    кратчайший ответ, чтобы проверить правильную дату

    if(!isNaN(date.getTime()))
    
    ответ дан abhirathore2006, с репутацией 2089, 4.07.2016
  • 36 рейтинг

    Хотелось бы отметить, что виджет DatePicker пользовательского интерфейса jQuery имеет очень хороший метод утилиты проверки даты, который проверяет формат и достоверность (например, г. , даты 01/33/2013 не допускаются).

    Даже если вы не хотите использовать виджет DatePicker на своей странице в качестве элемента пользовательского интерфейса, вы всегда можете добавить его. js библиотеку на свою страницу и затем вызовите метод validator, передав в него значение, которое вы хотите проверить Чтобы сделать жизнь еще проще, в качестве входных данных используется строка, а не объект JavaScript Date

    См .: http: // api. jqueryui. com / datepicker /

    Он не указан как метод, но он есть - как служебная функция. Поиск на странице "parsedate", и вы найдете:

    $. 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, представляющий переданное строковое значение. Если нет, это было бы неопределенным.

    ответ дан Matt Campbell, с репутацией 1235, 15.02.2013
  • 23 рейтинг

    Мне очень понравился подход Кристофа (но мне не хватило репутации, чтобы проголосовать) Для моего использования я знаю, что у меня всегда будет объект Date, поэтому я просто расширил дату с помощью метода valid ().

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

    Теперь я могу просто написать это, и это гораздо более наглядно, чем просто проверка isFinite в коде. , ,

    d = new Date(userDate);
    if (d.valid()) { /* do stuff */ }
    
    ответ дан broox, с репутацией 2263, 23.11.2010
  • 15 рейтинг

    Я использую следующий код для проверки значений года, месяца и даты.

    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

    ответ дан Jingguo Yao, с репутацией 2527, 27.10.2011
  • 15 рейтинг
    // check whether date is valid
    var t = new Date('2011-07-07T11:20:00.000+00:00x');
    valid = !isNaN(t.valueOf());
    
    ответ дан faridz, с репутацией 296, 6.07.2011
  • 12 рейтинг

    вы можете проверить действительный формат txDate. значение с этим сценарием. если он был в неправильном формате, объект Date не является экземпляром и возвращает ноль в dt.

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

    И как @ MiF's предложил коротко

     if(isNaN(new Date(...)))
    
    ответ дан zhilevan, с репутацией 3060, 14.05.2012
  • 12 рейтинг

    Здесь уже слишком много сложных ответов, но достаточно простой строки (ES5):

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

    или даже в ES6:

    Date.prototype.isValid = d => !isNaN(Date.parse(d));
    
    ответ дан Sebastien H., с репутацией 3000, 11.05.2017
  • 9 рейтинг

    Хорошее решение! Включено в мою библиотеку вспомогательных функций, теперь это выглядит так:

    Object.isDate = function(obj) {
    /// 
    /// Determines if the passed object is an instance of Date. ///
     
    /// 
    The object to test.
    
        return Object.prototype.toString.call(obj) === '[object Date]';
    }
    
    Object.isValidDate = function(obj) {
    /// 
    /// Determines if the passed object is a Date object, containing an actual date. ///
     
    /// 
    The object to test.
    
        return Object.isDate(obj) && !isNaN(obj.getTime());
    }
    
    ответ дан Dmytro Shevchenko, с репутацией 22057, 3.05.2011
  • 9 рейтинг

    Для угловых. проекты, которые вы можете использовать:

    angular.isDate(myDate);
    
    ответ дан Nick Taras, с репутацией 245, 18.09.2015
  • 6 рейтинг

    Это просто работает для меня

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

    Однако это не сработало

    new Date('foo') === 'Invalid Date'; //is false
    
    ответ дан user1296274, с репутацией 99, 6.01.2014
  • 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 делает 31/02/2012 в 03/02/2012, что это не действительно

    ответ дан John, с репутацией 2596, 31.08.2012
  • 5 рейтинг

    Ни один из этих ответов не работал для меня (проверено в Safari 6. 0) при попытке проверить дату, такую ​​как 31.02.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
    
    ответ дан Dex, с репутацией 8239, 9.09.2012
  • 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;
    }
    
    ответ дан Michael Goldshmidt, с репутацией 123, 14.09.2012
  • 4 рейтинг

    Я написал эту функцию. Передайте ему строковый параметр, и он будет определять, является ли это действительной датой или нет, основываясь на этом формате «дд / мм / гггг».

    вот тест

    вход: "хахаха", выход: ложь.

    вход: «29/2/2000», выход: true.

    вход: "29/2/2001", выход: ложь.

    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;
        }
    }
    
    ответ дан Yaseen, с репутацией 52, 25.02.2014
  • 3 рейтинг

    Вдохновленный подходом Боргара, я убедился, что код не только проверяет дату, но и на самом деле удостоверяется, что дата является реальной датой, то есть такие даты, как 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!";
    }
    
    ответ дан Raz, с репутацией 542, 18.08.2011
  • 3 рейтинг

    Я объединил лучшие результаты производительности, которые я нашел вокруг этой проверки, если данный объект:

    Результат следующий:

    function isValidDate(input) {
      if(!(input && input.getTimezoneOffset && input.setUTCFullYear))
        return false;
    
      var time = input.getTime();
      return time === time;
    };
    
    ответ дан zVictor, с репутацией 2072, 25.07.2014
  • 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;
    }
    
    ответ дан Zon, с репутацией 4619, 20.03.2017
  • 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());
    });
    
    ответ дан dolphus333, с репутацией 380, 18.06.2014
  • 2 рейтинг

    Объект Date to string является более простым и надежным способом определения, являются ли оба поля действительными. е. г. Если вы введете это «-------» в поле ввода даты. Некоторые из приведенных выше ответов не сработают.

    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}.');
    
    ответ дан kam, с репутацией 21, 12.08.2013
  • 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
    
    ответ дан kiranvj, с репутацией 11147, 23.08.2015
  • 2 рейтинг

    Вы можете преобразовать дату и время в миллисекунды. getTime ()

    это getTime() Метод return Не число NaN, если оно недействительно

    if(!isNaN(new Date("2012/25/255").getTime()))
      return 'valid date time';
      return 'Not a valid date time';
    
    ответ дан Mina Gabriel, с репутацией 9234, 23.11.2013
  • 1 рейтинг
    function isValidDate(date) {
      return !! (Object.prototype.toString.call(date) === "[object Date]" && +date);
    }
    
    ответ дан Joel Kornbluh, с репутацией 1197, 23.04.2015
  • 1 рейтинг

    Для основанных на 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)
    
    ответ дан Denis Ryzhkov, с репутацией 1186, 8.11.2013
  • 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;
        }
    
    ответ дан user889209, с репутацией 35, 11.08.2011
  • 1 рейтинг

    Обычно я придерживаюсь любой имплантации даты в стеке браузера Это означает, что вы всегда получите «Неверную дату» при вызове toDateString () в Chrome, Firefox и Safari на дату этого ответа.

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

    Я не проверял это в IE, хотя.

    ответ дан pixelbacon, с репутацией 23, 26.08.2014
  • 1 рейтинг

    Так что мне понравился ответ @Ask Clarke с небольшим улучшением, добавив блок try catch для дат, которые не могут пройти через var 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;
            }
    
        }
    
    ответ дан Saurabh Gupta, с репутацией 138, 25.04.2017
  • 0 рейтинг

    Date.prototype.toISOString выбрасывает RangeError (по крайней мере, в Chromium и Firefox) в недействительные даты. Вы можете использовать его как средство проверки и, возможно, не нуждаетесь в isValidDate как таковом (EAFP). В противном случае это:

    function isValidDate(d)
    {
      try
      {
        d.toISOString();
        return true;
      }
      catch(ex)
      {
        return false;    
      }    
    }
    
    ответ дан saaj, с репутацией 10587, 15.07.2018
  • 0 рейтинг

    date.parse(valueToBeTested) > 0 это все что нужно. Допустимая дата вернет значение эпохи, а недопустимое значение вернет NaN, что не пройдёт тест > 0, даже не будучи числом

    Это так просто, что вспомогательная функция не будет сохранять код, хотя она может быть немного более читабельной. Если вы хотели один:

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

    ИЛИ

    использовать:

    "StringToTest".isDate();
    
    ответ дан rainabba, с репутацией 1937, 31.03.2017
  • 0 рейтинг

    Этот вариант 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)
    }
    
    ответ дан Greg ''Wildman'' Finzer, с репутацией 3015, 17.11.2015
  • 0 рейтинг
    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;
          }
    
    ответ дан Dhayalan, с репутацией 57, 16.01.2014
  • 0 рейтинг

    Эта функция проверяет строковую дату в числовых форматах, разделенных символом, e. г. дд / мм / гггг, мм / дд / гггг

    /*
    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");
    }
    
    ответ дан wanglabs, с репутацией 49, 25.08.2014
  • -1 рейтинг
    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

    ответ дан Dustin Poissant, с репутацией 1841, 20.11.2016