Регулярное выражение для текстовых дат? (он же исходный код для strtotime php)
Я работаю над окном поиска для сайта событий. Я записывал поиски, которые совершают люди, и многие люди вводят комбо {date}+{ключевое слово}.
пример поиска:
jazz 5th november
dj shadow tonight
2nd october live music
поэтому мне нужно написать / найти регулярное выражение, которое может соответствовать текстовым датам из более длинной строки.
Я думаю, что самый простой способ сделать это будет работать с исходным кодом для PHP strtotime()
при условии, что он работает на регулярных выражениях.
Может кто-нибудь дать мне какие-нибудь советы по получению источника или, альтернативно, кто-нибудь сталкивался с какими-либо хорошими регулярными выражениями для текстовых дат?
2 ответа
Разбираясь в этом ответе, как насчет использования этого, чтобы найти даты (или вещи, которые, по крайней мере, похожи на даты) в тексте, а затем попытаться проанализировать их:
\b # match a word boundary
(?: # either...
(?: # match the following one to three times:
(?: # either
\d+ # a number,
(?:\.|st|nd|rd|th)* # followed by a dot, st, nd, rd, or th (optional)
| # or a month name
(?:(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]*)
)
[\s./-]* # followed by a date separator or whitespace (optional)
){1,3} # do this one to three times
| # or match a "colloquial" date and capture in backref 1:
(to(?:day|ni(?:te|ght)|morrow)|next\s+(?:week|month|year))
)
\b # and end at a word boundary.
Так что, если у вас есть совпадение и обратная ссылка $1
пусто, тогда была найдена буквальная дата; если $1
не пусто, он нашел дату как "сегодня" или "на следующей неделе". Конечно, это будет работать только с датами в английском тексте, и это, вероятно, не будет очень надежным.
if (preg_match(
'%\b # match a word boundary
(?: # either...
(?: # match the following one to three times:
(?: # either
\d+ # a number,
(?:\.|st|nd|rd|th)* # followed by a dot, st, nd, rd, or th (optional)
| # or a month name
(?:(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]*)
)
[\s./-]* # followed by a date separator or whitespace (optional)
){1,3} # do this one to three times
| # or ...
(?:to(?:day|ni(?:te|ght)|morrow)|next\s+(?:week|month|year))
)
\b # and end at a word boundary.%ix',
$subject, $regs)) {
$result = $regs[0];
$colloq = $regs[1]; // don't know what happens if $1 didn't participate in the match, though.
} else {
$result = "";
}
strtotime
распознает каждый формат, который объясняется в форматах даты и времени. Вы можете взять форматы прямо оттуда и создать регулярное выражение самостоятельно.
Вот пример для форматов времени:
// Uses Symbols
$frac = "(?:\.[0-9]+)"; //".21342", ".85"
$hh = "(?:0?[1-9]|1[0-2])"; // "04", "7", "12"
$HH = "(?:[01][0-9]|2[0-4])"; // "04", "7", "19"
$meridian = "(?:[AaPp]\.?[Mm]\.?[\0\t ])"; // "A.m.", "pM", "am."
$MM = "(?:[0-5][0-9])"; // "00", "12", "59"
$II = "(?:[0-5][0-9])"; // "00", "12", "59"
$space = "(?:[ \t])";
$tz = "(?:\(?[A-Za-z]{1,6})?|[A-Z][a-z]+(?:[_/][A-Z][a-z]+)+)"; // "CEST", "Europe/Amsterdam", "America/Indiana/Knox"
$tzcorrection = "(?:(?:GMT)?[+-]$hh:?$MM?)"; // "+0400", "GMT-07:00", "-07:00"
// 12 Hour Notation
$Hour_only_with_meridian = "(?:$hh$space?$meridian)"; // "4 am", "5PM"
$Hour_and_minutes_with_meridian = "(?:$hh[.:]$MM$space?$meridian)"; // "4:08 am", "7:19P.M."
$Hour_minutes_and_seconds_with_meridian = "(?:$hh[.:]$MM[.:]$II$space?$meridian)"; // "4:08:37 am", "7:19:19P.M."
$Hour_minutes_seconds_and_fraction_with_meridian = "(?:$hh:$MM:$II[.:][0-9]+$meridian)"; // "4:08:39:12313am"
// 24 Hour Notation
$Hour_and_minutes = "($t?$HH[.:]$MM)"; // "04:08", "19.19", "T23:43"
$Hour_and_minutes_no_colon = "(?:t?$HH$MM)"; // "0408", "t1919", "T2343"
$Hour_minutes_and_seconds = "(?:t?$HH$[.:]$MM[.:]$II)"; // "04.08.37", "t19:19:19"
$Hour_minutes_and_seconds_no_colon = "(?:t?$HH$MM$II)"; // "040837", "T191919"
$Hour_minutes_seconds_and_timezone = "(?:t?$HH[.:]$MM[.:]$II$space?(?:$tzcorrection|$tz))"; // "040837CEST", "T191919-0700"
$Hour_minutes_seconds_and_fraction = "(?:t?$HH[.:]$MM[.:]$II$frac)"; // "04.08.37.81412", "19:19:19.532453"
$Time_zone_information = "(?:$tz|$tzcorrection)"; // "CEST", "Europe/Amsterdam", "+0430", "GMT-06:00"