4

strtotimeで順序値を使用すると、予期しない結果が生じることがあります。たとえば、なぜ

date("M j", strtotime("second Tuesday February 2011"))

結果は「2月15日」になります(これは実際には2011年の第3火曜日ですか?

4

3 に答える 3

5

'of'がありません。

$ php -r'echo date( "M j"、strtotime( "2011年2月第2火曜日"));'
2月15日

$ php -r'echo date( "M j"、strtotime( "2011年2月の第2火曜日"));'
2月8日

PHPバージョン:

$ php -v
PHP 5.3.3(cli)(ビルド:2010年8月22日19:41:55)
Copyright(c)1997-2010 PHP Group
Zend Engine v2.3.0、Copyright(c)1998-2010 Zend Technologies

ドキュメントには、この原因が記載されています。

また、「序数スペースのデイネームスペース」の「の」と「最後の」スペースのデイネームスペースの「の」が特別なことをすることにも注意してください。

  • 曜日を1に設定します。
  • 「」の「通常の曜日名」は別の日に進みません。(例:「2008年7月の第1火曜日」は「2008-07-01」を意味します)。
  • 「序数の曜日名」は別の日に進みます。(例:「2008年7月の第1火曜日」は「2008-07-08」を意味します。上記のリストのポイント4も参照してください)。
于 2011-01-25T20:13:56.667 に答える
2

strtotime()のマニュアルは、あなたが何を求めているかを示しています

5.2.7より前のPHP5では、その曜日が月の最初の日である月の特定の曜日の特定のオカレンスを要求すると、返されるタイムスタンプに誤って1週間が追加されていました。これは、5.2.7以降のバージョンで修正されています。

要するに、それはあなたが使用しているバージョンのバグです。

ある種の適用可能な修正を探している場合、序数の値を削除することは機能しているようです(1番目/2番目/3番目が丸1週間を示しているかのように)

echo date("M j", strtotime("Tuesday February 2011")), '<br>';
echo date("M j", strtotime("first Tuesday February 2011")), '<br>';
echo date("M j", strtotime("second Tuesday February 2011")), '<br>';
echo date("M j", strtotime("third Tuesday February 2011")), '<br>';
于 2011-01-25T20:13:24.560 に答える
0

少なくともPHP<5.3のバージョンでは、通常の日付計算を処理するためにstrtotimeに依存することは安全ではないようです。(私は5.2.9と5.2.11でテストしましたが、バグが5.2.7で修正されたというオンラインドキュメントの主張にもかかわらず、どちらも機能しません。)

提案されているように「of」を追加すると、明らかにphp 5.3以降でのみ機能し、序数を完全に削除すると「最初の」オカレンスが返されますが、他の序数は7日間オフになります。

PHP 5.2の最適なソリューションは、次のようになります。

$recurrOrdinal = "last";
$dayOfWeek = "Thursday";
$monthYear = "March 2011";

echo ordinalDate($recurrOrdinal, $dayOfWeek, $monthYear);

function ordinalDate($recurrOrdinal, $dayOfWeek, $monthYear)    {
    $firstDate = date("j", strtotime($dayOfWeek . " " . $monthYear) );
    if ($recurrOrdinal == "first")
    $computed = $firstDate; 
    elseif ($recurrOrdinal == "second")
    $computed = $firstDate + 7; 
    elseif ($recurrOrdinal == "third")
    $computed = $firstDate + 14; 
    elseif ($recurrOrdinal == "fourth")
    $computed = $firstDate + 21; 
    elseif ($recurrOrdinal == "last")   {
    if ( ($firstDate + 28) <= date("t", strtotime($monthYear)) )
        $computed = $firstDate + 28; 
    else
        $computed = $firstDate + 21; 
    }
    return date("Y-m-d", strtotime($computed . " " . $monthYear) );
}
于 2011-01-26T15:11:35.927 に答える