Home > Back-end >  Using "first day this month" with strtotime() returns the previous month
Using "first day this month" with strtotime() returns the previous month

Time:12-01

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

My application uses unix timestamps to set events for certain days. I use relative time format string in conjunction with these timestamps.

I 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>"; 
?>

Why is PHP displaying this unexpected behaviour? My guess is that my timestamp being right on the edge of two days is the root cause of my problem. Is this some weird timezone issue?. I assume not because 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?

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