Home > Blockchain >  PHP strtotime() 'first day of this month' returns the first day of the previous month if i
PHP strtotime() 'first day of this month' returns the first day of the previous month if i

Time:11-30

I think i might have found a bug in the strtotime() function.

My application uses timestamps in unixtime to set events for certain days. To click on moths just generates a list starting from

for($i = strtotime('first day of this month'); $i <= $someRandomEndDate; $i = strtotime('first day of next month', $i)){
    //do stuff here

}  

Now the problem lies that when I input the following line the wrong date is returned! It gives the last day of the previous month!

strtotime('first day of this month', $i)

date('M', $i) does output the expected month!

As an example a made this minimal code to reproduce the bug:

<?php
echo  "Last day of ".date('M-Y', 1677628800)." is: ".date('M-d-Y', strtotime('last day this month', 1677628800))." expecting march 31! <br>"; 
echo  "Last day of ".date('M-Y', 1677628800)." is: ".date('M-d-Y', strtotime('last day next month', 1677628800))." expecting april 30 in this case!<br>";
echo  "Last day of ".date('M-Y', 1677628800)." is: ".date('M-d-Y', strtotime('first day of next month', 1677628800))." expecting first day of april <br>";
echo  "Last day of ".date('M-Y', strtotime('first day of this month'))." is: ".date('M-d-Y', strtotime('last day this month', strtotime('first day of this month')))."<br>"; 
echo  "Last day of ".date('M-Y', strtotime('first day of this month'))." is: ".date('M-d-Y', strtotime('last day this month'))."<br>"; 
?>

Since i know of this problem and know that this function will only ever digest strtotime('fisrt day of this month') timestamps Ive implemented the following work around by just adding a day:

strtotime('last day of this month', strtotime(' 1 day', $i))

Minimal expaple of it working

echo  "Last day of ".date('M-Y', strtotime('first day of this month'))." is: ".date('M-d-Y', strtotime('last day of this month', strtotime(' 1 day', strtotime('first day of this month')))); 

My question really is, why is PHP displaying unexpected behaviour? My guess is that my timestamp being right on the edge of two days is the root cause of my problem. Maybe some weird timezone thing. But strtotime is coming up with these timestamps in the first place so that should not make any difference!

Anyone got a better solution then just adding a day? It feels kinda sloppy :P

CodePudding user response:

It seems if you're missing "of" in your strtotime rule it's not working as expeted.

If I took your minimal code to reproduce the bug and fix it to add missing "of" it's working.

<?php
echo  "Last day of ".date('M-Y', 1677628800)." is: ".date('M-d-Y', strtotime('last day of this month', 1677628800))." expecting march 31!" . PHP_EOL; 
echo  "Last day of ".date('M-Y', 1677628800)." is: ".date('M-d-Y', strtotime('last day of next month', 1677628800))." expecting april 30 in this case!" . PHP_EOL; 
echo  "Last day of ".date('M-Y', 1677628800)." is: ".date('M-d-Y', strtotime('first day of next month', 1677628800))." expecting first day of april" . PHP_EOL; 
echo  "Last day of ".date('M-Y', strtotime('first day of this month'))." is: ".date('M-d-Y', strtotime('last day of this month', strtotime('first day of this month'))). PHP_EOL; 
echo  "Last day of ".date('M-Y', strtotime('first day of this month'))." is: ".date('M-d-Y', strtotime('last day of this month')) . PHP_EOL; 

See: https://onlinephp.io/c/69307

CodePudding user response:

This is an XY Problem (if not an off-topic:typo question) because you did not use of in your "relative time format" expression.

Because all months start from 1, you can statically declare 01 as the first day of any month in the calendar year. For the last day of a month there is t that provides this value.

Code: (Demo)

echo date('M-01-Y');

echo "\n---\n";

echo date('M-01-Y', strtotime('next month'));

echo "\n---\n";

echo date('M-t-Y');

echo "\n---\n";

echo date('M-t-Y', strtotime('next month'));

Output:

Nov-01-2022
---
Dec-01-2022
---
Nov-30-2022
---
Dec-31-2022

Beyond that, the PHP docs explicitly have an entry for first day of.

Sets the day of the first of the current month. This phrase is usually best used together with a month name following it as it only effects the current month

  • Related