Выбрать месяц из DateTime PHP?

Я хочу сделать массив предыдущего месяца 1-го и последнего дня. Из моего стартового \DateTime $date=2018-04-30. Когда я меняю свой начальный \DateTime на 2018-05-31, и мой ожидаемый результат представляет собой массив, содержащий:

[
  ['2018-03-01', 2018-03-31],
  ['2018-02-01', 2018-02-28],
  ['2018-01-01', 2018-01-31],
  ['2018-01-01', 2018-03-31],
  ['2017-03-01', 2018-03-31],
]

На данный момент я сделал:

$monthAgoStart = clone $date;
$monthAgoEnd = clone $date;
$month2agoStart = clone $date;
$month2agoEnd = clone $date;
$month3agoStart = clone $date;
$month3agoEnd = clone $date;
$currentYearStart = clone $date;
$yearAgo = clone $date;
$monthAgoStart->modify('first day of previous month');
$monthAgoEnd->modify('last day of previous month');
$month2agoStart->modify('first day of this month')->modify('-2 months');
$month2agoEnd = new \DateTime($month2agoEnd->modify('-1 months')->format('y-m-0'));
$month3agoStart= new \DateTime($month3agoStart->modify('-3 months')->format('y-m-1'));
$month3agoEnd = new \DateTime($month3agoEnd->modify('-3 months')->format('y-m-0'));
$currentYearStart->modify('first day of January');
$yearAgo->modify('-12 months');

Массив результатов:

$dates = [
  'ago1month' => ["start" => $monthAgoStart, "end" => $monthAgoEnd],
  'ago2month' => ["start" => $month2agoStart, "end" => $month2agoEnd],
  'ago3month' => ["start" => $month3agoStart, "end" => $month3agoEnd],
  'yearStart' => ["start" => $currentYearStart, "end" => $monthAgoEnd],
  'yearAgo' => ["start" => $yearAgo, "end" => $monthAgoEnd],
];

Мой код генерирует:

{"ago1month":{
         "start":{"date":"2018-03-01"},
         "end":{"date":"2018-03-31"}
    },
    "ago2month":{
         "start":{"date":"2018-02-01"},
         "end":{"date":"2018-02-28 "}
    },
    "ago3month":{
         "start":{"date":"2018-01-01 "},
         "end":{"date":"2017-12-31"}
    },
    "yearStart":{ 
        "start":{"date":"2018-01-01"},
        "end":{"date":"2018-03-31"}
    },
"yearAgo":{ 
        "start":{"date":"2017-04-30"},
        "end":{"date":"2018-03-31 "}
    }
}

Как лучше всего решить мою проблему? Я планировал сделать строки и создать new DateTime для каждой записи массива, но хочу убедиться, нет ли другого способа сделать это. Все еще ошибаюсь: "yearAgo":{ "start":{"date":"2017-04-30"}}"ago3month":{"end":{"date":"2017-12-31"}}

Я не понимаю ваш ожидаемый массив. Особенно ['2018-01-01', 2018-01-31], ['2018-01-01', 2018-03-31],. Вы имели в виду 2018-01-31 вместо 2018-03-31? Но тогда он будет дублироваться с приведенным выше ..

Xatenev 20.07.2018 15:23

Почему -12 месяцев с 30 апреля или 31 мая вернет 2017-03-01?

Devon 20.07.2018 15:24

@Xatenev кажется, что только первые 3 строки относятся к предыдущим месяцам, последние две должны быть в последнем квартале и в прошлом году

Karsten Koop 20.07.2018 15:26

Я думаю, вам было бы намного легче, если бы вы использовали DateTimeImmutable вместо DateTime. Вам не нужно ничего клонировать, и вы избежите изменения ваших базовых объектов при их изменении.

iainn 20.07.2018 15:28

Такое ощущение, что у вас есть рабочий код. Если вам нужен совет по уточнению, возможно, перейдите на CodeReview. Если у вас есть «проблема», мне это непонятно.

mickmackusa 20.07.2018 16:04

@mickmackusa Мой код работает не так, как ожидалось. Я не хочу, чтобы использовалась какая-либо функция format, и мой код работал. Должен ли я создавать new DateTime (string) для каждого элемента моего массива? Других решений нет?

pvaitonis 20.07.2018 16:07

@mickmackusa Перекрестно размещено и скоро будет закрыто на Code Review. Вопрос должен был быть убран здесь вместо того, чтобы размещать перекрестные сообщения.

Mast 23.07.2018 08:34

@Mast выглядит так, как будто OP вытащил его Я сказал, что вопрос мне непонятен.

mickmackusa 23.07.2018 08:48
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
8
124
1

Ответы 1

При получении последнего дня месяца вы должны использовать t из Формат даты.

Вы также можете упростить свой код и упростить его чтение, клонируя $ date, когда вам это нужно, или используя DateTimeImmutable.

$month3agoEnd = (clone $date)->modify('-3 months')->format('Y-m-t');

Как и ожидалось, это 2018-03-31. Использование Y-m-0 возвращает 2018-03-0, который вы обработали внутри нового объекта \ DateTime, поэтому ваш код фактически записывается как:

 $month3agoEnd = new DateTime('2018-03-0');

Это фактически возвращает новый экземпляр DateTime, установленный на 2018-02-28, поэтому я не уверен, как вам удалось получить 2017-12-31.

$month3agoEnd = (clone $date)->modify('-3 months')->format('Y-m-t'); А как насчет решения php 5.6?
pvaitonis 23.07.2018 09:43

@pvaitonis Это не будет работать в версии 5.6, но срок службы версии 5.6 почти подошел к концу, и я не знаю ни одного дистрибутива ОС, поддерживающего версию 5.6 дольше. Поэтому я бы не рекомендовал создавать новые проекты для 5.6. php.net/supported-versions.php. Вы все равно можете использовать DateTimeImmutable или просто использовать clone $ date в отдельной строке.

Devon 23.07.2018 14:14

Другие вопросы по теме