Перевірте, чи є рядок значенням дати


207

Простий спосіб перевірити, чи значення є дійсною датою, чи будь-який відомий формат дати.

Наприклад , я маю значення 10-11-2009, 10/11/2009, 2009-11-10T07:00:00+0000які всі повинні бути визнані в якості значення дати, а значення 200, 10, 350, , які не повинні бути визнані в якості значення дати. Який найпростіший спосіб перевірити це, якщо це можливо навіть? Тому що часові позначки також будуть дозволені.


Відповіді:


41

Було б Date.parse()достатньо?

Див . Відповідну сторінку документації MDN .


24
Будьте обережні з цим, оскільки воно все одно поверне повернення за недійсні дати в лютому, наприклад: 2013-02-31
leojh

58
Ще одна причина, щоб бути обережними - розбирають числа як дати. Date.parse("4.3")є 986270400000.
Могспад

Я спробував загадку з обома вищезазначеними випадками "обережності": console.log (Date.parse ("2013-02-31")); console.log (Date.parse ("4.3")); і в обох випадках (у firefox) він повернув NaN, тому для мене Date.parse здається нормальним (я все-таки переважаю за тире та правильну довжину перед синтаксичним розбором).
Cloudranger

55
Вибачте @Asmor, це не правильна відповідь. Date.parse буде розбирати будь-який рядок з числом, в якому він є.
jwerre

11
Date.parse ("Моє ім'я 8") походить як 99662040000, що неправильно. Я використовував це і тепер страждаю.
Рохіт

250

Оновлення 2015 року

Це старе питання, але інші нові питання, такі як:

закрити як копії цього, тому я думаю, що тут важливо додати свіжу інформацію. Я пишу це, бо злякався, думаючи, що люди насправді копіюють і вставляють частину коду, розміщеного тут, і використовують його у виробництві.

Більшість відповідей тут або використовують деякі складні регулярні вирази, які відповідають лише деяким дуже специфічним форматам, і насправді роблять це неправильно (наприклад, відповідність 32 січня, не відповідаючи фактичній даті ISO, як рекламується - див. Демонстрацію ), або намагаються передати що-небудьDate конструктору та побажати найкращого.

Використання моменту

Як я пояснив у цій відповіді , зараз для цього доступна бібліотека: Moment.js

Це бібліотека для аналізу, валідації, маніпулювання та відображення дат у JavaScript, яка має набагато багатший API, ніж стандартні функції обробки дат JavaScript.

Це 12kB мінімізований / gzipped і працює в Node.js та інших місцях:

bower install moment --save # bower
npm install moment --save   # npm
Install-Package Moment.js   # NuGet
spm install moment --save   # spm
meteor add momentjs:moment  # meteor

Використовуючи Момент, ви можете бути дуже конкретними щодо перевірки дійсних дат. Іноді дуже важливо додати підказки щодо формату, який ви очікуєте. Наприклад, така дата, як 22.06.2015, виглядає як дійсна дата, якщо ви не використовуєте формат DD / MM / РРРР, у цьому випадку цю дату слід відхилити як недійсну. Є кілька способів, як ви можете сказати Моменту, який формат очікуєте, наприклад:

moment("06/22/2015", "MM/DD/YYYY", true).isValid(); // true
moment("06/22/2015", "DD/MM/YYYY", true).isValid(); // false

trueАргумент є тому зараз не буде намагатися розібрати вхід , якщо він не точно відповідати одному з форматів , що надаються (це має бути поведінка за умовчанням , на мій погляд).

Ви можете використовувати внутрішньо наданий формат:

moment("2015-06-22T13:17:21+0000", moment.ISO_8601, true).isValid(); // true

І ви можете використовувати кілька форматів як масив:

var formats = [
    moment.ISO_8601,
    "MM/DD/YYYY  :)  HH*mm*ss"
];
moment("2015-06-22T13:17:21+0000", formats, true).isValid(); // true
moment("06/22/2015  :)  13*17*21", formats, true).isValid(); // true
moment("06/22/2015  :(  13*17*21", formats, true).isValid(); // false

Дивіться: DEMO .

Інші бібліотеки

Якщо ви не хочете використовувати Moment.js, є й інші бібліотеки:

Оновлення 2016 року

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

Оновлення 2018 року

Сьогодні я рекомендую використовувати Люксон для маніпуляції датою / часом замість Моменту, який (на відміну від Моменту) робить увесь об’єкт непорушним, тому немає неприємних сюрпризів, пов'язаних із неявною мутацією дат.

Більше інформації

Дивитися також:

Серія статей Роб Гравель про бібліотеки розбору дат JavaScript:

Нижня лінія

Звичайно, кожен може спробувати винайти колесо, написати регулярний вираз (але, будь ласка, прочитайте ISO 8601 та RFC 3339, перш ніж це зробити) або зателефонувати до вбудовуваних конструкторів із випадковими даними, щоб проаналізувати повідомлення про помилки на кшталт 'Invalid Date'(Ви впевнені, що це повідомлення точно так само на всіх платформах? У всіх локалях? Надалі?) або ви можете скористатися випробуваним рішенням і використати свій час для його вдосконалення, а не заново винаходити. Усі перераховані тут бібліотеки є відкритим кодом, вільним програмним забезпеченням.


4
як саме слід це використовувати? moment("whatever 123").isValid()повертає true.
krivar

4
@krivar Найкраще використовувати його так: moment("06/22/2015", "DD/MM/YYYY", true).isValid();із чітко наданим очікуваним форматом дати та аргументом, що trueозначає чітку перевірку. Я оновив свою відповідь більше інформації та кращих прикладів.
rsp

2
Хоча те саме, але я перевіряю вхід користувача, і я не знаю очікуваного формату дати ...
Jan Van der Haegen

3
@JanVanderHaegen Якщо можна зробити припущення, що 3/4/5 є дійсною датою, і так це 1 квітня 2015 року, тоді я рекомендую додати ці формати (а можливо і набагато більше) до явного списку підтримуваних форматів. Зауважте, що 3/4/5, які ви згадали, неоднозначно без явного формату.
rsp

3
Це могла б бути найкращою та доглянутою відповіддю, яку я бачив на SO
Phil3992

63

Ось як я вирішив цю проблему в додатку, над яким я зараз працюю:

оновлено на основі відгуків від krillgar:

var isDate = function(date) {
    return (new Date(date) !== "Invalid Date") && !isNaN(new Date(date));
}

5
Мені потрібно було повернутися (нова дата (дата)). ToString ()! == "Недійсна дата" для вузла. Також зверніть увагу на це? true: false - це зайве. просто повернення виразу тут буде достатньо.
domenukk

У IE8 new Date(date)не вказано "Недійсна дата".
krillgar

13
Це не є гарною відповіддю. new Date(date) !== "Invalid Date"буде завжди повертати справжнє , так як ліве вираз повертає об'єкт Date з TIMEVALUE від NaN , яке ніколи не може бути ===в рядок. Використання =="працює" за рахунок перетворення типів. Але оскільки синтаксичний аналіз рядків дат все ще залежить від реалізації, покладаючись на це для аналізу випадкових форматів, ми серйозно помилилися.
RobG

4
нова дата ("469") результатів у вівторок, 01 січня 469 00:00:00 GMT + 0200 (EET)
Dan Ochiana

3
Це схоже на помилково прийняту правильну відповідь. isDate('Mac OS X 10.14.2')тут повертається правда.
БредСтелл

24

new Date(date) === 'Invalid Date'працює лише у Firefox та Chrome. IE8 (той, який я маю на своїй машині для тестування) дає NaN.

Як було зазначено у прийнятій відповіді, Date.parse(date)також буде працювати для чисел. Тож, щоб обійти це, ви також можете перевірити, що це не число (якщо це щось, що ви хочете підтвердити).

var parsedDate = Date.parse(date);

// You want to check again for !isNaN(parsedDate) here because Dates can be converted
// to numbers, but a failed Date parse will not.
if (isNaN(date) && !isNaN(parsedDate)) {
    /* do your work */
}

2
Я розумію, що це через пару років, але isNanце не є функцією; неправильна справа в першій інстанції.
Тім Льюїс

Не працює. Якщо dateце так Foostreet 1, ваш стан оцінюється як справжній.
Фабіан Піконе

9

Як щодо чогось подібного? Він перевірить, чи це об'єкт дати або рядок дати:

function isDate(value) {
    var dateFormat;
    if (toString.call(value) === '[object Date]') {
        return true;
    }
    if (typeof value.replace === 'function') {
        value.replace(/^\s+|\s+$/gm, '');
    }
    dateFormat = /(^\d{1,4}[\.|\\/|-]\d{1,2}[\.|\\/|-]\d{1,4})(\s*(?:0?[1-9]:[0-5]|1(?=[012])\d:[0-5])\d\s*[ap]m)?$/;
    return dateFormat.test(value);
}

Я мушу зазначити, що це не тестує на рядки, відформатовані ISO, але, маючи трохи більше роботи з RegExp, ви повинні бути хорошими.


7

Жодна з відповідей тут не стосується перевірки того, чи недійсна дата, наприклад, 31 лютого. Ця функція вирішує цю проблему, перевіряючи, чи повернувся місяць еквівалентний початковому місяцю та переконавшись, що був представлений дійсний рік.

//expected input dd/mm/yyyy or dd.mm.yyyy or dd-mm-yyyy
function isValidDate(s) {
  var separators = ['\\.', '\\-', '\\/'];
  var bits = s.split(new RegExp(separators.join('|'), 'g'));
  var d = new Date(bits[2], bits[1] - 1, bits[0]);
  return d.getFullYear() == bits[2] && d.getMonth() + 1 == bits[1];
} 

Оскільки питання не більше, щоб перевірити, чи є рядок "дійсною" датою, а просто перевірка, що вона є строком, представляє формат дати.
Тизер

@Thizzer хороший момент. Я не заперечував би з виправленням, але перечитуючи ваше запитання, я наткнувся, тому що ви говорите, що 10 не повинно підтверджувати, але потрібно дозволити часові позначки.
гаразд каже, Відновіть Моніку

xD навіть не помічав цього, питання з моїх попередніх днів із датою / часовими позначками. Спробую відредагувати це питання пізніше сьогодні.
Thizzer

чому місяць-1, а потім місяць + 1?
Kapil Raghuwanshi

@KapilRaghuwanshi Дати JavaScript використовують нульовий місяць, тому вам потрібно відняти 1, щоб створити належну дату, і додайте 1, щоб перевірити, чи це еквівалентно початковому місяцю
гаразд, - Відновлення Моніки

5

Використовуйте регулярне вираження, щоб перевірити його.

isDate('2018-08-01T18:30:00.000Z');

isDate(_date){
        const _regExp  = new RegExp('^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]+)?(Z)?$');
        return _regExp.test(_date);
    }

4

Посилаючись на всі вищезазначені коментарі, я прийшов до рішення.

Це працює, якщо Dateпередане у форматі ISO або потрібно маніпулювати для інших форматів.

var isISO = "2018-08-01T18:30:00.000Z";

if (new Date(isISO) !== "Invalid Date" && !isNaN(new Date(isISO))) {
    if(isISO == new Date(isISO).toISOString()) {
        console.log("Valid date");
    } else {
        console.log("Invalid date");
    }
} else {
    console.log("Invalid date");
}

Ви можете грати тут на JSFiddle.


1
Це рішення найкраще працювало для мене, оскільки рядки дати, які підтримує моє додаток, мають формат YYYY-MM-DD, тому тривіально додавати T00:00:00.000Zта використовувати це рішення для перевірки дійсних рядків.
пришвидшити

для javascript це працює, але як його використовувати в машинопис.?
Се

3

Ось вдосконалена функція, яка використовує лише Date.parse():

function isDate(s) {
    if(isNaN(s) && !isNaN(Date.parse(s)))
        return true;
    else return false;
}

Примітка: Date.parse () буде аналізувати номери: наприклад Date.parse(1), поверне дату. Тому тут ми перевіряємо, чи sне є число, чи це дата.


1
це не працює, оскільки проходження 'тесту 2' пройде як справжня дата. перевірена в останній версії хрому
користувач1751287

2

Я б це зробив

var myDateStr= new Date("2015/5/2");

if( ! isNaN ( myDateStr.getMonth() )) {
    console.log("Valid date");
}
else {
    console.log("Invalid date");
}

Пограйте тут


2
Це не працює в поточному Chrome, можливо, в інших браузерах. Я змінив наданий рядок, EXAMPLE STRING 12345і він повертає "Дійсна дата".

1

Ось мінімалістична версія.

var isDate = function (date) {
    return!!(function(d){return(d!=='Invalid Date'&&!isNaN(d))})(new Date(date));
}

1
Досі не працює для мого прикладу:isDate("  1")
Томаш

@Tom Ви повинні перевірити, чи містить значення символів пробілів, перш ніж визначати, чи це дата. Ваша проблема - це окремий випадок, який повинен вирішуватися логікою вашого контролера.
Містер Polywhirl

1
Перевірка білих пробілів не повинна бути обов'язковою, оскільки рядок 1 січня 2020 року є дійсною датою, яка містить пробіл. Ваш метод цього не враховує.
Крістін Уолш

1

Ця функція дзвінка працює чудово, повертає справжню для дійсної дати. Обов’язково телефонуйте, використовуючи дату у форматі ISO (yyyy-mm-dd або yyyy / mm / dd):

function validateDate(isoDate) {

    if (isNaN(Date.parse(isoDate))) {
        return false;
    } else {
        if (isoDate != (new Date(isoDate)).toISOString().substr(0,10)) {
            return false;
        }
    }
    return true;
}

1
Це добре, але це не відповідає на питання повністю. Зокрема, це не працює для "2009-11-10T07: 00: 00 + 0000", одного з наведених прикладів.
амадан

Не думайте, що це працює так, як слід підтвердитиDate ('2016-12-30T08: 00: 00.000Z') // false
Хосе Браун

Незалежно від того, працює це чи ні, це може бути спрощено якreturn !isNaN(Date.parse(isoDate)) || isoDate == new Date(isoDate).toISOString().substr(0,10);
Мішель Юнг

1

Я знаю, що це давнє запитання, але я зіткнувся з тією ж проблемою і побачив, що жодна з відповідей не спрацювала належним чином - конкретно, відмиваючи цифри (1200,345 тощо) з дат, що є оригінальним питанням. Ось досить неортодоксальний метод, про який я міг би придумати, і він, здається, працює. Будь ласка, зазначте, чи є випадки, коли це не вдасться.

if(sDate.toString() == parseInt(sDate).toString()) return false;

Це рядок для відсіву чисел. Таким чином, вся функція може виглядати так:

function isDate(sDate) {  
  if(sDate.toString() == parseInt(sDate).toString()) return false; 
  var tryDate = new Date(sDate);
  return (tryDate && tryDate.toString() != "NaN" && tryDate != "Invalid Date");  
}

console.log("100", isDate(100));
console.log("234", isDate("234"));
console.log("hello", isDate("hello"));
console.log("25 Feb 2018", isDate("25 Feb 2018"));
console.log("2009-11-10T07:00:00+0000", isDate("2009-11-10T07:00:00+0000"));


1
console.log("hello 1 ", isDate("hello 1 "));повертається правдою
Іван

ти правий! у вас є рішення? До сих пір я думаю, що жодна з відповідей тут справді не відповіла належним чином на це питання!
peekolo

"100%", відсоток, повертається правдою
toddmo

0

чи добре перевірити, чи доступна для об’єкта функція, пов’язана з датою, щоб виявити, чи це об'єкт «Дата» чи ні?

подібно до

var l = new Date();
var isDate = (l.getDate !== undefined) ? true; false;

0

Ось як я закінчую це робити. Це охопить не всі формати. Ви повинні відповідно підкоригуватися. У мене є контроль над форматом, тому він працює для мене

function isValidDate(s) {
            var dt = "";
            var bits = [];
            if (s && s.length >= 6) {
                if (s.indexOf("/") > -1) {
                    bits = s.split("/");
                }
                else if (s.indexOf("-") > -1) {
                    bits = s.split("-");
                }
                else if (s.indexOf(".") > -1) {
                    bits = s.split(".");
                }
                try {
                    dt = new Date(bits[2], bits[0] - 1, bits[1]);
                } catch (e) {
                    return false;
                }
                return (dt.getMonth() + 1) === parseInt(bits[0]);
            } else {
                return false;
            }
        }

-1

Гаразд, це старе питання, але я знайшов інше рішення, перевіряючи рішення тут. Для мене працює, щоб перевірити, чи функція getTime () присутня в об'єкті дати:

const checkDate = new Date(dateString);

if (typeof checkDate.getTime !== 'function') {
  return;
}

-1

document.getElementById('r1').innerHTML = dayjs('sdsdsd').isValid()

document.getElementById('r2').innerHTML = dayjs('2/6/20').isValid()
<script src="https://unpkg.com/dayjs@1.8.21/dayjs.min.js"></script>

<p>'sdsdsd' is a date: <span id="r1"></span></p>
<p>'2/6/20' is a date: <span id="r2"></span></p>

Полегшена бібліотека готова для вас: Day.js


1
Це в основному реклама на StackOverflow, утримуйтесь від цього.
c4sh

-4
SimpleDateFormat sdf = new SimpleDateFormat(dateFromat);
sdf.setLenient(false);

За замовчуванням для цього встановлено значення TRUE. Тож навіть рядки неправильного формату повертають хороші значення.

Я використав це приблизно так:

SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
formatter.setLenient(false);
String value = "1990/13/23"; 

try {
      Date date = formatter.parse(value);
      System.out.println(date);
    }catch (ParseException e) 
  {
    System.out.println("its bad");
  }

5
... javascript ?!
artparks

-5

Спробуйте це:

if (var date = new Date(yourDateString)) {
    // if you get here then you have a valid date       
}

6
Це не працює для мене. Спочатку var в умові не розбирається, але якщо ви вилучите це і спробуйте щось подібне: if (date = new Date ("сміття")) {alert (дата); } Навіть якщо дата є сміттям, сповіщення все одно буде виконуватись, оскільки функція Date поверне "Недійсна дата" (принаймні для firefox), тому умова оцінюється як істинна. Я думаю, якщо деякі веб-переглядачі повернуть нулі на недійсну дату, то це буде працювати в цих браузерах. Тут може бути непослідовність браузера.
Cloudranger
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.