Виявлення екземпляра дати "недійсна дата" в JavaScript


1493

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

18
Ви можете видалити оператор if, змінивши тіло функції на:return ( Object.prototype.toString.call(d) === "[object Date]" && !isNaN(d.getTime()) );
styfle

3
@styfle - здогадуйтесь, що це стиль перевага: мені зрозуміліше відокремлювати перевірку типу від логіки рівності.
orip

26
@orip дискурс - це саме те, що сильно відштовхується від питань. Будь ласка, зверніться до відповідних мета-тем, щоб дізнатись обґрунтування, що стоять за ним. Розміщення відповіді на власне питання у самому питанні суперечить політиці сайту. OTOH, подякувати за відповіді та мати "EDIT" у своїй відповіді є типовим пухом. Якщо ви хочете, щоб ви оцінили найкраще питання, щоб визначити вас як людину, яка не знає, що таке SO і як ним користуватися, і не бажає цього дізнатися - будьте моїм гостем.

14
@orip: Це не було "втрачено"; це все ще захаращує історію перегляду питання, якщо ви хочете його переглянути ще раз. Але це не належить до питання. При 37-ти реп. Ви повинні це знати.
Гонки легкості по орбіті

6
Будь ласка, припиніть редагувати війну. Правки в цьому питанні обговорюються на мета . Будь ласка, не редагуйте / відкидайте цю публікацію більше. Якщо ви не погоджуєтесь з попередніми редакціями / відкатами або маєте якісь коментарі щодо них, будь ласка, опублікуйте цю метамету, а не тут.
Лундін

Відповіді:


1301

Ось як я це зробив:

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] : Якщо вас не стосуються об'єкти дати з інших контекстів JS (зовнішні вікна, рамки чи рамки кадрів), ця більш проста форма може віддавати перевагу:

function isValidDate(d) {
  return d instanceof Date && !isNaN(d);
}

21
instanceof перерви між кадрами. Введення качок може працювати також чудово: validDate == d && d.getTime &&! IsNaN (d.getTime ()); - Оскільки питання стосується загальної корисної функції, я вважаю за краще бути більш суворим.
Боргар

11
@ Borgar, щойно знайшов мою відповідь: "Проблеми виникають, коли справа стосується сценаріїв у багатокадрових середовищах DOM. У двох словах, об'єкти масиву, створені в межах одного iframe, не діляться [[Prototype]] на масиви, створені в іншому iframe . Їх конструктори - це різні об'єкти, і тому і перевірки екземплярів, і конструкторів не вдається ".
Еш

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!
днгід

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()як неявно перетворити в число.


Спробуйте це в chrome - Object.prototype.toString.call (нова дата ("2013-07-09T19: 07: 9Z")). Він поверне "[date date]". Згідно з вами, отже, "2013-07-09T19: 07: 9Z" має бути дійсною датою. Але це не так. Ви можете перевірити це, знову ж таки, в хромі, виконавши var dateStr = new Date ("2013-07-09T19: 07: 9Z"); dateStr Він поверне недійсну дату.
Тінтін

2
@Tintin: ось що isFinite()- toString.call()це лише заміна instanceofчастини чеку
Крістоф

Чи буде порівняння з '[дата об’єкта] працювати з не-англійськими браузерами? Я сумніваюся в цьому.
Крістіанп

2
@kristianp насправді це, мабуть, є і, мабуть, навіть є частиною специфікації ECMAScript. Але так, це здається некрасивим.
бінкі

Для мене перший підхід - це найкращий варіант, хоча я не впевнений, чи є якась реальна перевага використання isFiniteнад ними 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
@Ali Це дійсний об’єкт дати. 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()))

2
Єдина проблема - якщо дата не має тип Date; ви отримуєте помилку JS.
Андрій

@Andrew вам потрібно створити об’єкт дати, і якщо у вас вже є об’єкт, то використовуйтеdate && !isNaN(date.getTime())
abhirathore2006

Це все ще дає помилку JS, якщо dateвона не типу Date. Наприклад: var date = 4; date && !isNaN(date.getTime());.
Андрій

@Andrew use date instanceof Date && !isNaN(date.getTime())
abhirathore2006

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: Недійсна назва місяця, наприклад, момент ("Marbruary", "MMMM"). Містить самий недійсний рядок місяця або нульове значення.
  • empty: Рядок введення, що не містить нічого проаналізованого, наприклад, момент ("це нісенітниця") ;. Булева.
  • І т.д.

Джерело: 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
Цей метод може бути надзвичайно повільним при обробці багатьох дат. У цих випадках краще використовувати регулярний вираз.
Grid Trekkor

2
Використання moment.js може бути простим, але це величезні витрати. Ця бібліотека ВЕЛИЧЕЗНА. Я підтримав вашу відповідь.
Мік

38

Хотілося б зазначити, що у віджета jQuery UI DatePicker є дуже хороший утилітний метод перевірки дати, який перевіряє формат та дійсність (наприклад, не допускаються дати 01.01.2013).

Навіть якщо ви не хочете використовувати віджет datepicker на своїй сторінці в якості елемента інтерфейсу, ви завжди можете додати його .js-бібліотеку на свою сторінку, а потім викликати метод валідатора, передаючи на нього значення, яке потрібно перевірити. Щоб зробити життя ще простішим, для введення даних використовується рядок, а не об’єкт дати JavaScript.

Дивіться: http://api.jqueryui.com/datepicker/

Він не вказаний як метод, але він є - як функція корисності. Знайдіть на сторінці "розбір" на сторінці, і ви знайдете:

$ .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
Оновлення за першу відповідь, що працює з форматами дат, які не є англійською / локальними.
сокира.

26

Мені дуже сподобався підхід Крістофа (але не вистачило репутації, щоб проголосувати за нього). Для мого використання я знаю, що у мене завжди буде об’єкт Date, тому я просто продовжив дату правильним () методом.

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

Тепер я можу просто написати це, і це набагато більш описово, ніж просто перевірка isFinite в коді ...

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

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

5
Це те саме @Borgar написав 2 роки тому ... Що нового ??
синюватий

11
Це два рядки замість некрасивих вкладених, якщо тверджень.
Cypher

17

ви можете перевірити дійсний формат txDate.value за допомогою цього скрипту. якщо він був у неправильному форматі, об'єкт Date не встановлений і повертає null до dt.

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

І як коротко запропоновано @ MiF's

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

isNaN (нова дата (...)) - простий і короткий метод
MiF

1
@MiF так, я оновлюю свою відповідь вашою пропозицією;) дякую
Yuseferi

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
Не впевнений, якщо я щось пропускаю, але чи не роблю нову дату () двічі безглуздо?
Джон

2
Останній не має нічого спільного з TypeScript. Це цілком дійсний JS.
hackel

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

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

(нова дата ("30.02.2014"). Дійсно () повертається правдою
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/…, щоб ви могли отримати помилкові істинні чи помилкові значення.
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 по 02.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

Я написав цю функцію. Передайте йому параметр рядка, і він визначить, чи є це дійсною датою чи ні, виходячи з цього формату "dd / MM / yyyy".

ось тест

вхід: "hahaha", вихід: false.

вхід: "29/2/2000", вихід: вірно.

вхід: "29.02.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;    
  }    
}

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

Але ... вищевикладені методи (@ Боргар та інші) вже перевіряють чинність цього типу ... Я не можу отримати проблему.
синюватий

Боргар ні - бачите власний коментар до своєї відповіді.
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;
};

2

Об'єкт дати для рядка є більш простим і надійним способом виявити, чи обидві поля є дійсною датою. Наприклад, якщо ви введете це поле "-------" у поле введення дати. Деякі з вищезазначених відповідей не спрацюють.

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

Вибрана відповідь відмінна, і я її також використовую. Однак якщо ви шукаєте спосіб перевірити введення дати користувача, вам слід пам’ятати, що об’єкт «Дата» дуже наполегливий щодо того, щоб зробити те, що може здатися недійсним аргументом конструкції, в допустимі. Наступний тестовий код блоку ілюструє точку:

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

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

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, тому вам, можливо, доведеться відняти один, щоб правильно його вирівняти.
Ярмарок

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

3
У запитанні було задано питання про те, як знайти недійсні екземпляри дати, а не рядки, а крім того: хто каже, що дату не можна обмежувати чимось іншим, ніж перекидання вперед?
Jon z

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)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.