Ответ 1
Попробуйте это.
$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;
}
Я пытаюсь проверить, что даты, введенные конечными пользователями, находятся в 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("Y-m-d", $date);
return $dt !== false && !array_sum($dt::getLastErrors());
Это также проверяет ввод: $dt !== false
гарантирует, что дата может быть проанализирована с указанным форматом, а трюк array_sum
- это краткий способ 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)
Действительный месяц и день, исключая февраль (MM-DD):
((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 года в формате YYYY-MM-DD.
Я подозреваю, что его можно немного сократить, но я оставлю это кому-то еще.
Это будет соответствовать всем действительным датам. Если вы хотите, чтобы он был действителен только в том случае, если он содержит только одну дату и ничего больше, а затем заверните его в ^( )$
следующим образом:
^(((((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
мм/дд/гггг:
/^(((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('Y-m-d', $date);
if ($date) {
echo $date -> format('Y-m-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;
Я знаю, что это старый вопрос. Но я думаю, что у меня есть хорошее решение.
$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 нуждается в/или другом char в качестве разделителя.
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
Вы также можете сделать это так:
if (DateTime::createFromFormat('Y-m-d', $date)->format('Y-m-d') === $date) {
// date is correctly formatted and valid, execute some code
}
Это будет проверять не только формат, но и действительность даты, так как DateTime
создаст только действительные даты, и это должно соответствовать входным данным.
Если вы хотите совместить этот тип даты, используйте:
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})$/"
Если это поможет, вот регулярное выражение для формата jnY (год должен быть больше 2018):
if (preg_match('/^([1-9]|[1-2][0-9]|[3][0-1])\-([1-9]|[1][0-2])\-(?:20)([1][8-9]|[2-9][0-9])$/', $date)) {
// Do stuff
}
Все зависит от того, насколько строго вы хотите, чтобы эта функция была. Например, если вы не хотите допускать месяцы выше 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 в соответствии с вашим форматом и разделителем в explode.
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;
}
}
[Если вы используете Symfony 4.1.2, попробуйте это] [1]
$validDate = explode("-",$request->get('date'));
if (checkdate(filter_var($validDate[1],FILTER_SANITIZE_NUMBER_INT),filter_var($validDate[0],FILTER_SANITIZE_NUMBER_INT),filter_var($validDate[2],FILTER_SANITIZE_NUMBER_INT))){
$date = date_create(filter_var($request->get('date'),FILTER_SANITIZE_SPECIAL_CHARS));
}else{
return $this->redirectToRoute('YOUR_ROUTE');
}
Начиная с Laravel 5.7 и формата даты, то есть: 31.12.2009
function checkDateFormat(string $date): bool
{
return preg_match("/^(0[1-9]|1[0-2])\/(0[1-9]|[1-2][0-9]|3[0-1])\/[0-9]{4}$/", $date);
}
Формат 1: $ format1 = "2012-12-31";
Формат 2: $ format2 = "31-12-2012";
if (preg_match("/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/",$format1)) {
return true;
} else {
return false;
}
if (preg_match("/^(0[1-9]|[1-2][0-9]|3[0-1])-(0[1-9]|1[0-2])-[0-9]{4}$/",$format2)) {
return true;
} else {
return false;
}