Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

strtotime('-1 month') returning wrong date if month have 31 days

Tags:

date

php

datetime

I'm trying make a function to return the exact date of previous months.

That is a example of my code:

// Dates in TimeStamp
$ts_now =  strtotime('now');
$ts_month1 = strtotime("-1 month", $ts_now);
$ts_month2 = strtotime("-2 month", $ts_now);
$ts_month3 = strtotime("-3 month", $ts_now);

// Dates Formated
$date_now = date('Y-m-d', $ts_now);
$date_month1 = date('Y-m-d', $ts_month1);
$date_month2 = date('Y-m-d', $ts_month2);
$date_month3 = date('Y-m-d', $ts_month3);

//Output
echo $date_now;    //2020-04-30
echo $date_month1; //2020-03-30
echo $date_month2; //2020-03-01
echo $date_month3; //2020-01-30

The problem is in $date_month2 that represents February, the output is 2020-03-01 instead 2020-02-29 and I suppose that problem will happen in months who have 30 days when present date have 31 days.

What is the best way to resolve that?

like image 650
Leandro Ribeiro Avatar asked Oct 18 '25 19:10

Leandro Ribeiro


1 Answers

As you can see working with the end of the month can be problematic because of how PHP works with dates. Your best bet is to go back to the beginning of the month, do your date math (i.e. go backwards in time), and then go to the date you want. That way you can check to see if the current day is greater than the number of days in month. If so, use the last day of the month instead.

function getMonthsAgo(int $n): string {
    $date = new DateTime();
    $day  = $date->format('j');
    $date->modify('first day of this month')->modify('-' . $n . ' months');
    if ($day > $date->format('t')) {
        $day = $date->format('t');
    }
    $date->setDate($date->format('Y'), $date->format('m'), $day);
    return $date->format('Y-m-d');
}

// Dates Formated
$date_now = date('Y-m-d');
$date_month1 = getMonthsAgo(1);
$date_month2 = getMonthsAgo(2);
$date_month3 = getMonthsAgo(3);

//Output
echo $date_now;
echo $date_month1;
echo $date_month2;
echo $date_month3;

Output:

2020-04-30
2020-03-30
2020-02-29
2020-01-30
like image 116
John Conde Avatar answered Oct 21 '25 08:10

John Conde