我在启发式解析包含日期但格式相当随意(未知)的文本字符串时遇到问题。
function parseDateStr($text) {
$cleanText = filter($text);
# ...
$day = findDay($cleanText);
$month = findMonth($cleanText);
$year = findYear($cleanText);
# .. assert constraints, parse again or fail
return sprintf('%04d-%02d-%02d', $year, $month, $day)
}
输入文本是英语语言加上任意语法符号(如\W 正则表达式类的子集)的句子。该算法的任务是仅在过滤掉与日期无关的任何潜在垃圾(嘈杂)词后才提取日期。允许算法失败并且不返回任何结果。如果在字符串中只找到两个连接数字 (MM) 和其他四个数字 (YYYY) 的两个组合 - 假设两个数字对应于日期的月份,并且日期被认为是 01(第一天这个月)。结果以“YYYY-MM-DD”(SQL) 格式(DATE 类型)给出日期。
我的想法是继续使用 preg_replace & co 设计一系列过滤器。此外,对 $year、$day 的范围使用逻辑约束,对 $month 等使用词汇表,但如果可以想到或已经存在类似但更优雅的解决方案或方法,我不会感到惊讶。如果是这样,请让我知道他们。如果可以指出任何批评或潜在的陷阱,我也将不胜感激。
与类似问题的关系:
请注意,该问题不同于更基本的日期解析问题:
因为在我的例子中我无法指定或确定字符串的格式。另一方面,以下问题讨论了类似的任务:
- Extracting date from a string in Python
- Extract multiple date format from few string variables in php
- Extracting date from a string in PHP
我不确定最后一个是否重复,我最终不清楚 OP 想要解析什么(尽管 checkdate 和 date_parse 似乎是部分有用)。但是关于整个“mokey business”的第一个问题对于我的案例也是如此,并且已经通过模糊解析解决了
dparser.parse("monkey 2010-07-10 love banana",fuzzy=True)
最后,第二个包含很好的抓取正则表达式(几乎“模糊”)。
elegant 的 PS 我知道代码相当紧凑(对性能没有重大限制,因此可以使用“hacky”正则表达式)。
最佳答案
时间库
好吧,date_parse 的表现非常非常 很好,了解原因 很有教育意义。 PHP 函数 date_parse是 ext/date/lib 的一部分或 timelib,并且显然(尽管缺乏适当的文档)它在 C 中的实现(由 Derick Rethans 编写并从 Zend Engine 宏部分调用声明)使它成为一个聪明的工具:
- date_parse 已经模糊:文档页面上有很多警告(和提示)功能容忍和解析太多但显然它实际上是一个功能而不是错误(否则应该使用 date_parse_from_format 或相应的 DateTime::createFromFormat())
- date_parse 以相对聪明的方式使用(很多)正则表达式(基于 re2c )
- 除了过滤之外,这个“扫描仪”还寻找所有可能的单词和日期格式组合(从已知月份和时区的列表中),最后,通过寻找 YYYY、MM 和DD“分别”(与我需要做的非常相似)。
- date_parse 是一个真正的编译“扫描器”,带有前瞻逻辑和错误报告,可以由用户进一步处理(没有异常(exception),只是嵌套结果数组中的消息)。
- 甚至还有一个python package包装 timelib 的 C 代码(所以我什至不确定在“解析猴子业务”timelib 或 python-dateutil 中哪个最终更好)
测试和示例
就我而言,我未能从我的数据集中找到任何未被 date_parse 解析的输入示例,即:
echo FuzzyDateParser::fromText('banana 1/2/3');
echo FuzzyDateParser::fromText('Joe Soap was born on 12 February 1981'));
echo FuzzyDateParser::fromText('2005 Feb., reprint'));
echo FuzzyDateParser::fromText('!'); # will fail to parse, producing an empty string.
echo FuzzyDateParser::fromText('monkey 2010-07-10 loves bananas and php');
FuzzyDateParser 类的代码可以在这个 gist 中找到.它可以用作处理错误的模板,并实现从 date_parse 结果到自己的自定义逻辑的回退(我最终不必为我的案例做这件事)。
关于php - 从字符串中提取启发式(模糊)日期?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15350309/