PHP DateTime::modify adding and subtracting months

2019-01-02 18:11发布

I've been working a lot with the DateTime class and recently ran into what I thought was a bug when adding months. After a bit of research, it appears that it wasn't a bug, but instead working as intended. According to the documentation found here:

Example #2 Beware when adding or subtracting months

<?php
$date = new DateTime('2000-12-31');

$date->modify('+1 month');
echo $date->format('Y-m-d') . "\n";

$date->modify('+1 month');
echo $date->format('Y-m-d') . "\n";
?>
The above example will output:
2001-01-31
2001-03-03

Can anyone justify why this isn't considered a bug?

Furthermore does anyone have any elegant solutions to correct the issue and make it so +1 month will work as expected instead of as intended?

18条回答
浅入江南
2楼-- · 2019-01-02 18:28

I needed to get a date for 'this month last year' and it becomes unpleasant quite quickly when this month is February in a leap year. However, I believe this works... :-/ The trick seems to be to base your change on the 1st day of the month.

$this_month_last_year_end = new \DateTime();
$this_month_last_year_end->modify('first day of this month');
$this_month_last_year_end->modify('-1 year');
$this_month_last_year_end->modify('last day of this month');
$this_month_last_year_end->setTime(23, 59, 59);
查看更多
旧时光的记忆
3楼-- · 2019-01-02 18:29

In conjunction with shamittomar's answer, it could then be this for adding months "safely":

/**
 * Adds months without jumping over last days of months
 *
 * @param \DateTime $date
 * @param int $monthsToAdd
 * @return \DateTime
 */

public function addMonths($date, $monthsToAdd) {
    $tmpDate = clone $date;
    $tmpDate->modify('first day of +'.(int) $monthsToAdd.' month');

    if($date->format('j') > $tmpDate->format('t')) {
        $daysToAdd = $tmpDate->format('t') - 1;
    }else{
        $daysToAdd = $date->format('j') - 1;
    }

    $tmpDate->modify('+ '. $daysToAdd .' days');


    return $tmpDate;
}
查看更多
唯独是你
4楼-- · 2019-01-02 18:29

Extension for DateTime class which solves problem of adding or subtracting months

https://gist.github.com/66Ton99/60571ee49bf1906aaa1c

查看更多
还给你的自由
5楼-- · 2019-01-02 18:30

you can actually do it with just date() and strtotime() as well. For example to add 1 month to todays date:

date("Y-m-d",strtotime("+1 month",time()));

if you are wanting to use the datetime class thats fine too but this is just as easy. more details here

查看更多
春风洒进眼中
6楼-- · 2019-01-02 18:32
     $date = date('Y-m-d', strtotime("+1 month"));
     echo $date;
查看更多
墨雨无痕
7楼-- · 2019-01-02 18:34

I found a shorter way around it using the following code:

                   $datetime = new DateTime("2014-01-31");
                    $month = $datetime->format('n'); //without zeroes
                    $day = $datetime->format('j'); //without zeroes

                    if($day == 31){
                        $datetime->modify('last day of next month');
                    }else if($day == 29 || $day == 30){
                        if($month == 1){
                            $datetime->modify('last day of next month');                                
                        }else{
                            $datetime->modify('+1 month');                                
                        }
                    }else{
                        $datetime->modify('+1 month');
                    }
echo $datetime->format('Y-m-d H:i:s');
查看更多
登录 后发表回答