Intereting Posts
Значение mysql по столбцу, сгруппированное по значению столбца как автоматически копировать весь каталог в виде эскизов, используя phpthumb (или некоторую другую библиотеку) Интерфейс PHP-трансляции похож на Rosetta? $ _POST с переменным количеством входов? Почему я получаю исключение JSON, пытающееся загрузить данные из URL-адреса хоста? Сохранение строки JSON в базе данных MySQL Search_array во вложенных массивах Как различить пустую строку с нулевым размером в DOMDocument? Доступ к электронной таблице Google с помощью Zend без проверки подлинности CodeIgniter URL-адрес суффикса .html автоматически для всех URL-адресов Как получить несколько строк из базы данных в PHP Возобновляемая и частичная загрузка с завихрением PHP или подобным? Передача данных из одного текстового поля в другой на другой странице с помощью POST Сортировка второго вложенного массива по значению в 3-м с php Как проверить ввод формы на одной странице с помощью случайных чисел?

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

Я пытаюсь проверить, что даты, введенные конечными пользователями, находятся в YYYY-MM-DD. Regex никогда не был моей сильной стороной, я продолжаю получать ложное возвращаемое значение для preg_match () у меня есть настройка.

Поэтому я предполагаю, что я создал беспорядок регулярного выражения, подробно описанный ниже.

$date="2012-09-12"; if (preg_match("^[0-9]{4}-[0-1][0-9]-[0-3][0-9]$",$date)) { return true; }else{ return false; } 

Есть предположения?

Попробуй это.

 $date="2012-09-12"; if (preg_match("/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/",$date)) { return true; } else { return false; } 

Вероятно, лучше использовать другой механизм для этого.

Современное решение с DateTime :

 $dt = DateTime::createFromFormat("Ymd", $date); return $dt !== false && !array_sum($dt->getLastErrors()); 

Это также проверяет ввод: $dt !== false гарантирует, что дата может быть проанализирована с указанным форматом, а трюк array_sum – это краткое средство обеспечения того, чтобы PHP не выполнял «сдвиг месяца» (например, считают, что 32 января – февраль 1). См. DateTime::getLastErrors() для получения дополнительной информации.

Решение для старой школы с explode и checkdate :

 list($y, $m, $d) = array_pad(explode('-', $date, 3), 3, 0); return ctype_digit("$y$m$d") && checkdate($m, $d, $y); 

Это подтверждает, что ввод также является допустимой датой. Вы можете сделать это с помощью регулярного выражения, но это будет более суетным – и 29 февраля не может быть проверено с помощью регулярного выражения вообще.

Недостатком этого подхода является то, что вы должны быть очень осторожны, чтобы отвергать все возможные «плохие» входы, не вызывая уведомления ни при каких обстоятельствах. Вот как:

  • explode ограничено возвратом 3 жетонов (так что если вход «1-2-3-4», $d станет «3-4»)
  • ctype_digit используется, чтобы убедиться, что вход не содержит никаких числовых символов (кроме тире)
  • array_pad используется (со значением по умолчанию, которое приведет к сбою checkdate ), чтобы убедиться, что достаточно элементов возвращено, так что если вход «1-2» list() не будет выдавать уведомление

Критерии:

Каждый год, делящийся на 4, представляет собой високосный год, за исключением случаев, когда он делится на 100, если он не делится на 400. Итак:

 2004 - leap year - divisible by 4 1900 - not a leap year - divisible by 4, but also divisible by 100 2000 - leap year - divisible by 4, also divisible by 100, but divisible by 400 

Февраль имеет 29 дней в високосный год и 28, когда не високосный год

30 дней в апреле, июне, сентябре и ноябре

31 день в январе, марте, мае, июле, августе, октябре и декабре

Контрольная работа:

Следующие даты должны пройти проверку:

 1976-02-29 2000-02-29 2004-02-29 1999-01-31 

Следующие даты должны быть недействительными:

 2015-02-29 2015-04-31 1900-02-29 1999-01-32 2015-02-00 

Ассортимент:

Мы проверим даты с 1 января по 31 декабря 29 декабря 2999 года. Технически используемый в настоящее время григорианский календарь использовался только в 1753 году для Британской империи и в разные годы в 1600-х годах для стран Европы, но я не собираюсь беспокоиться об этом.

Regex для проверки на високосный год:

Годы, делящиеся на 400:

 1200|1600|2000|2400|2800 can be shortened to: (1[26]|2[048])00 if you wanted all years from 1AD to 9999 then this would do it: (0[48]|[13579][26]|[2468][048])00 if you're happy with accepting 0000 as a valid year then it can be shortened: ([13579][26]|[02468][048])00 

Годы, делящиеся на 4:

 [12]\d([02468][048]|[13579][26]) 

Годы, делящиеся на 100:

 [12]\d00 

Не делится на 100:

 [12]\d([1-9]\d|\d[1-9]) 

Годы, делящиеся на 100, но не на 400:

 ((1[1345789])|(2[1235679]))00 

Делимое на 4, но не на 100:

 [12]\d([2468][048]|[13579][26]|0[48]) 

Високосные годы:

 divisible by 400 or (divisible by 4 and not divisible by 100) ((1[26]|2[048])00)|[12]\d([2468][048]|[13579][26]|0[48]) 

Не делится на 4:

 [12]\d([02468][1235679]|[13579][01345789]) 

Не високосный год:

 Not divisible by 4 OR is divisible by 100 but not by 400 ([12]\d([02468][1235679]|[13579][01345789]))|(((1[1345789])|(2[1235679]))00) 

Действительный месяц и день, исключая февраль (ММ-ДД):

 ((01|03|05|07|08|10|12)-(0[1-9]|[12]\d|3[01]))|((04|06|09|11)-(0[1-9]|[12]\d|30)) shortened to: ((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)) 

Февраль с 28 днями:

 02-(0[1-9]|1\d|2[0-8]) 

Февраль с 29 днями:

 02-(0[1-9]|[12]\d) 

Действительной датой:

 (leap year followed by (valid month-day-excluding-february OR 29-day-february)) OR (non leap year followed by (valid month-day-excluding-february OR 28-day-february)) ((((1[26]|2[048])00)|[12]\d([2468][048]|[13579][26]|0[48]))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|[12]\d))))|((([12]\d([02468][1235679]|[13579][01345789]))|((1[1345789]|2[1235679])00))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|1\d|2[0-8])))) 

Итак, у вас есть регулярное выражение для дат между 1 января 1000 и 31 декабря 2999 года в формате ГГГГ-ММ-ДД.

Я подозреваю, что его можно немного сократить, но я оставлю это кому-то еще.

Это будет соответствовать всем действительным датам. Если вы хотите, чтобы он был действителен только в том случае, если он содержит только одну дату и ничего больше, а затем заверните его в ^( )$ так:

 ^(((((1[26]|2[048])00)|[12]\d([2468][048]|[13579][26]|0[48]))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|[12]\d))))|((([12]\d([02468][1235679]|[13579][01345789]))|((1[1345789]|2[1235679])00))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|1\d|2[0-8])))))$ 

Если вы хотите его для дополнительной записи даты (то есть, она может быть пустой или действительной датой), добавьте ^$| в начале, вот так:

 ^$|^(((((1[26]|2[048])00)|[12]\d([2468][048]|[13579][26]|0[48]))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|[12]\d))))|((([12]\d([02468][1235679]|[13579][01345789]))|((1[1345789]|2[1235679])00))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|1\d|2[0-8])))))$ 

yyyy-mm-dd: /^((((19|[2-9]\d)\d{2})\-(0[13578]|1[02])\-(0[1-9]|[12]\d|3[01]))|(((19|[2-9]\d)\d{2})\-(0[13456789]|1[012])\-(0[1-9]|[12]\d|30))|(((19|[2-9]\d)\d{2})\-02\-(0[1-9]|1\d|2[0-8]))|(((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))\-02\-29))$/g

yyyy / mm / dd: /^((((19|[2-9]\d)\d{2})\/(0[13578]|1[02])\/(0[1-9]|[12]\d|3[01]))|(((19|[2-9]\d)\d{2})\/(0[13456789]|1[012])\/(0[1-9]|[12]\d|30))|(((19|[2-9]\d)\d{2})\/02\/(0[1-9]|1\d|2[0-8]))|(((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))\/02\/29))$/g

mm-dd-yyyy: /^(((0[13578]|1[02])\-(0[1-9]|[12]\d|3[01])\-((19|[2-9]\d)\d{2}))|((0[13456789]|1[012])\-(0[1-9]|[12]\d|30)\-((19|[2-9]\d)\d{2}))|(02\-(0[1-9]|1\d|2[0-8])\-((19|[2-9]\d)\d{2}))|(02\-29\-((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))))$/g

mm / dd / yyyy: /^(((0[13578]|1[02])\/(0[1-9]|[12]\d|3[01])\/((19|[2-9]\d)\d{2}))|((0[13456789]|1[012])\/(0[1-9]|[12]\d|30)\/((19|[2-9]\d)\d{2}))|(02\/(0[1-9]|1\d|2[0-8])\/((19|[2-9]\d)\d{2}))|(02\/29\/((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))))$/g

dd / mm / yyyy: /^(((0[1-9]|[12]\d|3[01])\/(0[13578]|1[02])\/((19|[2-9]\d)\d{2}))|((0[1-9]|[12]\d|30)\/(0[13456789]|1[012])\/((19|[2-9]\d)\d{2}))|((0[1-9]|1\d|2[0-8])\/02\/((19|[2-9]\d)\d{2}))|(29\/02\/((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))))$/g

dd-mm-yyyy: /^(((0[1-9]|[12]\d|3[01])\-(0[13578]|1[02])\-((19|[2-9]\d)\d{2}))|((0[1-9]|[12]\d|30)\-(0[13456789]|1[012])\-((19|[2-9]\d)\d{2}))|((0[1-9]|1\d|2[0-8])\-02\-((19|[2-9]\d)\d{2}))|(29\-02\-((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))))$/g

Вы можете сделать это так:

 if (preg_match("/\d{4}\-\d{2}-\d{2}/", $date)) { echo 'true'; } else { echo 'false'; } 

но вам лучше использовать это:

 $date = DateTime::createFromFormat('Ym-d', $date); if ($date) { echo $date -> format('Ym-d'); } 

в этом случае вы получите объект, который проще использовать, чем просто строки.

Вы можете использовать preg_match с функцией checkdate php

 $date = "2012-10-05"; $split = array(); if (preg_match ("/^([0-9]{4})-([0-9]{2})-([0-9]{2})$/", $date, $split)) { return checkdate($split[2], $split[3], $split[1]); } return false; 

preg_match нуждается в / или другом символе в качестве разделителя.

 preg_match("/^[0-9]{4}-[0-1][0-9]-[0-3][0-9]$/",$date) 

вы также должны проверить действительность этой даты, чтобы у вас не получилось что-то вроде 9999-19-38

 bool checkdate ( int $month , int $day , int $year ) 

Я знаю, что это старый вопрос. Но я думаю, что у меня есть хорошее решение.

 $date = "2016-02-21"; $format = "Ymd"; if(date($format, strtotime($date)) == date($date)) { echo "true"; } else { echo "false"; } 

Можешь попробовать. Если вы измените дату на 21.02.2016, эхо будет ложным. И если вы измените формат после этого на dmY, эхо будет истинным.

С помощью этого простого кода вы сможете проверить, какой формат даты используется, не проверяя его регулярным выражением.

Может быть, есть человек, который будет проверять его на каждом случае. Но я думаю, что моя идея в целом действительна. Для меня это кажется логичным.

Если вы хотите сопоставить этот тип даты, используйте:

 preg_match("~^\d{4}-\d{2}-\d{2}$~", $date) 

Это должно сказать вам, является ли формат действительным, и если дата ввода действительна.

  $datein = '2012-11-0'; if(preg_match('/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/', $datein)){ echo 'good'; }else{ echo 'no good'; } 

Все зависит от того, насколько строго вы хотите, чтобы эта функция была. Например, если вы не хотите разрешать месяцы выше 12 и дней выше 31 (не в зависимости от месяца, для чего потребуется запись даты-логики), это может стать довольно сложным:

 function checkDate($date) { $regex = '/^' . '(' . // Allows years 0000-9999 '(?:[0-9]{4})' . '\-' . // Allows 01-12 '(?:' . '(?:01)|(?:02)|(?:03)|(?:04)|(?:05)|(?:06)|(?:07)|(?:08)|(?:09)|(?:10)|' . '(?:11)|(?:12)' . ')' . '\-' . // Allows 01-31 '(?:' . '(?:01)|(?:02)|(?:03)|(?:04)|(?:05)|(?:06)|(?:07)|(?:08)|(?:09)|(?:10)|' . '(?:11)|(?:12)|(?:13)|(?:14)|(?:15)|(?:16)|(?:17)|(?:18)|(?:19)|(?:20)|' . '(?:21)|(?:22)|(?:23)|(?:24)|(?:25)|(?:26)|(?:27)|(?:28)|(?:29)|(?:30)|' . '(?:31)' . ')' . '$/'; if ( preg_match($regex, $date) ) { return true; } return false; } $result = checkDate('2012-09-12'); 

Лично я бы просто пошел за: /^([0-9]{4}\-([0-9]{2}\-[0-9]{2})$/

Чтобы работать с датами в php, вы должны следовать стандарту php, поэтому данное регулярное выражение гарантирует, что у вас есть действительная дата, которая может работать с PHP.

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

Этот метод может быть полезен для проверки даты в PHP. Текущий метод предназначен для формата mm / dd / yyyy. Вы должны обновить последовательность параметров в checkdate в соответствии с вашим форматом и разделителем при взорвании .

  function isValidDate($dt) { $dtArr = explode('/', $dt); if (!empty($dtArr[0]) && !empty($dtArr[1]) && !empty($dtArr[2])) { return checkdate((int) $dtArr[0], (int) $dtArr[1], (int) $dtArr[2]); } else { return false; } } 

Проверка и проверка 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; } 

Выход будет:

 var_dump(isValidDate("2018-01-01")); // bool(true) var_dump(isValidDate("2018-1-1")); // bool(true) var_dump(isValidDate("2018-02-28")); // bool(true) var_dump(isValidDate("2018-02-30")); // bool(false) 

Допускаются день и месяц без начального нуля. Если вы не хотите разрешать это, регулярное выражение должно быть:

 "/^(\d{4})-(\d{2})-(\d{2})$/"