PHPを使用して長い文字列で日付を検索する

私は文書のコレクションを持っており、私はそれらの日付を引き出​​すことを試みています。彼らはプレーンテキストとHTMLがほとんどですが、それらはすべて英語の日付ですが、主に使用する日付形式です。長いテキスト列の中でこのような日付を見つけて解析するにはどうすればいいですか?

updated 2011-03-21T00:43:14
Sunday, March 20, 2011
Wednesday, March 16, 2011 | 11:25 AM
March 20, 2011 @ 12:21 pm
May 5, 2011
Published March 19, 2011
Some text here (March 19, 2011)
10/28/2011 21:16
4
@MOleYArd、私はあなたの助言を取り、正規表現に頼った。
追加された 著者 Xeoncross,
私は答えません、ちょうど助言を与える。これは間違いなく正規表現の仕事です。可能な日付形式のセットが限られている場合は、独自の小さなクラス/メソッドを記述する必要があります。 functions-online.com/preg_match_all.html を見て、サンプルテキストを投稿してください。それはあなたを大きく助けることができます。
追加された 著者 MOleYArd,

2 答え

今夜は少し時間があったので、私は数字のグループ分けを探していることを知って、いくつかの正規表現で遊んだ。以下はすべて下のすべての部分を解析します。また、foreachは単なる例です。正規表現は preg_match_all()用に構築されているので、問題のない文字列からすべての日付を取り出すことができるはずです。

$str = 'updated 2011-03-21T00:43:14
Sunday, March 20, 2011
Wednesday, March 16, 2011 | 11:25 AM
March 20, 2011 @ 12:21 pm
May 5, 2011
Published March 19, 2011
Some text here (March 19, 2011)
10/28/2011 21:16
Author Name on Mar 17th 2011 ...
Location, ABBR., Jan. 8, 2008
01/07/2008 (6:00 pm)
Published under recent news one March 17, 2011. Now onto other things!
By Author Name and Company 03/19/2011 09:59
Posted by Author Name on March 16, 2011 at 03:20 PM EDT';

$months = array(
    'jan', 'january',
    'feb', 'febuary',
    'mar', 'march',
    'apr', 'april',
    'may',
    'june',
    'july',
    'aug', 'august',
    'sept', 'september',
    'oct', 'october',
    'nov', 'november',
    'dec', 'december',
);

header('Content-Type: text/plain');

foreach(explode( "\n", $str) as $line)
{
    $line = str_replace(array('@', '|', '(', ')', 'at', 'on', 'am', 'pm'), '', mb_strtolower(trim($line)));

    if(preg_match('/([a-z]+[, .]+)?(\d.+?)\D*?$/m', $line, $match))
    {
        $date = '';

       //Is that word a valid month?
        if(in_array(trim($match[1], ',. '), $months))
        {
            $date = $match[1];
        }

        $date .= $match[2];

        if( ($date = strtotime($date)) !== false)
        {
            echo "Converted '" . $line . "' to '" . date( 'F jS, Y h:i:s A', $date) . "'\n";
            continue;
        }
    }
    else
    {
        print "Failed to find anything\n";
    }

    echo "Could not parse line - '" . $line . "'\n";//Need additional processing/regex here
}

これはちょっとハッキリした感じで、おそらく誰かがより良いパーサーで答えることができます。

2
追加された

strtotime 機能をご覧ください。

// Output: March 20th, 2011 12:00:00 AM
echo date( 'F jS, Y h:i:s A', strtotime( "Sunday, March 20, 2011"));

Edit: Here is a more complete example showing how to parse a bunch of the dates provided.

<?php
$dates = array( '03/19/2011 09:59', 'Wednesday, March 16, 2011 | 11:25 AM', 'Sunday, March 20, 2011', 'March 20, 2011 @ 12:21 pm', 'May 5, 2011');
foreach( $dates as $date)
{
    echo $date . ' ---- ' . date( 'F jS, Y h:i:s A', strtotime( str_replace( array( '@', '|'), '', $date))) . "
\n"; }

デモ

もちろん、一部の日付は、日付の形式 - これらの場合、日付を抽出するか、strtotimeに適した文字列に変換するために、いくつかの追加のフィルタリング/解析を行う必要があります。

Edit: Since there's an interest in further processing of the input string, here is an example of how you can parse the text without using a regex to get the dates out. Notice how some of the dates just can't be extracted, for this you will either need more string processing, or to use a regex.

補足として、もし正規表現が日付を含む行の多くの変形のうちの1つだけであるならば、私は正規表現を使って調べるでしょう。ただし、指定された文字列が日付が見つかる唯一の形式であれば、文字列処理で十分です。

$str = 'updated 2011-03-21T00:43:14
Sunday, March 20, 2011
Wednesday, March 16, 2011 | 11:25 AM
March 20, 2011 @ 12:21 pm
May 5, 2011
Published March 19, 2011
Some text here (March 19, 2011)
10/28/2011 21:16
Author Name on Mar 17th 2011 ...
Location, ABBR., Jan. 8, 2008
01/07/2008 (6:00 pm)
By Author Name and Company 03/19/2011 09:59
Posted by Author Name on March 16, 2011 at 03:20 PM EDT';

foreach( explode( "\n", $str) as $line)
{
    $line = str_replace( array( '@', '|', '(', ')'), '', trim( $line));
    $line = strip_tags( $line);
    if( ($time = strtotime( $line)) === false)
    {
        echo "Could not parse line - '" . $line . "'\n";//Need additional processing/regex here
        continue;
    }
    echo "Converted '" . $line . "' to '" . date( 'F jS, Y h:i:s A', $time) . "'\n";
}

デモ。

最終編集:

最後に、より多くの日付を解析するためにテキスト処理を行う方法の例。

foreach( explode( "\n", $str) as $line)
{
    $line = str_replace( array( '@', '|', '(', ')', 'Published', '...'), '', trim( $line));
    $line = strip_tags( trim( $line));
    if( ($time = strtotime( $line)) === false)
    {
        if( !(($on_position = stripos( $line, 'on')) === false))
        {
            $line = substr( $line, $on_position + 3);
            if( ($time = strtotime( trim( $line))) === false)
            {
                echo "Could not parse line that contains 'on' - '" . $line . "'\n";
                continue;
            }
        }
        echo "Could not parse line - '" . $line . "'\n";
        continue;
    }
    echo "Converted '" . $line . "' to '" . date( 'F jS, Y h:i:s A', $time) . "'\n";
}

デモ

2
追加された
@Michael、私は考えることができるすべてのユースケースを扱う答えを投稿しました。おそらくあなたたちはそれを拡張することができます。
追加された 著者 Xeoncross,
@Michael - もちろん、 strtotime()はすべての日付を解析するわけではありませんが、それらを扱うことができます。私はより完全なデモンストレーションで自分の答えを更新していましたが、あなたはそれらの日付と他のものの両方を正確に解析することができます。
追加された 著者 nickb,
完全なソリューションは1つの質問の範囲外です。これは文字列を日付に変換する1つの方法であり、質問の正当な使用例です。すべての日付を抽出するには、重いテキストの解析や非常に複雑な正規表現が必要です。私はあなたが私が公式化するとは思わないと思いますか?私の答えは、より大きな問題に対する基本的な解決策です。
追加された 著者 nickb,
@ JaredFarrish - チップをありがとう!私は通常、代わりに "ソース"リンクをクリックします。
追加された 著者 nickb,
-1そこには、 strtotime()が処理しない多くの日付書式があります。 March 20、2011 @ 12:21 pm などです。また、 2011年3月16日| 11:25 AM
追加された 著者 Michael Berkowski,
どのようにして、それらの文脈を文脈から抽出することを提案していますか?この答えはまだ完全ではありません。
追加された 著者 Michael Berkowski,
出力を読みやすくするには、
 タグを使用してください。  codepad.viper-7.com/pKyjbh  codepad.viper-7.com/q9kYP5 
追加された 著者 Jared Farrish,
それでも解決策を待っている@Michael。私は当面は this に答えています。
追加された 著者 Linus Kleen,
PHP - 日本のコミュニティ [ja]
PHP - 日本のコミュニティ [ja]
4 参加者の

このグループではPHPについて話します。 パートナー:kotaeta.com