php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #63234 DateTime::createFromFormat() with a Unix timestamp can be one day off
Submitted: 2012-10-08 06:21 UTC Modified: 2017-03-19 10:47 UTC
Votes:3
Avg. Score:3.7 ± 0.9
Reproduced:3 of 3 (100.0%)
Same Version:2 (66.7%)
Same OS:2 (66.7%)
From: christopher dot jf dot hopper at gmail dot com Assigned:
Status: Not a bug Package: Date/time related
PHP Version: 5.3.17 OS: Linux 2.6.32-220.17.1.el6.i686
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: christopher dot jf dot hopper at gmail dot com
New email:
PHP Version: OS:

 

 [2012-10-08 06:21 UTC] christopher dot jf dot hopper at gmail dot com
Description:
------------
== PHP Version Information ==
# php --version
PHP 5.3.3 (cli) (built: May  7 2012 19:58:17)
Copyright (c) 1997-2010 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies
    with Xdebug v2.2.1, Copyright (c) 2002-2012, by Derick Rethans
# cat /proc/version
Linux version 2.6.32-220.17.1.el6.i686 (mockbuild@c6b5.bsys.dev.centos.org) (gcc 
version 4.4.6 20110731 (Red Hat 4.4.6-3) (GCC) ) #1 SMP Tue May 15 22:09:39 BST 
2012

== Describing The Problem ==
When using the static method DateTime::createFromFormat() or the new DateTime() 
constructor to create a DateTime object instance from a Unix Timestamp, the 
resulting date can be one day out, even though the timestamp is not. To 
reproduce the bug, run the test script below.

Test script:
---------------
<?php 
// Bad
$d=DateTime::createFromFormat("!Y-m-d H:i:s", "2012-11-30 00:00:00"); 
echo $d->getTimestamp() . PHP_EOL; 
echo $d->format("Y-m-d") . PHP_EOL; 
$e=new DateTime("@". $d->getTimestamp()); 
echo $e->getTimestamp() . PHP_EOL; 
echo $e->format("Y-m-d") . PHP_EOL . PHP_EOL;
/*
1354194000
2012-11-30
1354194000
2012-11-29
*/

// Bad
$d=DateTime::createFromFormat("!Y-m-d H:i:s", "2012-11-30 00:00:00"); 
echo $d->getTimestamp() . PHP_EOL; 
echo $d->format("Y-m-d") . PHP_EOL; 
$e=DateTime::createFromFormat("U", $d->getTimestamp()); 
echo $e->getTimestamp() . PHP_EOL; 
echo $e->format("Y-m-d") . PHP_EOL . PHP_EOL;
/*
1354194000
2012-11-30
1354194000
2012-11-29
*/

// Good
$d=DateTime::createFromFormat("!Y-m-d H:i:s", "2012-11-30 00:00:00"); 
echo $d->getTimestamp() . PHP_EOL; 
echo $d->format("Y-m-d") . PHP_EOL; 
$e=new DateTime(); 
$e->setTimestamp($d->getTimestamp()); 
echo $e->getTimestamp() . PHP_EOL; 
echo $e->format("Y-m-d") . PHP_EOL;
/*
1354194000
2012-11-30
1354194000
2012-11-30
*/

Expected result:
----------------
1354194000
2012-11-30
1354194000
2012-11-30

1354194000
2012-11-30
1354194000
2012-11-30

1354194000
2012-11-30
1354194000
2012-11-30


Actual result:
--------------
1354194000
2012-11-30
1354194000
2012-11-29

1354194000
2012-11-30
1354194000
2012-11-29

1354194000
2012-11-30
1354194000
2012-11-30


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2012-11-10 01:29 UTC] mail+php at requinix dot net
There's a bug here but it's a little different from how you've described it. 
Take a careful look at the note attached to the $timezone parameter to 
DateTime's constructor and its createFromFormat():

"The $timezone parameter and the current timezone are ignored when the $time 
parameter either is a UNIX timestamp..."

When you create $e you specify a timestamp and thus the current timezone is 
ignored. Completely and utterly ignored.

echo $d->getTimezone()->getName() . " <-> " . $e->getTimezone()->getName();

Since the timezone is +0 you get a different formatted time than you originally 
gave to $d. Thus the bug is more that the constructor doesn't set a timezone at 
all when really it should - even if it doesn't have any impact on the $time 
itself. To work around this for now you can set the timezone in $e, or even easier 
use setTimestamp() as you've shown.
 [2017-03-19 10:47 UTC] heiglandreas@php.net
-Status: Open +Status: Not a bug
 [2017-03-19 10:47 UTC] heiglandreas@php.net
This is not a bug but related to your timezone settings.

The first DateTime-Object you create is created within your default timezone. And as that is east to UTC the 00:00 H is related to your local time. The timestamp though is UTC. The DateTime-Object you then create from the timestamp will use UTC as timezone (as you created it from a timestamp). And in UTC 00:00 your local time is some time *before* that (depending on your offset to UTC).

You can see that when you add the following lines to your test-script:

echo $d->format('c') . "\n";
echo $e->format('c') . "\n";

As it's not a bug, I'm going to close this issue.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Apr 25 07:01:31 2024 UTC