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


Answers

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

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

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

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

Question

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



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



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

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



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

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

или даже в ES6:

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



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



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

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




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

angular.isDate(myDate);



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



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

Реализация

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



function isValidDate(date) {
  return !! (Object.prototype.toString.call(date) === "[object Date]" && +date);
}



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

этот getTime() возвращает не число NaN когда недействительно

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



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

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

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

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



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



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



Хотелось бы упомянуть, что виджет jQuery UI DatePicker имеет очень полезный метод проверки валидности даты, который проверяет формат и достоверность (например, даты, датированные 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 Date, представляющим строковое значение переданной строки. Если нет, это будет неопределенным.