On 4 April 2011 16:35, Ian <php_list@xxxxxxxxxxxxx> wrote: > Hi, > > I have a problem using the php built in classes DateTime and DateTimeZone. > > The idea behind the following code is to return the timestamp for the > current time in Singapore (or other places). ÂWhat it actually returns > is the timestamp for the local system. Other formatted dates appear to > return correctly, which is why I am puzzled. > > I am using the latest php 5.3.6 compiled from source on a OpenVZ CentOS > container. All packages are up to date. > > Am I doing something wrong or is this a bug? > > I can workaround this problem my parsing the correctly formatted date > using strtotime() but I would like to know what's going on. > > > > This is the output of the script: > >    ÂCurrent time in Asia/Singapore is 2011-04-04 23:32:36 >    ÂTimestamp for Asia/Singapore is 1301931156 >    ÂDate created from previous timestamp is 2011-04-04 16:32:36 > > The code is : > > <?php > > $timezone="Asia/Singapore"; > > # Create Timezone object > $remote_timezone    Â= new DateTimeZone($timezone); > > # Create datetime object > $remote_time      Â= new DateTime("now" , $remote_timezone); > > # Print the date > print "Current time in {$timezone} "; > print "is {$remote_time->format("Y-m-d H:i:s")}<br/>"; > > # Print the timestamp > print "Timestamp for {$timezone} "; > print "is {$remote_time->format("U")}<br />"; > > # Get the timestamp and create a date from it > $timestamp = (int)$remote_time->format("U"); > > # Show the formatted date created from timestamp > print "Date created from previous timestamp is "; > print date("Y-m-d H:i:s",$timestamp)."<br/>"; > > ?> Timestamps (the integer value) do not hold the timezone data. Internally, the value represents a number of milliseconds from a point in time. So saying "timestamp for Asia/Singapore" isn't right. It is just "Timestamp". The following script (http://pastebin.com/0MQAaYUq) may show you in a more concrete way ... <?php $a_Times = array( 'now', '2011-03-27 00:59:59', '2011-03-27 02:00:00', ); // Create Timezone objects $a_Timezones = array( 'Singapore' => new DateTimeZone('Asia/Singapore'), 'NewYork ' => new DateTimeZone('America/New_York'), 'London ' => new DateTimeZone('Europe/London'), 'UTC ' => new DateTimeZone('UTC'), ); foreach($a_Times as $s_Time) { echo 'Time : ', $s_Time, PHP_EOL; // Create datetime objects $a_DateTimes = array(); foreach($a_Timezones as $s_Timezone => $tz_Timezone) { $a_DateTimes[$s_Timezone] = new DateTime($s_Time , $tz_Timezone); } // Print the date foreach($a_DateTimes as $s_Timezone => $dt_DateTime) { echo 'Current time in ', $s_Timezone, ' : ', $dt_DateTime->format(DateTime::RSS), ' Offset : ', str_pad($dt_DateTime->getOffset(), 6, ' ', STR_PAD_LEFT), ' Timestamp : ', ($i_Timestamp = $dt_DateTime->getTimestamp()), ' Local : ', date(DateTime::RSS, $i_Timestamp), PHP_EOL; } echo PHP_EOL; } ?> outputs (http://pastebin.com/mETSbR7h) ... Time : now Current time in Singapore : Tue, 05 Apr 2011 17:56:32 +0800 Offset : 28800 Timestamp : 1301997392 Local : Tue, 05 Apr 2011 10:56:32 +0100 Current time in NewYork : Tue, 05 Apr 2011 05:56:32 -0400 Offset : -14400 Timestamp : 1301997392 Local : Tue, 05 Apr 2011 10:56:32 +0100 Current time in London : Tue, 05 Apr 2011 10:56:32 +0100 Offset : 3600 Timestamp : 1301997392 Local : Tue, 05 Apr 2011 10:56:32 +0100 Current time in UTC : Tue, 05 Apr 2011 09:56:32 +0000 Offset : 0 Timestamp : 1301997392 Local : Tue, 05 Apr 2011 10:56:32 +0100 Time : 2011-03-27 00:59:59 Current time in Singapore : Sun, 27 Mar 2011 00:59:59 +0800 Offset : 28800 Timestamp : 1301158799 Local : Sat, 26 Mar 2011 16:59:59 +0000 Current time in NewYork : Sun, 27 Mar 2011 00:59:59 -0400 Offset : -14400 Timestamp : 1301201999 Local : Sun, 27 Mar 2011 05:59:59 +0100 Current time in London : Sun, 27 Mar 2011 00:59:59 +0000 Offset : 0 Timestamp : 1301187599 Local : Sun, 27 Mar 2011 00:59:59 +0000 Current time in UTC : Sun, 27 Mar 2011 00:59:59 +0000 Offset : 0 Timestamp : 1301187599 Local : Sun, 27 Mar 2011 00:59:59 +0000 Time : 2011-03-27 02:00:00 Current time in Singapore : Sun, 27 Mar 2011 02:00:00 +0800 Offset : 28800 Timestamp : 1301162400 Local : Sat, 26 Mar 2011 18:00:00 +0000 Current time in NewYork : Sun, 27 Mar 2011 02:00:00 -0400 Offset : -14400 Timestamp : 1301205600 Local : Sun, 27 Mar 2011 07:00:00 +0100 Current time in London : Sun, 27 Mar 2011 02:00:00 +0100 Offset : 3600 Timestamp : 1301187600 Local : Sun, 27 Mar 2011 02:00:00 +0100 Current time in UTC : Sun, 27 Mar 2011 02:00:00 +0000 Offset : 0 Timestamp : 1301191200 Local : Sun, 27 Mar 2011 03:00:00 +0100 Getting the the timestamp for a DateTime object will return the timestamp appropriately converted to the local timezone. If you don't want to lose the timezone, then don't use the timestamp. This, of course, is an issue if you want to use datetimes in a DB. In these instances, converting the datetime to UTC and storing the timezone separately is certainly one option. If you are using SQL Server 2008, then there is a column type of DATETIMEOFFSET which is a datetime column with Timezone and 100nanosecond accuracy, so you can store and use datetimes like ... 2007-05-08 12:35:29.1234567 +12:15 Which is a pretty accurate. I guess there is some difference in logic between knowing the timezone and the timezone offset. I found the talk by Derick Rethans very useful : (looking for this but can't find it any more. The link to it is http://www.phparch.com/2009/08/dont-miss-todays-webcast-on-date-manipulation/ A book is also available : http://www.phparch.com/books/phparchitects-guide-to-date-and-time-programming/ I -- Richard Quadling Twitter : EE : Zend @RQuadling : e-e.com/M_248814.html : bit.ly/9O8vFY -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php