我建议处理它们以进行概括(基本上删除数字和名称并使其成为占位符),然后按类似格式分组,以便您有一个示例组可以使用。
例如,20th, 21st August 1987
则变为[number][postfix], [number][postfix] [month] [year]
(假设 a<number><st|th|rd|nd>
被识别为数字且后缀和月份很明显,并且年份是 4 位数字)。
从那里,您会发现有多少遵循该模式,然后找到您需要匹配的独特模式。然后,您至少可以有一个样本来测试您希望使用的任何类型的算法(正则表达式可能是您最好的选择,因为它可以检测重复的模式(#th[, $th[, ...]]
)和日期名称。)
看来您可能想按模式分解它(鉴于您提供的内容)。因此,例如首先打破年度信息:
(.*?)([0-9]{4})(?:, |$)
然后你需要把它分解成几个月
(.*?)(January|February|...)(?:, |$)
然后你想要那个月内包含的天数:
(?:([0-9]{1,2})(?:st|nd|rd|th)(?:, )?)*(?:, |$)
然后是编译信息。但同样,这只是在使用你在我面前的东西。最终,您需要知道您正在使用什么样的数据以及您想如何处理它。
更新
所以,我忍不住尝试自己解决这个问题。我想知道我使用的方法有些准确,而且我没有把烟吹到你的裙子上。话虽如此,这就是我想出的。请注意,这是在 PHP 中的几个原因:
- PHP 更容易上手
- 我觉得如果这是一个可行的解决方案,你应该努力把它移植过来。:咧嘴笑:
无论如何,这是源代码和演示输出。享受。
<?php
$samples = array(
'20th, 21st August 1897',
'31st May, 1st June 1909',
'29th January 2007',
'10th, 11th, 12th May 1954',
'26th, 27th, 28th, 29th, 30th March 2006',
'27th, 28th, 29th, 30th November, 1st December 2006',
'30th, 31st, December 2010, 1st, 2nd January 2011'
);
//header('Content-Type: text/plain');
$months = array('january','february','march','april','may','june','july','august','september','october','november','december');
foreach ($samples as $sample)
{
$dates = array();
// find yearly information first
$yearly = null;
if (preg_match_all('/(?:^|\s)(?<month>.*?)\s?(?<year>[0-9]{4})(?:$|,)/',$sample,$yearly))
{//var_dump($yearly);
for ($y = 0; $y < count($yearly[0]); $y++)
{
$year = $yearly['year'][$y];
//echo "year: {$year}\r\n";
$monthly = null;
if (preg_match_all('/(?<days>(?:(?:^|\s)[0-9]{1,2}(?:st|nd|rd|th),?)*)\s?(?<month>'.implode('|',$months).')$/i',$yearly['month'][$y],$monthly))
{//var_dump($monthly);
for ($m = 0; $m < count($monthly[0]); $m++)
{
$month = $monthly['month'][$m];
//echo "month: {$month}\r\n";
$daily = null;
if (preg_match_all('/(?:^|\s)(?<day>[0-9]{1,2})(?:st|nd|rd|th)(?:,|$)/i',$monthly['days'][$m],$daily))
{//var_dump($daily);
for ($d = 0; $d < count($daily[0]); $d++)
{
$day = $daily['day'][$d];
//echo "day: {$day}\r\n";
$dates[] = sprintf("%d-%d-%d", array_search(strtolower($month),$months)+1, $day, $year);
}
}
}
}
$data = $yearly[1];
}
}
echo "<p><b>{$sample}</b> was parsed to include:</p><ul>\r\n";
foreach ($dates as $date)
echo "<li>{$date}</li>\r\n";
echo "</ul>\r\n";
}
?>
1897 年 8 月 21 日 20 日被解析为包括:
- 1897 年 8 月 20 日
- 8-21-1897
1909 年 5 月 31 日,6 月 1 日被解析为包括:
2007 年1 月 29 日被解析为包括:
1954 年 5 月 10 日、11 日、12 日被解析为包括:
- 1954 年 5 月 10 日
- 1954 年 5 月 11 日
- 1954 年 5 月 12 日
2006 年3 月 26 日、27 日、28 日、29 日、30 日被解析为包括:
- 2006 年 3 月 26 日
- 2006 年 3 月 27 日
- 2006 年 3 月 28 日
- 2006 年 3 月 29 日
- 2006 年 3 月 30 日
2006 年 11 月 27 日、28 日、29 日、11 月 30 日、12 月 1 日被解析为包括:
2010 年 12 月 30 日、31 日、2011 年 1 月 1 日、2 日被解析为包括:
- 2010 年 12 月 30 日
- 2010 年 12 月 31 日
- 1-1-2011
- 1-2-2011
为了证明我无所不能,http://www.ideone.com/GGMaH