Каков шаблон регулярного выражения для datetime (2008-09-01 12:35:45)?

Что такое шаблон RegEx для DateTime (2008-09-01 12:35:45)?

Я получаю эту ошибку:

Не найден конечный разделитель '^'

С использованием:

preg_match('(?n:^(?=\d)((?<day>31(?!(.0?[2469]|11))|30(?!.0?2)|29(?(.0?2)(?=.{3,4}(1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|(16|[2468][048]|[3579][26])00))|0?[1-9]|1\d|2[0-8])(?<sep>[/.-])(?<month>0?[1-9]|1[012])\2(?<year>(1[6-9]|[2-9]\d)\d{2})(?:(?=\x20\d)\x20|$))?(?<time>((0?[1-9]|1[012])(:[0-5]\d){0,2}(?i:\ [AP]M))|([01]\d|2[0-3])(:[0-5]\d){1,2})?$)', '2008-09-01 12:35:45');

Выдает эту ошибку:

Предупреждение: preg_match() [function.preg-match]: Ошибка компиляции: ничего не повторяется по смещению 0 в E:\www\index.php в строке 19


person Alexander Morland    schedule 01.09.2008    source источник


Ответы (12)


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

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

(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})

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

$year = $1;
$month = $2;
$day = $3;
$hour = $4;
$minute = $5;
$second = $6;

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

person Greg Hewgill    schedule 01.09.2008
comment
Просто комментарий, чтобы сказать, что это регулярное выражение не обнаружит, имеет ли дата, месяц или время значение, превышающее максимальное. Например, 2012-65-65 99:99:99 будет работать. Кроме того, регулярное выражение великолепно! - person darkheir; 20.10.2012
comment
Показанное регулярное выражение не предназначено для проверки даты. Он предназначен для проверки синтаксиса строки, чтобы увидеть, похоже ли это на дату. После получения значений вы можете проверить заданную дату, используя обычные функции библиотеки дат. - person Greg Hewgill; 05.03.2014
comment
Это регулярное выражение перестанет работать через 7981 год. - person Boris; 30.01.2019
comment
Это регулярное выражение дает совпадение даже для такой даты, как 2020-99-99 99:99:99, что неверно, как указано @darkheir. - person Swaru; 08.07.2020

Простая версия, которая будет работать для упомянутого формата, но не для всех остальных, согласно @Espos:

(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) 
person Tom    schedule 01.09.2008
comment
плюс одно простое решение! - person chiliNUT; 16.12.2014
comment
Этот проверяет как 0000-00-00 00:00:00, так и 0000-00-00 00:00 (\d{4})-(\d{2})-(\d{2}) (\d{ 2}):(\d{2})?((:)?(\d{2})) - person iRector; 28.11.2017

http://regexlib.com/REDetails.aspx?regexp_id=610

^(?=\d)(?:(?:31(?!.(?:0?[2469]|11))|(?:30|29)(?!.0?2)|29(?=.0?2.(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00)))(?:\x20|$))|(?:2[0-8]|1\d|0?[1-9]))([-./])(?:1[012]|0?[1-9])\1(?:1[6-9]|[2-9]\d)?\d\d(?:(?=\x20\d)\x20|$))?(((0?[1-9]|1[012])(:[0-5]\d){0,2}(\x20[AP]M))|([01]\d|2[0-3])(:[0-5]\d){1,2})?$


Этот RE проверяет как даты, так и/или шаблоны времени. Дни в феврале также действительны для високосных лет. Даты: в формате дд/мм/гггг или д/м/гг между 01.01.1600 и 31.12.9999. Начальные нули необязательны. Разделителями даты могут быть совпадающие тире (-), косые черты (/) или точки (.) Время: в формате чч: мм: сс AM/PM 12-часовой формат (12:00 - 23:59:59) или чч :MM:ss формат военного времени (00:00:00 - 23:59:59). 12-часовой формат времени: 1) час может начинаться с нуля. 2) Минуты и секунды необязательны для 12-часового формата. 3) Требуется указать AM или PM с учетом регистра. Военное время 1) должно иметь начальный нуль для всех часов менее 10. 2) Минуты обязательны. 3) секунды необязательны. Дата и время: комбинация вышеуказанных форматов. Сначала дата, затем время, разделенное пробелом. пример) дд/мм/гггг чч:мм:сс


Изменить: убедитесь, что вы скопировали RegEx с веб-сайта regexlib.com, поскольку StackOverflow иногда удаляет/уничтожает специальные символы.

person Espo    schedule 01.09.2008
comment
Этот ответ дает хорошее регулярное выражение, но не является ответом на фактический вопрос. Вопрос состоит в том, чтобы проверить даты, разделенные - а не / как описывает этот ответ. - person Murilo Garcia; 19.03.2016

$date = "2014-04-01 12:00:00";

preg_match('/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/',$date, $matches);

print_r($matches);

$match будет:

Array ( 
   [0] => 2014-04-01 12:00:00 
   [1] => 2014 
   [2] => 04 
   [3] => 01 
   [4] => 12 
   [5] => 00 
   [6] => 00
)

Простой способ разбить строку в формате даты и времени.

person Philip    schedule 01.04.2014

что касается ответа Имрана от 1 сентября 2008 г. в 12:33, отсутствует: в шаблоне правильные шаблоны

preg_match('/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/', '2008-09-01 12:35:45', $m1);
print_r( $m1 );
preg_match('/\d{4}-\d{2}-\d{2} \d{1,2}:\d{2}:\d{2}/', '2008-09-01 12:35:45', $m2);
print_r( $m2 );
preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/', '2008-09-01 12:35:45', $m3);
print_r( $m3 );

это возвращает

Array ( [0] => 2008-09-01 12:35:45 )
Array ( [0] => 2008-09-01 12:35:45 )
Array ( [0] => 2008-09-01 12:35:45 ) 
person deni    schedule 18.01.2011

Добавление к ответу @Greg Hewgill: если вы хотите иметь возможность сопоставлять как дату-время, так и только дату, вы можете сделать часть регулярного выражения «время» необязательной:

(\d{4})-(\d{2})-(\d{2})( (\d{2}):(\d{2}):(\d{2}))?

таким образом вы будете соответствовать как 2008-09-01 12:35:42, так и 2008-09-01

person Milkncookiez    schedule 19.05.2020

Вот мое решение:

/^(2[0-9]{3})-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01]) (0[0-9]|1[0-9]|2[0123])\:([012345][0-9])\:([012345][0-9])$/u
person Tornike    schedule 30.09.2015


Предварительные функции PHP требуют, чтобы ваше регулярное выражение было заключено в символ-разделитель, который может быть любым символом. Вы не можете использовать этот символ-разделитель без экранирования внутри регулярного выражения. Это должно работать (здесь символ-разделитель /):

preg_match('/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/', '2008-09-01 12:35:45');

// or this, to allow matching 0:00:00 time too.
preg_match('/\d{4}-\d{2}-\d{2} \d{1,2}:\d{2}:\d{2}/', '2008-09-01 12:35:45');

Если вам нужно сопоставить строки, содержащие только дату и время, добавьте ^ и $ в начале и в конце регулярного выражения.

preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/', '2008-09-01 12:35:45');

Ссылка на руководство по PHP preg_match()

person Imran    schedule 01.09.2008

Вот мое решение:

[12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]) ([01][0-9]|2[0-3]):[0-5]\d

Визуализация регулярных выражений

Демонстрация отладки

https://regex101.com/r/lbthaT/4

person Yeongjun Kim    schedule 19.10.2016

Вот упрощенная версия (возникла из ответа Эспо). Проверяет правильность даты (даже високосный год), а формат чч:мм:сс является необязательным.
Примеры работы:
- 31/12/2003 11:59:59
- 29- 2-2004

^(?=\d)(?:(?:31(?!.(?:0?[2469]|11))|(?:30|29)(?!.0?2)|29(?=.0?2.(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00)))(?:\x20|$))|(?:2[0-8]|1\d|0?[1-9]))([-./])(?:1[012]|0?[1-9])\1(?:1[6-9]|[2-9]\d)?\d\d(?:(?=\x20\d)\x20|$))(|([01]\d|2[0-3])(:[0-5]\d){1,2})?$
person Duc Tran    schedule 11.07.2014

person    schedule
comment
использовал этот с небольшой модификацией, допускающей даты до 2000 года: ^(\d{4}-([0]\d|[1][0-2])-([0-2]\d|[3][ 0-1])\s([0-1]\d|[2][0-3])\:[0-5]\d\:[0-5]\d)$ - person Axi; 18.09.2018