php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #66980 Last day of Fenruary
Submitted: 2014-03-29 07:57 UTC Modified: 2014-04-02 17:34 UTC
Votes:2
Avg. Score:3.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: tm8544 at hotmail dot com Assigned:
Status: Not a bug Package: Date/time related
PHP Version: 5.5.10 OS: Windows 7
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: tm8544 at hotmail dot com
New email:
PHP Version: OS:

 

 [2014-03-29 07:57 UTC] tm8544 at hotmail dot com
Description:
------------
Code in test script does not correctly produce the last day of february.

Also, if you change the test script to $string = "first day of " . $month;
also the first day of february is wrong (1.3.2014)

For all other months, it works as expected.

Test script:
---------------
<?php
   $months = array("january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december");
   
   foreach ($months as $month) {
      $string = "last day of " . $month;
      echo $month ." - " . date("j.n.Y", strtotime($string)) . "\r\n";
   }

?>

Expected result:
----------------
january - 31.1.2014
february - 28.2.2014
march - 31.3.2014
april - 30.4.2014
may - 31.5.2014
june - 30.6.2014
july - 31.7.2014
august - 31.8.2014
september - 30.9.2014
october - 31.10.2014
november - 30.11.2014
december - 31.12.2014


Actual result:
--------------
january - 31.1.2014
february - 31.3.2014
march - 31.3.2014
april - 30.4.2014
may - 31.5.2014
june - 30.6.2014
july - 31.7.2014
august - 31.8.2014
september - 30.9.2014
october - 31.10.2014
november - 30.11.2014
december - 31.12.2014


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-03-29 08:43 UTC] tm8544 at hotmail dot com
As you can see, this problem was produced on 29.3.2014.
I assume that if it was tested on 31.3.2014, also last days of april, june, september and november would have been wrong.

It is possible to get around this by using
strtotime($string, mktime(0,0,0,date("n"),1)) instead of strtotime($string) in line 6 of the test script, but my point is that "last day of february" is a known fact for each year, and the result of the code shall not depend on the date when it is executed.
 [2014-03-29 10:31 UTC] pajoye@php.net
-Package: date_time +Package: Date/time related
 [2014-04-02 12:07 UTC] ab@php.net
-Status: Open +Status: Feedback
 [2014-04-02 12:07 UTC] ab@php.net
Hi, thanks for reporting. I cannot reproduce it with 5.5.10 or 5.5-dev branch with your snippet. Both first and last day look correct. Could you please give some more details on how you invoke it, maybe timezone and so on? To exclude it's a configuration error maybe you could try it on some other machine.

Thanks.
 [2014-04-02 12:59 UTC] tm8544 at hotmail dot com
-Status: Feedback +Status: Open
 [2014-04-02 12:59 UTC] tm8544 at hotmail dot com
This bug depends on the date when you run the snippet.
Optional second parameter of strtotime ( string $time [, int $now = time() ] ) plays key role in this bug.
As I wrote in the first comment, I noticed this bug at 29th of March.
If I run the code today, there seems to be no problem.

Try these two ways to test this bug:
1) change your computer's date to 29.3.2014 and run the snippet, or
2) replace line 6 of the snippet with the following:
   echo $month ." - " . date("j.n.Y", strtotime($string, mktime(0,0,0,3,29,2014)));

You might also be interested to test with changing line 6 to
echo $month ." - " . date("j.n.Y", strtotime($string, mktime(0,0,0,3,31,2014)));
Besides February, note also April, June, September and November.
 [2014-04-02 15:05 UTC] ab@php.net
-Status: Open +Status: Verified
 [2014-04-02 15:05 UTC] ab@php.net
Yes, now I can reproduce it with the change you mentioned, thanks.

<?php
    $months = array("january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december");

    foreach ($months as $month) {
        $string = "last day of " . $month;
        echo $month ." - " . date("j.n.Y", strtotime($string, mktime(0,0,0,3,29,2014))) . "\n";
    }
 [2014-04-02 15:28 UTC] ab@php.net
-Status: Verified +Status: Not a bug
 [2014-04-02 15:28 UTC] ab@php.net
Wait a minute, but that is correct. It just moves up to the next valid "last day of ". The same way if you try

echo date("j.n.Y", mktime(0,0,0,2,29,2014)) . "\r\n";

you will get 

1.3.2014

because Feb 2014 has 28 days, not 29.

Btw. the behavior is consistent with Linux as well.

Thanks
 [2014-04-02 15:34 UTC] ab@php.net
It makes more sense to use the 1st of a month, so here's your snippet modified to work correctly

<?php
$months = array("january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december");

foreach ($months as $i => $month) {
        $string = "last day of " . $month;
        echo $month ." - " . date("j.n.Y", strtotime($string, mktime(0,0,0,($i+1),1,2014))) . "\r\n";
}
 [2014-04-02 16:26 UTC] tm8544 at hotmail dot com
As I already said in the first comment, there are ways to get around this problem, you just have to be aware that strtotime() behaves funny in certain conditions.
But again, in my opinion "last day of february (or any month)" is not a relative date which depends on how many days any month has, or what is the current date.
Last day of any month should be considered as an absolute date. For February, you naturally have to take into account whether it is a leap year or not.
 [2014-04-02 16:46 UTC] tm8544 at hotmail dot com
In time functions, 'first' and 'next' provide the same relative 
but it this always right? Next and previous should produce relative values, all others are not so relative.

/* The relative text table. */
static timelib_lookup_table const timelib_reltext_lookup[] = {
	{ "first",    0,  1 },
	{ "next",     0,  1 },
	{ "second",   0,  2 },
	{ "third",    0,  3 },
	{ "fourth",   0,  4 },
	{ "fifth",    0,  5 },
	{ "sixth",    0,  6 },
	{ "seventh",  0,  7 },
	{ "eight",    0,  8 },
	{ "eighth",   0,  8 },
	{ "ninth",    0,  9 },
	{ "tenth",    0, 10 },
	{ "eleventh", 0, 11 },
	{ "twelfth",  0, 12 },
	{ "last",     0, -1 },
	{ "previous", 0, -1 },
	{ "this",     1,  0 },
	{ NULL,       1,  0 }
};
 [2014-04-02 17:34 UTC] ab@php.net
> As I wrote in the first comment, I noticed this bug at 29th of March.

When some timestamp is passed, it's logic to have precedence. With no timestamp like this 

date("j.n.Y", strtotime('last day of february'))

it takes the current year and the result is fine, too. Either it's today or on March 29th, I don't see how it differs from an arbitrary day of year. But if you pass March 29 explicitly, it has precedence over 'last day of february'.

Thanks
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sun Jun 16 18:01:30 2024 UTC