PHP - регулярное выражение для удаления всего остального, кроме даты из строки - PullRequest
0 голосов
/ 28 февраля 2019

Я извлекаю некоторые данные из моей базы данных для вывода в файл .csv.Эти выведенные строки могут включать или не включать две даты в нескольких различных форматах, включая:

YYYY-MM-DD (2019-02-01)
DD.MM.YYYY (01.02.2019)
D.M.YYYY (1.2.2019)
DD.MM.YY (01.02.19)
D.MM.YY (1.02.19)
D.MM.YYYY (1.02.2019)

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

Product 1, 1.10.2018 - 31.12.2018 just a test string
Product 2 15.12.18-23.6.19

Теперь я хотел бы проанализировать обе эти даты в одном формате (ДД.ММ.ГГГГ), если он найден из строки всобственные переменные.

Если в строке не найдены даты, строку можно пока игнорировать.Вот что я попробовал до сих пор:

<?php

        function contains_date($str) {
          if (preg_match('/\b(\d{4})-(\d{2})-(\d{2})\b/', $str, $matches)) {
            if (checkdate($matches[2], $matches[3], $matches[1])) {
              return true;
            }
          }
          return false;
        }

        $i = 0;
        $table = [];
        while($row = $stmt->fetch()) {
        if(contains_date($row['product'])) {
          $product = preg_replace('/\s+/', '', $row['product']);
          $date = substr($product, -21);
          $periodStart = date('d.m.Y', strtotime(substr($date, 0, 10)));
          $periodEnd = date('d.m.Y', strtotime(substr($date, 11)));

        }

        $table[$i]['product'] = $row['product'];
        $table[$i]['startDate'] = $periodStart;
        $table[$i]['endDate'] = $periodEnd;

        $i++;
        }
        ?>

Это работает в тех случаях, когда дата указана в формате ГГГГ-ММ-ДД, и если эти две даты находятся в конце строки.Он не охватывает все случаи, когда формат даты отличается, или если даты находятся в середине строки.Любая помощь будет высоко ценится!

1 Ответ

0 голосов
/ 28 февраля 2019

Вы можете использовать группы с одинаковыми именами для сопоставления разных форматов дат с одним регулярным выражением:

$rx = '/(?J)(?<!\d)(?:(?<year>\d{4})-(?<month>\d{1,2})-(?<day>\d{1,2})|(?<day>\d{1,2})\.(?<month>\d{1,2})\.(?<year>\d{2}(?:\d{2})?))(?!\d)/';

См. Демонстрационную версию регулярного выражения .

POI :

  • Группы с одинаковыми именами в одном шаблоне включаются с помощью модификатора J
  • (?<!\d) с отрицательным взглядом наначало регулярного выражения отменяет совпадение после цифры (оно соответствует местоположению, которому непосредственно не предшествует цифра)
  • (?!\d) отрицательное ожидание в конце регулярного выражения отменяет совпадение перед цифрой (соответствуетместоположение, за которым сразу же не стоит цифра)

Демонстрация PHP :

$strs = ['YYYY-MM-DD (2019-02-01)', 'DD.MM.YYYY (01.02.2019)', 'D.M.YYYY (1.2.2019)','DD.MM.YY (01.02.19)','D.MM.YY (1.02.19)','D.MM.YYYY (1.02.2019)','Product 1, 1.10.2018 - 31.12.2018 just a test string','Product 2 15.12.18-23.6.19' ];
$rx = '/(?J)(?<!\d)(?:(?<year>\d{4})-(?<month>\d{1,2})-(?<day>\d{1,2})|(?<day>\d{1,2})\.(?<month>\d{1,2})\.(?<year>\d{2}(?:\d{2})?))(?!\d)/';
foreach ($strs as $s) {
    echo "INPUT: $s\n";
    if (preg_match_all($rx, $s, $matches, PREG_SET_ORDER, 0)) {
        foreach ($matches as $m) {
            echo "DAY: " . $m["day"] . "\nMONTH: " . $m["month"] . "\nYEAR: " . $m["year"] . "\n\n";
        }
    }
}

Вывод:

INPUT: YYYY-MM-DD (2019-02-01)
DAY: 01
MONTH: 02
YEAR: 2019

INPUT: DD.MM.YYYY (01.02.2019)
DAY: 01
MONTH: 02
YEAR: 2019

INPUT: D.M.YYYY (1.2.2019)
DAY: 1
MONTH: 2
YEAR: 2019

INPUT: DD.MM.YY (01.02.19)
DAY: 01
MONTH: 02
YEAR: 19

INPUT: D.MM.YY (1.02.19)
DAY: 1
MONTH: 02
YEAR: 19

INPUT: D.MM.YYYY (1.02.2019)
DAY: 1
MONTH: 02
YEAR: 2019

INPUT: Product 1, 1.10.2018 - 31.12.2018 just a test string
DAY: 1
MONTH: 10
YEAR: 2018

DAY: 31
MONTH: 12
YEAR: 2018

INPUT: Product 2 15.12.18-23.6.19
DAY: 15
MONTH: 12
YEAR: 18

DAY: 23
MONTH: 6
YEAR: 19
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...