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

1494

Я хотел бы сказать разницу между действительными и недействительными объектами даты в 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 делает это, но мне нужно протестировать его в разных браузерах. Мне также интересно, есть ли более элегантный способ.
  • Эш заставил меня задуматься о том, чтобы мой API вообще не принимал Dateэкземпляры, это будет проще всего проверить.
  • Боргар предложил проверить Dateэкземпляр, а затем проверить Dateзначение времени. Если дата недействительна, значение времени равно NaN. Я проверил с ECMA-262, и это поведение в стандарте, который именно то, что я ищу.
orip
источник
18
Вы можете удалить оператор if, изменив тело функции на:return ( Object.prototype.toString.call(d) === "[object Date]" && !isNaN(d.getTime()) );
styfle
3
@styfle - угадайте, что это предпочтение стиля: я считаю более понятным отделить проверку типа от логики равенства.
orip
26
Дискурс @orip - это именно то, что крайне обескураживает в вопросах. Пожалуйста, обратитесь к соответствующим мета-темам, чтобы узнать причину этого. Размещение ответа на собственный вопрос в самом вопросе противоречит политике сайта. OTOH, благодарность за ответы и наличие «РЕДАКТИРОВАТЬ» в вашем ответе - типичный пух. Если вы хотите, чтобы ваш вопрос с самым высоким рейтингом идентифицировал вас как человека, который не знает, что такое SO и как его использовать, и не хочет изучать это, - будьте моим гостем.
14
@orip: это не было "потеряно"; он все еще захламляет историю изменений вопроса, если вы хотите увидеть его снова. Но это не относится к вопросу. На 37k репутации вы должны знать это.
Гонки легкости на орбите
6
Пожалуйста, прекратите редактировать войну. Правки по этому вопросу обсуждаются на мета . Пожалуйста, не редактируйте / откатывайте этот пост дальше. Если вы не согласны с предыдущими изменениями / откатами или у вас есть какие-либо комментарии относительно них, пожалуйста, пишите в этой мета-ветке, а не здесь.
Лундин

Ответы:

1304

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

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);
}
Боргар
источник
21
instanceof ломается через кадры. Утиная печать тоже может работать отлично: validDate == d && d.getTime &&! IsNaN (d.getTime ()); - Поскольку вопрос касается общей функции полезности, я предпочитаю быть более строгим.
Боргар
11
@Borgar, только что нашел мой ответ: «Проблемы возникают, когда речь идет о сценариях в многокадровых средах DOM. В двух словах, объекты Array, созданные в одном iframe, не разделяют [[Prototype]] с массивами, созданными в другом iframe. Их конструкторы - это разные объекты, поэтому и проверки instanceof, и проверки конструктора завершаются неудачно. "
Пепел
64
вам даже не нужно d.getTimeпростоisNan(d)
TecHunter
8
Может быть упрощена , как это:d instanceof Date && !isNaN(d.getTime())
Zorgatone
5
Спасибо за ответ, но я хочу подчеркнуть комментарии @Borgar и @blueprintChris: если я, например, проанализирую цифру, 1у меня все равно будет действительная дата, в результате Mon Jan 01 2001 00:00:00которой действительно будет дата, однако для целей моего приложения она совершенно бесполезна , Таким образом, по крайней мере, в моем случае требуется дополнительная проверка ввода. Этот ответ подтверждает, а dateObjectне Date!
18:00
264

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

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

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

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

ясень
источник
119
-1 Не знаю, почему это так много голосов, Date.parseзависит от реализации и определенно не заслуживает доверия для анализа общих строк даты. Нет единого формата, который правильно анализируется в популярных браузерах, тем более во всех используемых (хотя в конечном итоге формат ISO8601, указанный в ES5, должен быть в порядке).
RobG
1
Если вы используете, new Date('foo')это в основном эквивалентно Date.parse('foo')методу. Смотрите: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Так что, как сказал @RobG, это относится и к нему.
golddragon007
2
Этот тест потерпит неудачу в Chrome. Например, Date.parse ('AAA-0001') в Chrome дает мне номер.
Ник
не удалось ... определить все числовые значения
Hos Mercury
109

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

d instanceof Date && isFinite(d)

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

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

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

Christoph
источник
Попробуйте это в chrome - Object.prototype.toString.call (новая дата («2013-07-09T19: 07: 9Z»)). Он вернет «[дата объекта]». Поэтому, по вашему мнению, «2013-07-09T19: 07: 9Z» должна быть действительной датой. Но это не так. Вы можете проверить это снова в chrome, выполнив var dateStr = new Date ("2013-07-09T19: 07: 9Z"); dateStr Возвращает недопустимую дату.
Тинтин
2
@Tintin: это то, что isFinite()для - toString.call()только замена для instanceofчасти проверки
Кристоф
Будет ли сравнение с «[дата объекта]» работать с неанглийскими браузерами? Я сомневаюсь в этом.
Кристианп
2
@kristianp на самом деле это, вероятно, будет и, вероятно, даже является частью спецификации ECMAScript. Но, да, это выглядит некрасиво.
Бинки
Для меня первый подход здесь - самый лучший вариант, хотя я не уверен, есть ли какое-то реальное преимущество использования isFiniteover isNaN(оба отлично работают Date(Infinity)). Кроме того, если вы хотите , состояние противоположное, это становится немного проще: if (!(date instanceof Date) || isNaN(date)).
Андрей
86

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

Реализация

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
Эш Кларк
источник
28
isNaNболее явный способ проверить NaN
orip
1
И, тем не менее, вы всегда найдете людей, пишущих свои собственные версии :) documentcloud.github.com/underscore/docs/…
Эш Кларк
4
так как я уважаю underscore.js, это вызвало некоторые исследования. isNaN("a") === true, пока ("a" !== "a") === false. Об этом стоит подумать. +1
orip
8
Я проверил производительность для 3 основных решений, которые я нашел здесь. Поздравляю, вы победитель! jsperf.com/detecting-an-invalid-date
zVictor
2
@ Али Это допустимый объект даты. new Date("02-31-2000") // Thu Mar 02 2000 00:00:00 GMT+0000 (GMT Standard Time), Если вы передаете строку в конструктор даты, вы должны передать стандартизированную строку, чтобы получить надежный результат. В частности, «Строка должна быть в формате, распознаваемом методом Date.parse ()». developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Эш Кларк
71

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

if(!isNaN(date.getTime()))
abhirathore2006
источник
2
Единственная проблема заключается в том, что дата не имеет типа Date; Вы получаете ошибку JS.
Андрей
@ Андрею нужно создать объект даты, и если у вас уже есть объект, используйтеdate && !isNaN(date.getTime())
abhirathore2006
Это все еще дает вам ошибку JS, если dateне имеет типа Date. Например: var date = 4; date && !isNaN(date.getTime());.
Андрей
@ date instanceof Date && !isNaN(date.getTime())
Andrew
3
Правильно, как и другие ответы от 8 лет назад. : P stackoverflow.com/a/1353945/2321042
Эндрю
45

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

Вот пример:

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

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

А также, следующие флаги синтаксического анализа приводят к неверной дате:

  • overflow: Переполнение поля даты, например, 13-го месяца, 32-го дня месяца (или 29-го февраля для не високосных годов), 367-го дня года и т. Д. Переполнение содержит индекс недопустимой единицы соответствовать #invalidAt (см. ниже); -1 означает отсутствие переполнения.
  • invalidMonth: Неверное название месяца, например, момент («Март», «ММММ»); Содержит недопустимую строку месяца, либо ноль.
  • empty: Входная строка, которая не содержит ничего доступного для анализа, например момент («это чушь»); Boolean.
  • И т.п.

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

Ив М.
источник
6
Лучшее решение, чрезвычайно простое в реализации, работает с любым форматированием (в моем случае это dd / MM / yyyy), также знает високосные годы и не конвертирует недопустимые даты (например, 29.02.2015) в действительные (т.е. 30/03/2015). Чтобы проверить дату в формате dd / MM / yyyy, я просто должен был использоватьmoment("11/06/1986", "DD/MM/YYYY").isValid();
Рафаэль Мерлин
3
Это использование момента было объявлено устаревшим :(
Джеймс Самнерс,
2
Это использование не было амортизировано. Момент вызова (ввод) без форматной строки амортизируется (если вход не отформатирован в формате ISO).
Чет
2
Этот метод может быть очень медленным при обработке многих дат. Лучше использовать регулярные выражения в этих случаях.
Сетка Треккор
2
Использование moment.js может быть простым, но это огромные накладные расходы. Эта библиотека огромна. Я понизил твой ответ.
Мик
38

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

Мэтт Кэмпбелл
источник
3
Upvote для того, чтобы быть первым ответом, работающим с не английскими / локальными форматами даты.
топор.
26

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

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

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

d = new Date(userDate);
if (d.valid()) { /* do stuff */ }
broox
источник
10
Продление прототипа? Это большой JavaScript-нет-нет!
Джасдип Халса
Апвоттинг из-за isFiniteсработал у меня отлично. Но да, бессмысленно расширять прототип. !isFiniteна Dateпоймать тот факт, что Dateесть Invalid Date. Также стоит отметить мой контекст внутри узла.
Staghouse
23
// check whether date is valid
var t = new Date('2011-07-07T11:20:00.000+00:00x');
valid = !isNaN(t.valueOf());
faridz
источник
5
То же самое @Borgar написал 2 года назад ... Что нового ??
голубоватое
11
Это две строки вместо уродливых вложенных операторов if.
Cypher
17

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

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

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

 if(isNaN(new Date(...)))
Yuseferi
источник
isNaN (новая дата (...)) - простой и короткий метод
MiF
1
@MiF да, я обновляю свой ответ твоим предложением;) спасибо
Юсефери
16

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

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

Цзинго Яо
источник
strне используется
Самис
12

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

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

или даже в ES6:

Date.prototype.isValid = d => !isNaN(Date.parse(d));
Себастьен Х.
источник
1
Из MDN: «Метод Date.parse () анализирует строковое представление даты и возвращает количество миллисекунд с 1 января 1970 года, 00:00:00 UTC или NaN ...». Функция возвращает целое число или NaN. Затем функция isNaN () выдаст чистое логическое значение, сообщающее вам, было ли исходное значение допустимым объектом даты или нет. Этого достаточно для выборочной проверки, но приведенный выше пример затем присоединяет этот метод к объекту Date, чтобы сделать функциональность легко доступной и читаемой во всей вашей программе.
Макс Уайлдер
если d - логическое значение, вы получите 0 или 1, что не является Nan !!
davcup
@davcup только что протестировал с помощью Date.parse(true), я правильно получаю NaN.
Себастьян Х.
12

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

JavaScript способ:

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

TypeScript способ:

const isValidDate = dateObject => new Date(dateObject ).toString() !== 'Invalid Date';
isValidDate(new Date('WTH'));
Джейсон Фолья
источник
1
Не уверен, что я что-то упускаю, но не делаю ли я новый Date () дважды бессмысленно?
Джон
2
Последний не имеет ничего общего с TypeScript. Это совершенно справедливо JS.
Хакель
9

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

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

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

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

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

new Date('foo') === 'Invalid Date'; //is false
user1296274
источник
5
Я считаю, что это зависит от браузера.
barrypicker
@barrypicker Что вы имеете в виду, это зависит от браузера?
Аджил О.
Вы можете сделать: `${new Date('foo')}` === 'Invalid Date'
Даниэле Врут
9

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

angular.isDate(myDate);
Ник тарас
источник
3
Это возвращает истину при тестировании объекта даты, который был инициализирован с недопустимой датой.
дчхетри
6

Ни один из этих ответов не сработал для меня (проверено в 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
источник
(новая дата ('30.02.2014')). valid () возвращает true
Andre Figueiredo
1
Прошло некоторое время с тех пор, как я ответил на это, но вам могут понадобиться оба условия возврата, в том числе&& value.split('/')[0] == (d.getMonth()+1);
Dex
Использование new Date('string date')эквивалентно Date.parse('string date'), см .: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…, так что вы можете получить ложные значения true или false.
golddragon007
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, что он недействителен

Джон
источник
3
Хорошо, но это проверяет, является ли строка датой в формате M / D / Y, а не «разницей между действительными и недействительными объектами даты». Это не совсем то, о чем идет речь.
Боргар
причина, по которой он проверяется на соответствие формату, состоит в том, чтобы проверить, изменилась ли дата после анализа
Джон
Разве ОП не запрашивает метод для возврата логического значения, а не отформатированной строки?
barrypicker
1
Пример кода возвращает логическое значение, форматирование играет роль в тестировании некоторых недопустимых случаев.
Джон
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;
}
Майкл Гольдшмидт
источник
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;
    }
}
Ясин
источник
4

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

function isValidDate(d)
{
  try
  {
    d.toISOString();
    return true;
  }
  catch(ex)
  {
    return false;    
  }    
}
SAAJ
источник
1
Кажется, это единственная функция, которая выдает ошибку по определению ECMA-262. 15.9.5.43 Date.prototype.toISOString () Эта функция возвращает значение String, представляющее экземпляр во времени, представленный этим объектом Date. Формат строки - это формат строки даты и времени, определенный в 15.9.1.15. Все поля присутствуют в строке. Часовой пояс всегда UTC, обозначается суффиксом Z. Если значение времени этого объекта не является конечным числом, возникает исключение RangeError.
Генри Лю
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
источник
Но ... методы выше (@ Borgar's и другие) уже проверяют этот тип достоверности ... Я не могу понять проблему.
голубоватое
У Боргара нет - см. Его собственный комментарий к его ответу.
EML
1
Это решение работает только тогда, когда ваша страна использует dd/MM/yyyyобозначения. Кроме того, он возвращает, trueкогда он действителен, а 'Invalid date!'если нет, лучше вернуть только 1 тип.
A1rPun
3

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

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

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

  var time = input.getTime();
  return time === time;
};
zVictor
источник
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}.');
кам
источник
2

Для компонентов даты на основе 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)
Денис Рыжков
источник
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
источник
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
источник
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;
}
Зон
источник
2

Простое и элегантное решение:

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

прозвание
источник
1
date.getDate() == dayнедостаточно, чтобы определить, является ли дата действительной. Исходный формат даты будет возвращать недопустимую дату в некоторых реализациях независимо от того, является ли дата действительной или нет. Также "1970-01-01 00:00", если проанализировано правильно, вернет false (т.е. Boolean(+new Date("1970-01-01"))возвращает false).
RobG
ВНИМАНИЕ: Это не будет работать в Safari
Vigrant
Он будет работать в Safari, если вы используете формат. const date = new Date(year, month, day); Обратите внимание, что таким образом месяц проиндексирован на 0, поэтому вам, возможно, придется вычесть один, чтобы правильно выстроить его.
Vigrant
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
источник
3
Был задан вопрос о том, как найти недопустимые экземпляры Date, а не строки и, кроме того: кто сказал, что дата не может быть разделена чем-то иным, кроме косой черты?
Jon Z