Search code examples
phpdatedatetime-formatstrtotime

Using "first day this month" with strtotime() returns the previous month


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?


Solution

  • 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