Проблема с функцией php strtotime при использовании порядковых значений - PullRequest
4 голосов
/ 25 января 2011

Иногда я получаю неожиданные результаты при использовании порядковых значений с strtotime. Например, почему

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

результат в "15 февраля" (что на самом деле третий вторник в 2011 году?

Ответы [ 3 ]

5 голосов
/ 25 января 2011

Вам не хватает «из».

$ php -r 'дата эха ("M j", strtotime ("второй вторник февраля 2011"));'
15 февраля

$ php -r 'дата эха ("M j", strtotime ("второй вторник февраля 2011"));'
8 февраля

Версия PHP:

$ php -v
PHP 5.3.3 (cli) (сборка: 22 августа 2010 19:41:55)
Copyright (c) 1997-2010 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies

Документация сообщает причину этого:

Также обратите внимание, что "из" в "порядковом пробел день имя пробел '' 'и' 'последний' космическое имя дня что-то особенное.

  • Устанавливает день месяца равным 1.
  • "порядковый номер дня" из 'не перейти к другому дню. (Пример: «Первый вторник июля 2008 года» означает "2008-07-01").
  • "порядковый день" делает перейти к другому дню. (Пример: «Первый вторник июля 2008» означает «2008-07-08», см. Также пункт 4 в список выше).
2 голосов
/ 25 января 2011

Руководство для strtotime () говорит о том, что вы ищете

В PHP 5 до 5.2.7, запрашивая данное вхождение данного дня недели в месяц, когда этот будний день был первый день месяца будет неправильно добавить одну неделю к возвращенная метка времени. Это было исправлено в 5.2.7 и более поздних версиях.

Короче говоря, это ошибка в используемой версии.

Если вы ищете какое-то применимое исправление, кажется, что отбрасывание порядкового значения сработает (как будто первая / вторая / третья указывают на полные недели)

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>';
0 голосов
/ 26 января 2011

Похоже, небезопасно полагаться на strtotime, чтобы иметь дело с вычислениями порядковых дат - по крайней мере, в версиях PHP <5.3.(Я тестировал с 5.2.9 и 5.2.11, и ни один из них не работает, несмотря на утверждение в онлайн-документации о том, что ошибка была исправлена ​​в 5.2.7.) </p>

Добавление «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) );
}
...