Req #55240 [Asn->Opn]: DateTime::createFromFormat with format 'd.m.Y Gi' returns wrong date

From: Date: Tue, 24 Oct 2017 07:57:09 +0000
Subject: Req #55240 [Asn->Opn]: DateTime::createFromFormat with format 'd.m.Y Gi' returns wrong date
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-212190@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=55240&edit=1

 ID:                 55240
 Updated by:         kalle@php.net
 Reported by:        m dot strucken at binserv dot de
 Summary:            DateTime::createFromFormat with format 'd.m.Y Gi'
                     returns wrong date
-Status:             Assigned
+Status:             Open
 Type:               Feature/Change Request
 Package:            Date/time related
 Operating System:   Windows Server 2008 R2
 PHP Version:        5.3.6
-Assigned To:        derick
+Assigned To:        
 Block user comment: N
 Private report:     N



Previous Comments:
------------------------------------------------------------------------
[2014-01-09 17:26:45] brian at brianhogg dot ca

This is similar to this example:

<?php
$date = DateTime::createFromFormat('MjY', 'Jan92014');
var_dump($date);
var_dump(DateTime::getLastErrors());

which outputs:

class DateTime#1 (3) {
  public $date =>
  string(19) "0014-04-02 18:24:29"
  public $timezone_type =>
  int(3)
  public $timezone =>
  string(13) "Europe/Zurich"
}
array(4) {
  'warning_count' =>
  int(1)
  'warnings' =>
  array(1) {
    [8] =>
    string(27) "The parsed date was invalid"
  }
  'error_count' =>
  int(0)
  'errors' =>
  array(0) {
  }
}

Technically you could know where to stop based on the fact that Y is 4 digits and M is 3 characters,
but understand that parsing left-to-right makes this difficult.

------------------------------------------------------------------------
[2011-11-26 16:40:47] derick@php.net

Hi!

I've had a look at this, and now I can tell you what happens.
Without the delimiter, the 800 gets parsed as 80 hours, 0 minutes.
If you add 80 hours to  11.11.2009, that means 3 days, 8 hours, you get 14.11.2009, 8am.

If you call DateTime::getLastError, you see it shows a warning:

derick@whisky:~$ cat /tmp/test.php 
<?php
$dt = DateTime::createFromFormat( 'd.m.Y Gi', '11.11.2009 800' );
var_dump($dt);
var_dump(DateTime::getLastErrors());
echo $dt->format( 'd.m.Y G i' );
?>

derick@whisky:~$ php /tmp/test.php 
class DateTime#1 (3) {
  public $date =>  string(19) "2009-11-14 08:00:00"
  public $timezone_type =>  int(3)
  public $timezone =>  string(13) "Europe/London"
}
array(4) {
  'warning_count' =>
  int(1)
  'warnings' =>
  array(1) {
    [14] =>
    string(27) "The parsed time was invalid"
  }
  'error_count' =>
  int(0)
  'errors' =>
  array(0) {
  }
}
14.11.2009 8 00
derick@whisky:~$ 

The parser for "G" parses up to 2 characters, and it doesn't know how to stop if it
encounters something too high. I'm looking at how I can changes this, but still not break BC in
any form. I've changed the bug's status to FR now.

cheers,
Derick

------------------------------------------------------------------------
[2011-07-19 11:11:45] m dot strucken at binserv dot de

Description:
------------
Having a date without a delimiter between hour and minute and the hour without leading zero, the
returned date from DateTime::createFromFormat() is incorrect

Test script:
---------------
$dt = DateTime::createFromFormat( 'd.m.Y Gi', '11.11.2009 800' );
echo $dt->format( 'd.m.Y Gi' );

Expected result:
----------------
11.11.2009 800

Actual result:
--------------
14.11.2009 800


------------------------------------------------------------------------



--
Edit this bug report at https://bugs.php.net/bug.php?id=55240&edit=1


Thread (5 messages)

« previous php.bugs (#212190) next »