php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #62476 DateTime::createFromFormat z format incorrect wrt 29.02
Submitted: 2012-07-04 00:20 UTC Modified: 2021-10-01 13:01 UTC
Votes:27
Avg. Score:4.6 ± 0.7
Reproduced:24 of 25 (96.0%)
Same Version:5 (20.8%)
Same OS:4 (16.7%)
From: kaido at tradenet dot ee Assigned:
Status: Closed Package: Date/time related
PHP Version: 5.4.4 OS: debian 2.6.32-5-amd64
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: kaido at tradenet dot ee
New email:
PHP Version: OS:

 

 [2012-07-04 00:20 UTC] kaido at tradenet dot ee
Description:
------------
When creating DateTime object from string and using z (day of year) format option, 
the 29.02 of the leap year is missing. works ok in 5.3.5

Test script:
---------------
for ($d=55;$d<65;$d++) {
        $dt = DateTime::createFromFormat ('z.Y', $d.'.2012');
        $dd = $dt->format ('d.m.Y');
        echo "$d $dd\n";
}

29.02.2012 is clearly missing .. 

Expected result:
----------------
55 25.02.2012
56 26.02.2012
57 27.02.2012
58 28.02.2012
59 29.02.2012
60 01.03.2012
61 02.03.2012
62 03.03.2012
63 04.03.2012
64 05.03.2012

Actual result:
--------------
55 25.02.2012
56 26.02.2012
57 27.02.2012
58 28.02.2012
59 01.03.2012
60 02.03.2012
61 03.03.2012
62 04.03.2012
63 05.03.2012
64 06.03.2012

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2012-07-05 11:04 UTC] Sjon at hortensius dot net
I can confirm this, this is broken since 5.3.9

http://3v4l.org/1Z4W4
 [2012-07-05 19:13 UTC] kaido at tradenet dot ee
the bug was introduced in commit 4c9fad8b362a7d2b6a94b4961e4b2dc037b2766d to fix 
the bug #51994.

the problem is that in parse_date.c in timelib_parse_from_format() function, in 
case of the z-format option, the date is immidiately normalized, but at that 
point (if year format option happens to come _after_ the z - ie right from it) 
year is not yet set, and -99999 is used instead, which most probably is not a 
leap year :)

the obvious quick solution is to call timelib_do_normalize() only if year is  
set already.

doing so passes all test, too. even the one for #51994.

should the timelib_do_normalize() call be added to year option, too, if 
date/month are set at that point?


also, in timelib_do_normalize() there seems to be 3 checks like:

if (time->s != TIMELIB_UNSET) .. 

shouldn't 2nd and 3rd be "if (time->i != TIMELIB_UNSET)" and "if (time->h != 
TIMELIB_UNSET)" instead ?

(I did not dig deep enough, to be sure, though)
 [2015-02-03 19:40 UTC] kohenkatz at gmail dot com
Why is this still an issue 2.5 years later?

I see it in 5.5.12 on Ubuntu 14.10 and 5.6.5 on Windows Server 2012.
 [2015-03-10 09:14 UTC] info at giorgiosironi dot com
Possible workaround:

$ php -r 'echo DateTime::createFromFormat("z Y", "59 2016")->format("Y-m-d"), PHP_EOL;'
2016-03-01
$ php -r 'echo DateTime::createFromFormat("Y z", "2016 59")->format("Y-m-d"), PHP_EOL;'
2016-02-29
$ php -v
PHP 5.4.31-1+deb.sury.org~precise+1 (cli) (built: Jul 25 2014 07:04:32)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2014 Zend Technologies
    with Zend OPcache v7.0.2, Copyright (c) 1999-2013, by Zend Technologies

If it can be any helpful in Google searches for this bug, we encountered this when using MongoDB $dayOfYear aggregation option.
 [2016-07-28 17:27 UTC] cmb@php.net
-Package: Calendar related +Package: Date/time related
 [2021-10-01 12:38 UTC] cmb@php.net
-Type: Bug +Type: Documentation Problem
 [2021-10-01 12:38 UTC] cmb@php.net
As of PHP 8.0.10, it is no longer possible to use "z.Y" at all ("A
'day of year' can only come after a year has been found").  Fixing
the unsupported format to "Y.z" brings the desired results[1].

So this is a documentation problem.

[1] <https://3v4l.org/2In8R>
 [2021-10-01 13:01 UTC] cmb@php.net
Ah, just found that the change in PHP 8.0.10 is due to fixing bug
#79580.  Apparently, when the day-of-year is parsed before the
given year, the day-of-year is applied to the current year.
 [2021-10-01 13:34 UTC] git@php.net
Automatic comment on behalf of cmb69
Revision: https://github.com/php/doc-en/commit/a8f160fa977075f981c74bff2a68abb99c98f04d
Log: Fix #62476: DateTime::createFromFormat z format incorrect wrt 29.02
 [2021-10-01 13:34 UTC] git@php.net
-Status: Open +Status: Closed
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 12:01:29 2024 UTC