我试图弄清楚如何使用用户定义的模式从字符串中提取日期。该模式可以采用多种不同的方式,例如:Y-m-d
,d/m/Y
,(m/d/Y)
,[d/m/Y]
等等。
包含其中解析日期的字符串是常规文本块,并使用定义的模式进行解析(类似于上面描述的)。例如,字符串中的日期类似于以下内容,具体取决于用户定义的模式:2014-04-25
,04/25/2014
,25/04/2014
,(04/25/2014)
,{{1等等。
有没有办法使用用户定义的模式从字符串中提取实际日期?我希望某种正则表达式可以完成这项工作,但到目前为止,我仍然坚持这个问题。
答案 0 :(得分:1)
你可以强制一种模式策略,即年份总是4个字符等。YYYY-MM-DD
或str_replace()
来获得你想要的一个。您可能需要使用大写字母,否则\d
会获得替换,因为它会看到d
。或者更好的是,强制模式为大写:
$pattern = 'Y-M-D';
$pattern = str_replace(array('Y','M','D'), array('\d{4}','\d{1,2}','\d{1,2}'), strtoupper($pattern));
$pattern = preg_quote($pattern, '#');
preg_match("#$pattern#", $string, $match);
print_r($match);
答案 1 :(得分:0)
创建一个映射,将日期模式转换为正则表达式,然后使用preg_match_all()
从给定字符串中提取所有匹配日期:
function extractDates($text, $pattern)
{
$mapping = [
'y' => '\d{4}',
'm' => '\d{2}',
'd' => '\d{2}',
];
$regex = strtr(strtolower($pattern), $mapping);
if (preg_match_all("~$regex~", $text, $matches)) {
return $matches[0];
}
return false;
}
测试用例:
$testcases = [
'foo 2014-04-25 bar' => 'y-m-d',
'foo 25/04/2014 bar' => 'd/m/y',
'foo 04/25/2014 bar' => 'm/d/y',
'foo [2014-04-25] bar' => 'y-m-d',
'foo (25/04/2014) bar' => 'd/m/y',
'foo [04/25/2014] bar' => 'm/d/y',
];
foreach ($testcases as $text => $pattern) {
echo extractDates($text, $pattern)[0], PHP_EOL;
}
<强>输出:强>
2014-04-25
25/04/2014
04/25/2014
2014-04-25
25/04/2014
04/25/2014
答案 2 :(得分:0)
可以使用用户可用于定义其选择格式的预定义符号来完成。然后,您可以使用这些符号安全地创建正则表达式:
function findDates($haystack, $format) {
// Symbol to regex table
// Change this to suit how you want the symbols
// to be matched
static $table = [
'D' => '(?<!\d)(?:0[1-9]|[12]\d|3[01])(?!\d)',
'd' => '(?<!\d)(?:[1-9]|[12]\d|3[01])(?!\d)',
'M' => '(?<!\d)(?:0[1-9]|1[012])(?!\d)',
'm' => '(?<!\d)(?:[1-9]|1[012])(?!\d)',
'Y' => '(?<!\d)(?:\d{4})(?!\d)',
'y' => '(?<!\d)(?:\d{2})(?!\d)',
];
// Escape any special characters in the format, so
// that it can be used for the regular expression
$format = preg_quote($format, '/');
// Create the regex by replacing symbols with their
// corresponding regex
$regex = str_replace(array_keys($table), array_values($table), $format);
// Attempt to find dates
preg_match_all("/{$regex}/", $haystack, $matches);
// Return matches; if there were no matches then
// then return false instead
return $matches[0] ?: false;
}
$text = 'It happens on either 18/9 2015 or 8/10 2015.';
$findFormat = 'd/m Y';
var_dump(findDates($text, $findFormat));