Насколько я могу судить, эта проблема очень ограничена по объему, поэтому вам, скорее всего, лучше всего протестировать один тип ошибки и исправить ее.
Все, что вы хотите сделать, - это убедиться, что добавление «одного месяца» к более поздней дате, такой как 29-е, 30-е или 31-е, не подтолкнет вас на 1-е, 2-е или 3-е число следующего следующего месяца.
Способ работы date_modify () (с использованием его в качестве примера для даты «2012-01-31» со строкой, такой как «+1 месяц») заключается в том, что сначала он увеличивает номер месяца на 1, а затем находит 31-й день. с начала этого месяца. Вот почему он распространяется на 3 марта.
Когда это не то, что вы хотели, все, что вам нужно сделать, это снова использовать date_modify (), теперь попросив его вернуться назад на несколько дней (в данном примере 3 дня). Поскольку вы хотите вернуться только к последнему дню предыдущего месяца, количество дней, которое вы хотите вернуть, всегда совпадает с днем месяца в вашей ошибочной дате.
Осталось только убедиться, что вы не применяете это исправление, когда оно не нужно, например, когда PHP улучшится в будущем. Это относительно просто, потому что область возможных проблемных ситуаций очень ограничена.
- (1) Проблема возникает только при добавлении месяцев к датам 29, 30 или 31
- (2) При возникновении проблемы итоговая дата всегда равна 1, 2 или 3.
Мой код ниже добавляет «+1 месяц», проверяет, вызвало ли это дикое изменение дня месяца с чего-то высокого на что-то низкое, и корректирует дату, если это так.
//Create the date, store its day-of-month, and add X months
$myDateTimeISO = "2012-01-31";
$addThese = 1;
$myDateTime = new DateTime($myDateTimeISO);
$myDayOfMonth = date_format($myDateTime,'j');
date_modify($myDateTime,"+$addThese months");
//Find out if the day-of-month has dropped
$myNewDayOfMonth = date_format($myDateTime,'j');
if ($myDayOfMonth > 28 && $myNewDayOfMonth < 4){
//If so, fix by going back the number of days that have spilled over
date_modify($myDateTime,"-$myNewDayOfMonth days");
}
echo date_format($myDateTime,"Y-m-d");
Результаты: 2012-02-29 (да, это был високосный год).
PS: Если вы хотите добавить годы, проблема и симптомы почти идентичны. Опять же, вам просто нужно проверить, равен ли день месяца 1/2/3, а днем месяца 29/30/31. Если это так, вам нужно вернуться к «-X дням», используя date_modify, где X - итоговый день месяца.