Регулярное выражение для текстовых дат? (он же исходный код для 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"
Другие вопросы по тегам