Проверьте, является ли строка значением даты

207

Какой простой способ проверить, является ли значение допустимой датой, разрешен любой известный формат даты.

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

Thizzer
источник
4
Дубликат: stackoverflow.com/questions/1353684/...
Даан

Ответы:

41

Хватило бы Date.parse()?

См. Относительную страницу документации MDN .

Asmor
источник
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.

Это миниатюрный / gzipped 12kB и работает в 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, выглядит как действительная дата, если вы не используете формат ДД / ММ / ГГГГ, и в этом случае эта дата должна быть отклонена как недействительная. Есть несколько способов, как вы можете сказать Момент, какой формат вы ожидаете, например:

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

Смотрите: ДЕМО .

Другие библиотеки

Если вы не хотите использовать Moment.js, есть и другие библиотеки:

Обновление 2016

Я создал модуль immoment, который похож на (подмножество) Момент, но без неожиданностей, вызванных мутацией существующих объектов (см. Документацию ).

2018 Обновление

Сегодня я рекомендую использовать Luxon для манипуляции с датой / временем вместо Moment, что (в отличие от Moment) делает все объекты неизменяемыми, поэтому нет никаких неприятных сюрпризов, связанных с неявной мутацией дат.

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

Смотрите также:

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

Нижняя граница

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

RSP
источник
4
как именно это использовать? moment("whatever 123").isValid()возвращается true.
Кривар
4
@krivar Лучше всего использовать это так: moment("06/22/2015", "DD/MM/YYYY", true).isValid();с явно заданным форматом даты и с аргументом, trueозначающим строгую проверку. Я обновил свой ответ, добавив больше информации и лучших примеров.
rsp
2
То же самое, но я проверяю пользовательский ввод и не знаю ожидаемого формата даты ...
Ян Ван дер Хейген
3
@JanVanderHaegen Если можно сделать предположение, что 3/4/5 является действительной датой, как и 1 апреля 2015 г., я бы рекомендовал добавить эти форматы (и, возможно, намного больше) в явный список поддерживаемых форматов. Обратите внимание, что 3/4/5, который вы упомянули, неоднозначен без явного формата.
RSP
3
Это мог бы быть лучший и наиболее ухоженный ответ, который я видел на SO
Phil3992
63

Вот как я решил эту проблему в приложении, над которым я сейчас работаю:

обновляется на основе отзывов крильгара:

var isDate = function(date) {
    return (new Date(date) !== "Invalid Date") && !isNaN(new Date(date));
}
Нил Жирарди
источник
5
Мне нужно было вернуть (новая дата (дата)). ToString ()! == «Неверная дата» для узла. Также обратите внимание, что? истина: ложь избыточна. простого возврата выражения здесь будет достаточно.
Доменукк
В IE8 new Date(date)не выдает «Неверная дата».
Крильгар
13
Это не хороший ответ. всегдаnew Date(date) !== "Invalid Date" будет возвращать true, поскольку левое выражение будет возвращать объект Date со значением времени NaN , которое никогда не может быть строкой. Использование «работает» из-за преобразования типов. Но так как синтаксический анализ строк даты все еще в значительной степени зависит от реализации, мы полагаем, что анализ синтаксиса произвольных форматов имеет серьезные недостатки. =====
RobG
4
Новая Дата ("469") приводит к вторнику 01 января 469 00:00:00 по Гринвичу + 0200 (EET)
Дан Очиана
3
Это похоже на ложно принятый правильный ответ. isDate('Mac OS X 10.14.2')возвращает истину здесь.
BradStell
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 */
}
krillgar
источник
2
Я понимаю, что это пара лет спустя, но isNanэто не функция; неправильный регистр в первой инстанции.
Тим Льюис
Не работает. Если dateэто так Foostreet 1, ваше состояние оценивается как истинное.
Фабиан Пикон
9

Как насчет этого? Он проверит, является ли это объектом Date или строкой даты:

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 вы должны быть хорошими.

jwerre
источник
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];
} 
икей говорит восстановить монику
источник
Потому что вопрос не в том, чтобы проверить, является ли строка «действительной» датой, а в том, чтобы проверить, является ли строка строкой формата даты.
Тиззер
@ Это хорошая идея. Я не возражаю против исправления, но перечитывая ваш вопрос, я озадачен, потому что вы говорите, что 10 не должно проверяться, но что отметки времени должны быть разрешены.
ykay говорит восстановить Монику
xD даже не заметил этого, вопрос из моих предыдущих дней с указанием даты / времени. Я постараюсь изменить вопрос позже сегодня.
Тиззер
почему месяц-1, а затем месяц + 1?
Капил Рагхуванши
@KapilRaghuwanshi в датах javascript используется месяц, основанный на нуле, поэтому вам необходимо вычесть 1, чтобы создать правильную дату, и добавить 1, чтобы проверить, эквивалентен ли он исходному месяцу
ykay говорит восстановить Monica
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);
    }
lpradhap
источник
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не является ли число, если это дата.

A-Sharabiani
источник
1
это не работает, так как прохождение теста 2 пройдет как истинную дату. протестировано в последней версии Chrome
user1751287
2

Я бы сделал это

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

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

Играть здесь

kiranvj
источник
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 Вам следует проверить, содержит ли значение символы пробела, прежде чем определять, является ли это датой. Ваша проблема - это особый случай, который должен обрабатываться логикой вашего контроллера.
г-н Поливирл,
1
Проверка символов пробела не требуется, так как строка 1 января 2020 года является действительной датой, содержащей пробел. Ваш метод не учитывает это.
Кирстин Уолш
1

Эта вызываемая функция работает отлично, возвращает true для правильной даты. Обязательно звоните, используя дату в формате ISO (гггг-мм-дд или гггг / мм / дд):

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», одного из приведенных примеров.
амадан
Не думайте, что это работает так, как это должно происходить validateDate ('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"));

peekolo
источник
1
console.log("hello 1 ", isDate("hello 1 "));возвращается истина
Джон
Ты прав! У тебя есть решение? До сих пор я думаю, что ни один из ответов здесь действительно не отвечал на вопрос должным образом!
peekolo
«100%», процент, возвращает истину
toddmo
0

Можно ли проверить, доступна ли функция, связанная с датой, для объекта, чтобы определить, является ли он объектом Date или нет?

лайк

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;
            }
        }
kheya
источник
-1

Хорошо, это старый вопрос, но я нашел другое решение при проверке решений здесь. Для меня работает проверить, присутствует ли функция getTime () на объекте date:

const checkDate = new Date(dateString);

if (typeof checkDate.getTime !== 'function') {
  return;
}
m.steini
источник
-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
Это не работает для меня. Сначала переменная в условии не анализируется, но если вы удалите ее и попробуете что-то вроде этого: if (date = new Date ("мусор")) {alert (date); } Даже если дата является мусорной, предупреждение все равно будет выполнено, так как функция Date вернет «Недопустимую дату» (по крайней мере для firefox), поэтому условие оценивается как истинное. Я предполагаю, что если некоторые браузеры возвращают нуль в недопустимую дату, то это будет работать в этих браузерах. Здесь может быть несовместимость браузера.
Cloudranger