Как получить предыдущий месяц и год относительно сегодняшнего дня, используя strtotime и date? - PullRequest
56 голосов
/ 30 марта 2011

Мне нужно получить предыдущий месяц и год относительно текущей даты.

Однако см. Следующий пример.

// Today is 2011-03-30
echo date('Y-m-d', strtotime('last month'));

// Output:
2011-03-02

Такое поведение понятно (до определенного момента), из-зана разное количество дней в феврале и марте, и код в приведенном выше примере - это то, что мне нужно, но работает только на 100% правильно в период с 1 по 28 числа каждого месяца.

Итак, как получить последний месяц И год(представьте себе date("Y-m")) самым элегантным из возможных способов, который работает на каждый день года?Оптимальное решение будет основано на разборе аргументов strtotime.

Обновление.Чтобы немного уточнить требования.

У меня есть фрагмент кода, который получает статистику за последние пару месяцев, но я сначала показываю статистику за прошлый месяц, а затем загружаю другие месяцы, когда это необходимо.Это намеченная цель.Итак, в течение ЭТОГО месяца я хочу выяснить, какой месяц-год мне нужно выбрать, чтобы загрузить ПРЕДЫДУЩУЮ статистику за месяц.

У меня также есть код, который учитывает часовой пояс (сейчас это не очень важно),и он принимает strtotime -совместимую строку в качестве входных данных (для инициализации внутренней даты), а затем позволяет настраивать дату / время, также используя strtotime -совместимые строки.

Я знаю, что это можно сделать с помощьюнесколько условных выражений и базовая математика, но это действительно грязно, по сравнению с этим, например (если он работал правильно, конечно):

echo tz::date('last month')->format('Y-d')

Итак, мне нужны ТОЛЬКО предыдущие месяц и год, в strtotime -совместимая мода.

Ответ (спасибо, @dnagirl):

// Today is 2011-03-30
echo date('Y-m-d', strtotime('first day of last month')); // Output: 2011-02-01

Ответы [ 14 ]

48 голосов
/ 30 марта 2011

Посмотрите на класс DateTime. Он должен делать вычисления правильно, а форматы даты совместимы с strttotime. Что-то вроде:

$datestring='2011-03-30 first day of last month';
$dt=date_create($datestring);
echo $dt->format('Y-m'); //2011-02
27 голосов
/ 30 марта 2011

, если сам день не имеет значения, сделайте это:

echo date('Y-m-d', strtotime(date('Y-m')." -1 month"));
23 голосов
/ 31 мая 2012

Я нашел ответ, потому что у меня была та же самая проблема сегодня, которая является 31-ой. Это не ошибка в php , как некоторые предполагают, но ожидаемая функциональность (в некоторых случаях). В соответствии с этим post , что фактически делает strtotime, устанавливает месяц назад на единицу и не изменяет количество дней. Так что на сегодняшний день, 31 мая, он ищет 31 апреля, который является недействительной датой. Таким образом, это займет 30 апреля, а затем прибавит 1 день после него и даст 1 мая.

В вашем примере 2011-03-30 он вернется на один месяц к 30 февраля, что недопустимо, поскольку в феврале всего 28 дней. Затем он принимает разницу этих дней (30-28 = 2) и затем перемещается на два дня позже 28 февраля, то есть 2 марта.

Как отмечали другие, лучший способ получить «последний месяц» - это добавить «первый день» или «последний день», используя объект strtotime или DateTime:

// Today being 2012-05-31
//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');

Таким образом, используя их, можно создать диапазон дат, если вы делаете запрос и т. Д.

9 голосов
/ 12 ноября 2013

Если вы хотите, чтобы предыдущий год и месяц были связаны с определенной датой, а DateTime был доступен, вы можете сделать это:

$d = new DateTime('2013-01-01', new DateTimeZone('UTC')); 
$d->modify('first day of previous month');
$year = $d->format('Y'); //2012
$month = $d->format('m'); //12
6 голосов
/ 26 августа 2016

strtotime имеют второй параметр timestamp, который устанавливает первый параметр относительно второго параметра.Таким образом, вы можете сделать это:

date('Y-m', strtotime('-1 month', time()))
6 голосов
/ 31 июля 2014
date('Y-m', strtotime('first day of last month'));
5 голосов
/ 30 марта 2011

если я правильно понимаю вопрос, вы просто хотите, чтобы в прошлом месяце и в каком году он был:

<?php

  $month = date('m');
  $year = date('Y');
  $last_month = $month-1%12;
  echo ($last_month==0?($year-1):$year)."-".($last_month==0?'12':$last_month);

?>

Вот пример: http://codepad.org/c99nVKG8

4 голосов
/ 30 марта 2011

Эх, это не ошибка, как упомянул один человек. это ожидаемое поведение, так как количество дней в месяце часто отличается. Самый простой способ получить предыдущий месяц с использованием strtotime - это использовать -1 месяц с первого числа этого месяца.

$date_string = date('Y-m', strtotime('-1 month', strtotime(date('Y-m-01'))));
2 голосов
/ 30 марта 2011

Я думаю, вы нашли ошибку в функции strtotime.Всякий раз, когда мне нужно обойти это, я всегда занимаюсь математикой значений месяца / года.Попробуйте что-то вроде этого:

$LastMonth = (date('n') - 1) % 12;
$Year      =  date('Y') - !$LastMonth;
1 голос
/ 31 мая 2012

Это потому, что в предыдущем месяце меньше дней, чем в текущем месяце.Я исправил это, сначала проверив, есть ли в предыдущем месяце меньше дней, чем текущий, и изменив расчет, основанный на нем.

Если у него меньше дней, получите последний день -1 месяца, иначе текущий день-1 месяц:

if (date('d') > date('d', strtotime('last day of -1 month')))
{
    $first_end = date('Y-m-d', strtotime('last day of -1 month'));
}
else
{
    $first_end = date('Y-m-d', strtotime('-1 month'));
}
...