PHP Strtotime -1month -2month

Это работало нормально вчера, без изменений кода.

echo date("M", strtotime("-3 month", time()) );
echo date("M", strtotime("-2 month", time()) );
echo date("M", strtotime("-1 month", time()) );
echo date("M", time());

Выход, который он производил вчера, был таким, каким вы ожидали бы - а.е., май, июнь, июль

Сегодня он повторяет май май июль июль

Любые идеи?

Спасибо заранее.

Ответ 1

Это может быть связано с ошибкой # 44073

Вы можете попробовать что-то вроде этого:

echo date("M", strtotime("-3 month", strtotime(date("F") . "1")) ) . "\n";
echo date("M", strtotime("-2 month", strtotime(date("F") . "1")) ) . "\n";
echo date("M", strtotime("-1 month", strtotime(date("F") . "1")) ) . "\n";
echo date("M", time()) . "\n";

(Решение найдено в разделе комментариев strtotime; direct ссылка)

И вывод:

Apr
May
Jun
Jul

Вид "обмана" с форматом даты и именем месяца и всем этим...

Ответ 2

Горден правильно определил проблему, но я хотел дать другое решение, которое было бы полезным, а не техническим. Просто используйте "первый день" или "последний день" в своем strtotime. Например, следующие примеры преодолевают проблему 31-го числа месяца:

// Today is May 31st
//All the following return 2012-04-30
echo date('Y-m-d', strtotime("last day of -1 month"));
echo date('Y-m-d', strtotime("last day of last month"));
echo date_create("last day of -1 month")->format('Y-m-d'); 

// All the following return 2012-04-01
echo date('Y-m-d', strtotime("first day of -1 month")); 
echo date('Y-m-d', strtotime("first day of last month"));
echo date_create("first day of -1 month")->format('Y-m-d');

Ответ 3

Попробуйте это вместо strtotime:

mktime(0, (date("n") - 3 + 12) % 12, 1)

Идея состоит в том, чтобы взять текущий номер месяца (date("n")), вычесть количество месяцев от него, которое вы хотите (здесь -3), добавить 12 к нему, а затем получить по модулю 12.

Ответ 4

Это известное и ожидаемое поведение. Причина этого в том, что месяц является относительной датой без фиксированной длины. Из http://www.gnu.org/software/tar/manual/html_node/Relative-items-in-date-strings.html#SEC120

Единица смещения времени может быть выбрана по строке "год" или "месяц" для перемещения целыми годами или месяцами. Это нечеткие единицы, поскольку годы и месяцы не одинаковы. Более точные единицы - "две недели, которые стоят 14 дней", неделя стоит 7 дней, "день стоит 24 часа", "час стоит 60 минут", "минута" или "мин", 60 секунд, и "секунда" или "секунда в одну секунду". Суффикс на этих устройствах принимается и игнорируется.

Следовательно (внимание мое)

Fuzz в единицах может вызвать проблемы с относительными элементами. Например, "2003-07-31 -1 месяц может быть оценен до 2003-07-01, поскольку 2003-06-31 является недопустимой датой. Чтобы более надежно определить предыдущий месяц, вы можете запросить месяц до 15 числа текущего месяца. Например:

$ date -R
Thu, 31 Jul 2003 13:02:39 -0700
$ date --date='-1 month' +'Last month was %B?'
Last month was July?
$ date --date="$(date +%Y-%m-15) -1 month" +'Last month was %B!'
Last month was June!

Вышеуказанное может быть выражено в PHP как

echo date('M', strtotime(date('Y-m-') . '15 -1 month'));

Также см. пункты ниже http://bugs.php.net/bug.php?id=22486

Ответ 5

Из PHP 5.3 (Ссылка: https://bugs.php.net/bug.php?id=44073) и выше вы можете сделать:

"first day of +1 month" или "first day of next month" или даже "last day of next month"

Пример:

$date = '2015-12-31';

echo date("Y-m-d", strtotime($date ."first day of previous month"));

Будет производить: 2015-11-01 Это не вычисляет дни на основе времени +30 дней.

Ответ 6

простым способом может быть запись этого типа

эхо-дата ( "M", strtotime ( "в этом году +3 месяца" ));

или

эхо-дата ( "M", strtotime ( "в этом месяце -3 месяца" ));

зависит от того, как вы его используете.