Regex для проверки даты в PHP с использованием формата в формате ГГГГ-ММ-ДД

Я пытаюсь сделать валидатор регулярных выражений даты. Проблема, с которой я сталкиваюсь, заключается в том, что я использую поле ввода с типом "date" , которое работает как шарм в Chrome; он открывает календарь в Chrome, но в остальном он ничего не делает, поэтому я решил пойти на ручной ввод даты для остальных.

Это мое сообщение с ошибкой (я ищу формат YYYY-MM-DD):

 $date_regex ='#^(19|20)\d\d[\- /.](0[1-9]|1[012])[\- /.](0[1-9]|[12][0-9]|3[01])$#'; $hiredate = $_POST['hiredate']; if (!preg_match($date_regex, $hiredate)){ $errors[] = 'Your hire date entry does not match the YYYY-MM-DD required format.'; } 

Я знаю, что есть много примеров об этом, но я пробовал уже 20, и я не мог его решить. Может быть, я что-то упустил.

Вот поле ввода, если оно имеет несколько значение:

 <input type="date" name="hiredate" /> 

Ваше регулярное выражение не сработало, потому что у вас был unescaped / delimiter.

Регулярное выражение, которое будет проверять дату в формате YYYY-MM-DD следующим образом:

 ^(19|20)\d\d[\-\/.](0[1-9]|1[012])[\-\/.](0[1-9]|[12][0-9]|3[01])$ 

Он подтвердит, что год начинается с 19 или 20 , что месяц не превышает 12 и не равен 0 и что день не больше 31 и не равен 0 .

Пример онлайн

Используя ваш первоначальный пример, вы можете протестировать его следующим образом:

 $date_regex = '/^(19|20)\d\d[\-\/.](0[1-9]|1[012])[\-\/.](0[1-9]|[12][0-9]|3[01])$/'; $hiredate = '2013-14-04'; if (!preg_match($date_regex, $hiredate)) { echo '<br>Your hire date entry does not match the YYYY-MM-DD required format.<br>'; } else { echo '<br>Your date is set correctly<br>'; } 

Пример онлайн

Не используйте regex для этого, вы можете получить тот же результат, используя DateTime::createFromFormat

 // specify your date's original format, in this example m/d/Y (eg 08/31/2013) $format = "m/d/Y"; $hireDate = DateTime::createFromFormat($format, $_POST['hiredate']); if(!$hireDate) { // createFromFormat returns false if the format is invalid; } else { //change it to any format you want with format() (eg 2013-08-31) echo $hireDate->format("Ymd"); } 

Вы можете прочитать больше здесь:

http://php.net/manual/en/datetime.createfromformat.php

Однако, похоже, проблема совершенно не связана с PHP.

PHP работает на задней панели, и кажется, что у вас проблема с интерфейсом.

Я также сомневаюсь, что проблема заключается в типе ввода, который вы используете. Если один браузер не поддерживает указанный тип ввода, он по умолчанию использует текст. Смотрите здесь:

http://jsfiddle.net/FKGCA/

Мой браузер не знает, что такое <input type="whatever" /> , поэтому он по умолчанию вводит тип "text". Если я упакую эти 4 входа в <form action="myForm.php" method="POST"></form> , браузер отправляет входы на сервер, потому что сервер не заботится / знает, были ли входы скрытые, переключатели, выбор, текст или пароль. Серверы получают только исходные данные.

Скорее всего, ваша проблема связана с вашим Javascript, а не с вашим PHP. Попробуйте проверить, не показывает ли браузер, который не отображает ваш виджет, что на вашей странице есть какая-то ошибка.

У Safari и Firefox есть инструменты для разработки / отладки, которые не настолько уверены в IE.

Проверка и проверка YYYY-MM-DD в одной строке

 function isValidDate($date) { return preg_match("/^(\d{4})-(\d{1,2})-(\d{1,2})$/", $date, $m) ? checkdate(intval($m[2]), intval($m[3]), intval($m[1])) : false; } 

Подробности см. В моем ответе.

Не используйте слепое DateTime::createFromFormat для проверки дат. Давайте возьмем несуществующую дату 2018-02-30 и посмотрим:

 $d = DateTime::createFromFormat("Ymd", "2018-02-30"); var_dump((bool) $d); // bool(true) 

Да, он возвращает true , а не false как вы могли ожидать. Интереснее:

 $d = DateTime::createFromFormat("Ymd", "2018-99-99"); var_dump((bool) $d); // bool(true) 

Также true … Итак, он проверяет только количество цифр. Еще одна попытка:

 $d = DateTime::createFromFormat("Ymd", "ABCD-99-99"); var_dump($d); // bool(false) 

Наконец, false .

Что здесь происходит, мы можем видеть из этого фрагмента:

 $d = DateTime::createFromFormat("Ymd", "2018-02-30"); var_dump($d); // var_dump OUTPUT object(DateTime)#1 (3) { ["date"]=> string(26) "2018-03-02 16:41:34.000000" ["timezone_type"]=> int(3) ["timezone"]=> string(3) "UTC" } 

Как вы можете видеть, когда мы пропускаем несуществующий 2018-02-30 , объект DateTime содержит 2018-03-02 . Я предполагаю, что это потому, что февраль 2018 года составляет 28 дней, то есть максимальная дата 2018-02-28 , а когда мы проходим день 30 , createFromFormat просто добавляет 30 дней к 2018-02-01 и создает новую дату без предшествующей даты Проверка.