Как проверить даты без начального нуля в день и месяц?

Мне нужно проверить точный формат даты в php.

В моем случае оптимальный формат даты должен быть: например. 1/1/2017 (без ведущих нулей), и код должен позволить мне избежать остального формата даты.

Следующий код - это то, что я написал, но безрезультатно:

if(preg_match("/([1-9]|[1-2][0-9]|3[0-1]-([1-9]|1[0-2])-^[0-9]{4})$/", $date){
    // insert into etc. etc....
}else{
    // update etc. etc....
}

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


person Sergio Santopietro    schedule 14.06.2017    source источник
comment
См. date_parse_from_format().   -  person Alex Howansky    schedule 14.06.2017
comment
или strptime().   -  person Casimir et Hippolyte    schedule 14.06.2017
comment
Конечно, вы можете использовать регулярное выражение для этого. С другой стороны, вы также можете использовать регулярное выражение для анализа всего дерева DOM, что не означает, что вы должны это делать.   -  person apokryfos    schedule 14.06.2017


Ответы (4)


Я заметил, что представленный ОП ответ не был пуленепробиваемым, поэтому я начал исследовать некоторые функции, упомянутые в комментариях под вопросом, и некоторые из моих собственных мыслей.

Я согласен с apokryfos в том, что использование регулярных выражений для проверки выражения даты не является лучшей практикой. Чистое регулярное выражение будет все более многословным и менее понятным шаблоном, потому что ему придется учитывать високосные годы как в прошлом, так и в будущем. По этой причине я исследовал несколько функций даты, которые предлагает php.

  1. date_parse_from_format(), предложенный Алексом Ховански. К сожалению, в данном случае это не будет самостоятельным решением, поскольку параметр format подчиняется синтаксису/правилам DateTime::createFromFormat():

введите здесь описание изображения

Посмотрите, как d и j сгруппированы вместе, как и m и n. Следовательно, эта функция будет обнаруживать недопустимые даты, но не нежелательные ведущие нули.

  1. strptime(), предложенный Casimir et Hippolyte. Эта функция позволяет сопоставлять дни без начальных нулей, используя %e. Эта функция не имеет символа, который соответствует номерам месяцев, отличным от нуля. Кроме того, могут быть сбои с этой функцией в операционной системе.

  2. check_date() кажется логичным выбором, но опять же, он не дрогнет нулевые числа. Кроме того, эта функция требует немного большей подготовки данных, чем другие, потому что она требует индивидуальной настройки значений месяца, дня и года.

  3. if(!DateTime::createFromFormat('j/n/Y', $date)), предложенный deceze относительно немного другого сценария, в этом случае не сработает. createFromFormat() сделает все возможное, чтобы создать правильную дату — даже такая строка, как 99/99/9999, пройдет.


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

if (($d=DateTime::createFromFormat('n/j/Y',$date)) && $date==$d->format('n/j/Y')){
    // valid
}else{
    // invalid
}

strtotime() можно использовать с одним условием для этого случая, потому что формат даты OP использует косую черту в качестве разделителя, и эта функция будет правильно анализировать выражение даты «в американском стиле».

Кажется, это самый простой способ проверить правильность даты без ведущих нулей: Демо-ссылка

if(date('n/j/Y',strtotime($date))==$date){
    // valid
}else{
    // invalid
}

Если вы имеете дело с выражениями даты и времени и не хотите проверять часть времени, вы можете вызвать эту строку перед условной строкой:

$date = explode(' ', $date)[0];  // create an array of two elements: date and time, then only access date

Ссылка на демонстрацию

or

$date = strstr($date, ' ', true); // extract substring prior to first space
person mickmackusa    schedule 31.07.2017

вы можете использовать с углеродом

$date->format('j')
person Turan Zamanlı    schedule 19.09.2018

Разделителем даты является /, а не -, поэтому добавьте \/ в регулярное выражение для /. И используйте ^ в начале регулярного выражения:

if(preg_match("/^([1-9]|[1-2][0-9]|3[0-1])\/([1-9]|1[0-2])\/([0-9]{4})$/", $date){
person Mohammad Hamedani    schedule 14.06.2017
comment
Эта закономерность будет неверной для 31 числа февраля, апреля, июня, сентября, ноября; 30 февраля, условно 29 февраля. Этот ответ не следует использовать в проектах. - person mickmackusa; 02.12.2020

Через несколько часов, наконец, я нашел правильный ответ. Правильный шаблон для php — использовать одинарную кавычку ('), а не двойную кавычку ("), например:

preg_match('/^([1-9]|[1-2][0-9]|3[0-1])\/([1-9]|1[0-2])\/([0-9]{4})/',$date)

это отлично работает для меня ... Спасибо всем, особенно @Mohammad Hamedani, потому что выражение было правильным, но чертова цитата сводит меня с ума

person Sergio Santopietro    schedule 15.06.2017
comment
Эта закономерность будет неверной для 31 числа февраля, апреля, июня, сентября, ноября; 30 февраля, условно 29 февраля. Этот ответ не следует использовать в проектах. - person mickmackusa; 02.12.2020