Обнаружение экземпляра даты «недействительной даты» в 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 и это поведение находится в стандарте, и это именно то, что я ищу.



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

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

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

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



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

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

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



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




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

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

или даже в ES6:

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



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

Реализация

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



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

angular.isDate(myDate);



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



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



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



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




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