PHP Regex для проверки даты находится в формате гггг-ММ-ДД
Я пытаюсь проверить, что даты, введенные конечными пользователями, находятся в YYYY-MM-DD. Регулярное выражение никогда не было моей сильной стороной, я продолжаю получать ложное возвращаемое значение для 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;
}
какие мысли?
16 ответов:
попробуйте это.
$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("Y-m-d", $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
to fail), чтобы убедиться, что возвращается достаточно элементов, так что если вход "1-2"list()
не будет выдавать уведомление
критерии:
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
гггг-ММ-ДД :
/^((((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
гггг/ММ/ДД :
/^((((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
ММ-ДД-гггг :
/^(((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
ММ/ДД/гггг :
/^(((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
ДД/ММ/гггг :
/^(((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
ДД-ММ-гггг :
/^(((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('Y-m-d', $date); if ($date) { echo $date -> format('Y-m-d'); }
в этом случае вы получите объект, который muck проще в использовании, чем просто строки.
вы можете использовать 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;
Я знаю, что это старый вопрос. Но я думаю, что у меня есть хорошее решение.
$date = "2016-02-21"; $format = "Y-m-d"; if(date($format, strtotime($date)) == date($date)) { echo "true"; } else { echo "false"; }
вы можете попробовать его. Если вы измените дату на 21.02.2016, эхо будет ложным. И если вы измените формат после этого на d.m.Y, эхо будет истинным.
С помощью этого простого кода, Вы должны быть в состоянии проверить, какой формат даты используется не проверив его с помощью регулярных выражений.
может быть, есть человек, который будет проверять его на каждом случае. Но я думаю, что моя идея в целом верна. Для меня это кажется логичным.
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 )
можно использовать
function validateDate($date, $format = 'Y-m-d H:i:s') { $d = DateTime::createFromFormat($format, $date); return $d && $d->format($format) == $date; } $date="2012-09-12"; echo validateDate($date, 'Y-m-d'); // true or false
Если вы хотите, чтобы соответствовать этому типу даты, используйте:
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'; }
проверки
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})$/"
вы также можете сделать это так:
if (DateTime::createFromFormat('Y-m-d', $date)->format('Y-m-d') === $date) { // date is correctly formatted and valid, execute some code }
это не только формат, но и дату, поскольку
DateTime
будет создавать только действительные даты, и это должно соответствовать входным данным.
все зависит от того, насколько строго вы хотите, чтобы эта функция была. Например, если вы не хотите, чтобы месяцы выше 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; } }