Обнаружение экземпляра даты "недействительной даты" в 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 и проверить/подтвердить, является ли он действительным или нет. Решение Borgar делает это, но мне нужно проверить его в браузерах. Я также задаюсь вопросом, есть ли более элегантный способ.
  • Ash заставил меня подумать о том, что мой API не принимает экземпляры Date вообще, это было бы проще всего проверить.
  • Borgar предложил тестирование экземпляра Date, а затем тестирование значения времени Date. Если дата недействительна, значение времени NaN. Я проверил с ECMA-262, и это поведение находится в стандарте, и именно это я и ищу.

Ответы

Ответ 1

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

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

Ответ 2

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

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

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

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

Ответ 3

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

d instanceof Date && isFinite(d)

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

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

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

Ответ 4

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

Реализация

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

Ответ 5

кратчайший ответ для проверки действительной даты

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

Ответ 6

Вы можете просто использовать moment.js

Вот пример:

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

Раздел проверки в документации достаточно ясен.

Кроме того, следующие флаги разбора приводят к недопустимой дате:

  • overflow: переполнение поля даты, например, 13-й месяц, 32-й день месяца (или 29 февраля в непиковые годы), 367-й день года и т.д. переполнение содержит индекс недопустимой единицы для соответствия #invalidAt (см. ниже); -1 означает отсутствие переполнения.
  • invalidMonth: Недействительное имя месяца, например, момент ('Marbruary', 'MMMM');. Содержит недействительную строку месяца, иначе null.
  • empty: входная строка, которая не содержит ничего разборного, например момент ( "это вздор" ); Boolean.
  • Etc.

Источник: http://momentjs.com/docs/

Ответ 7

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

Даже если вы не хотите использовать виджет datepicker на своей странице в качестве элемента пользовательского интерфейса, вы всегда можете добавить свою библиотеку .js на свою страницу, а затем вызвать метод проверки, передав значение, которое вы хотите проверить в нем, Чтобы сделать жизнь еще проще, она берет строку как входную, а не объект 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 Date, представляющим строковое значение переданного. Если нет, это будет undefined.

Ответ 8

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

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

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

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

Ответ 9

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

Ответ 10

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

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

Ответ 11

вы можете проверить действительный формат txDate.value с помощью этой обрезки. если он был в некотором формате, то Date obejct не был установлен и возвращает null в dt.

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

И как @MiF предложил в кратчайшие сроки

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

Ответ 12

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

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

или даже в ES6:

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

Ответ 13

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

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

Ответ 14

Для проектов Angular.js вы можете использовать:

angular.isDate(myDate);

Ответ 15

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

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

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

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

Ответ 16

Ни один из этих ответов не работал у меня (проверен в 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

Ответ 17

Я видел некоторые ответы, которые очень близко подошли к этому маленькому фрагменту.

Способ 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'));

Ответ 18

Ни одно из вышеперечисленных решений для меня не помогло, что работала

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, что его недействительный

Ответ 19

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

Ответ 20

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

вот тест

input: "hahaha", output: false.

input: "29/2/2000", output: true.

input: "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;
    }
}

Ответ 21

Вдохновленный подход 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!";
}

Ответ 22

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

В результате получается следующее:

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

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

Ответ 23

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

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

Ответ 24

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

this getTime() Возвращает метод Не Число NaN, если оно недействительно

if(!isNaN(new Date("2012/25/255").getTime()))
  return 'valid date time';
  return 'Not a valid date time';

Ответ 25

Выбранный ответ превосходный, и я тоже его использую. Однако, если вы ищете способ подтверждения ввода даты пользователя, вы должны знать, что объект Date очень устойчив в отношении того, что может показаться недопустимыми аргументами построения в действительные. Следующий код unit test иллюстрирует точку:

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 not.  So, the secret to working with this version of 
  //isValidDate is to pass in dates as text strings... Hooboy
  //alert(d.toString());
});

Ответ 26

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

Ответ 27

Готовая функция, основанная на наилучшем ответе:

  /**
   * 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 not a date.
  }

  return isValid;
}

Ответ 28

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

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

Ответ 29

Я думаю, что некоторые из них - долгий процесс. Мы можем сократить его, как показано ниже:

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

Ответ 30

Для компонентов, основанных на 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)