php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #77814 strtotime("L", (string)($y);
Submitted: 2019-03-28 08:44 UTC Modified: 2019-03-28 11:35 UTC
From: beverlydutoit at gmail dot com Assigned:
Status: Not a bug Package: Date/time related
PHP Version: 7.2 OS: Android
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: beverlydutoit at gmail dot com
New email:
PHP Version: OS:

 

 [2019-03-28 08:44 UTC] beverlydutoit at gmail dot com
Description:
------------
1. ver 7.2.3 ksweb for android app build
2. check for leap year y2k error
3. checkdate works for 2,29, $y reports 1
4. phpinfo() for app default installation
5. huh? whatsa gdb bactrace? :-)

Test script:
---------------
<?php 
echo "<p>$ver; $tz</p>";
$y=1970;
for ($y; $y<2020; $y++){
echo $leap = date("L", strtotime((string)($y))) ? "$y=yes; ":"$y=no; ";
echo checkdate(2,29,$y);
echo '; ';
}
 ?>

Expected result:
----------------
1970=no; ; 1971=no; ; 1972=yes; 1; 1973=no; ; 1974=no; ; 1975=no; ; 1976=yes; 1; 1977=no; ; 1978=no; ; 1979=no; ; 1980=yes; 1; 1981=no; ; 1982=no; ; 1983=no; ; 1984=yes; 1; 1985=no; ; 1986=no; ; 1987=no; ; 1988=yes; 1; 1989=no; ; 1990=no; ; 1991=no; ; 1992=yes; 1; 1993=no; ; 1994=no; ; 1995=no; ; 1996=yes; 1; 1997=no; ; 1998=no; ; 1999=no; ; at this point i'd want to see 2000=yes; 1; instead of  2000=no; 1; 2001=no; ; 2002=no; ; 2003=no; ; 2004=no; 1; 2005=no; ; 2006=no; ; 2007=no; ; 2008=no; 1; 2009=no; ; 2010=no; ; 2011=no; ; 2012=no; 1; 2013=no; ; 2014=no; ; 2015=no; ; 2016=no; 1; 2017=no; ; 2018=no; ; 2019=no; ; same for 2004, 2008, 2012, 2016 and 2020

Actual result:
--------------
dunno whatsa bactrace

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2019-03-28 09:10 UTC] php-bugs at allenjb dot me dot uk
I reproduced the issue with more descriptive code: https://3v4l.org/57h2S

```
<?php

var_dump(date_default_timezone_get());

for ($y = 1970; $y <= 2020; $y++) {
    $ts = strtotime((string) $y);
    $date = date("Y-m-d H:i:s", $ts);
    $isL = date("L", $ts);
    print "$y :: $date :: $isL\n";
}
```

The problem here is the use of strtotime(). strtotime() is a "best efforts guess" based on a set of rules and, as in this example, can unexpectedly change its interpretation for similar values.

Here we can see at a value of "2000", it starts interpreting the value as time instead of year.

The solution is to use DateTime::createFromFormat() instead - as the format is explicitly specified, the interpretation will not stray from what you expect: https://3v4l.org/Z38gl

```
<?php

var_dump(date_default_timezone_get());

for ($y = 1970; $y <= 2020; $y++) {
    $dt = DateTime::createFromFormat("Y", $y);
    $date = $dt->format("Y-m-d H:i:s");
    $isL = $dt->format("L");
    print "$y :: $date :: $isL\n";
}
```
 [2019-03-28 09:30 UTC] cmb@php.net
-Package: Calendar related +Package: Date/time related -PHP Version: 7.1.27 +PHP Version: 7.2
 [2019-03-28 11:35 UTC] derick@php.net
-Status: Open +Status: Not a bug
 [2019-03-28 11:35 UTC] derick@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

This is expected. Don't use strtotime() for this, or, if you must, specify a full date in the form of "{$y}-01-01".
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Fri May 09 21:01:27 2025 UTC