php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #76624 date_create_from_format doesn't respect "T" Timezone format character
Submitted: 2018-07-14 20:39 UTC Modified: 2018-07-15 14:50 UTC
From: jalaj dot chhalotre at gmail dot com Assigned:
Status: Not a bug Package: Date/time related
PHP Version: 7.0.30 OS: Ubuntu 16.04.1
Private report: No CVE-ID: None
 [2018-07-14 20:39 UTC] jalaj dot chhalotre at gmail dot com
Description:
------------
When T timezone format character is used to specify timezone in date_create_from_format() function, wrong time (with respect to epoch) is generated.
In test script attached, two different epoch times are generated if 'T' and 'e' timezone format characters are used. However using e format character returns correct time.

Test script:
---------------
# date_string = "2018-07-13 15:30:15 IST" = "2018-07-13 15:30:15 Asia/Kolkata"

$date1 = new DateTime('2018-07-13 15:30:15', new DateTimeZone('Asia/Kolkata'));
echo $date1->format('Y-m-d H:i:s T');
//2018-07-13 15:30:15 IST

echo $str1=$date1->format('U');
//1531476015
$date2=date_create_from_format('Y-m-d H:i:s T', '2018-07-13 15:30:15 IST');
echo $str2=$date2->format('U');
//1531488615

/*
$str1 IS NOT equal to $str2
but date1=date2
*/

echo $date1->format('Y-m-d H:i:s e');
//2018-07-13 15:30:15 Asia/Kolkata

echo $str3=$date1->format('U');
//1531476015
$date2=date_create_from_format('Y-m-d H:i:s e', '2018-07-13 15:30:15 Asia/Kolkata');
echo $str4=$date2->format('U');
//1531476015

/*
$str3 IS equal to $str4
as date1=date3
*/


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-07-14 20:43 UTC] jalaj dot chhalotre at gmail dot com
-Operating System: Ubuntu 0.16.04.1 +Operating System: Ubuntu 16.04.1
 [2018-07-14 20:43 UTC] jalaj dot chhalotre at gmail dot com
Corrected OS (typo)
 [2018-07-14 21:30 UTC] cmb@php.net
-Package: *General Issues +Package: Date/time related
 [2018-07-15 08:07 UTC] jalaj dot chhalotre at gmail dot com
Noticed this bug is timezone dependent, e.g. if TimeZone is CDT (Canada/Central) the difference in epoch of mentioned function is 0. On the other side IST, CST(China Standard time) result in epoch difference.

Created a test function to check variability of this bug with timezone.
<?php
bug_epoch_diff('2018-07-13 15:30:15','Asia/Shanghai');
bug_epoch_diff('2018-07-13 15:30:15','Asia/Kolkata');
bug_epoch_diff('2018-07-13 15:30:15','Asia/Hong_Kong');
bug_epoch_diff('2018-07-13 15:30:15','Asia/Macau');
bug_epoch_diff('2018-07-13 15:30:15','Asia/Macau'); 
bug_epoch_diff('2018-07-13 15:30:15','Canada/Central');
bug_epoch_diff('2018-07-13 15:30:15','Brazil/Acre');
bug_epoch_diff('2018-07-13 15:30:15','Europe/Berlin');


function bug_epoch_diff($datetime,$timezone){
// date='2018-07-13 15:30:15' TimeZone='Asia/Kolkata'
$date = new DateTime($datetime, new DateTimeZone($timezone));
echo "DateTime in format 'Y-m-d H:i:s T': ". $date->format('Y-m-d H:i:s T');
echo " | ";
echo $ep1=$date->format('U');
echo " | ";
//1531476015
echo $ep2=date_create_from_format('Y-m-d H:i:s T', $date->format('Y-m-d H:i:s T'))->format('U');
//1531488615
echo " | ";

//Comment: for same date two different epoch
echo "Epoch difference for ".$timezone."=".(((float)$ep2)-((float)$ep1))."<br>";
}
?>
_____
Output:
DateTime in format 'Y-m-d H:i:s T': 2018-07-13 15:30:15 CST | 1531467015 | 1531517415 | Epoch difference for Asia/Shanghai=50400
DateTime in format 'Y-m-d H:i:s T': 2018-07-13 15:30:15 IST | 1531476015 | 1531488615 | Epoch difference for Asia/Kolkata=12600
DateTime in format 'Y-m-d H:i:s T': 2018-07-13 15:30:15 HKT | 1531467015 | 1531467015 | Epoch difference for Asia/Hong_Kong=0
DateTime in format 'Y-m-d H:i:s T': 2018-07-13 15:30:15 CST | 1531467015 | 1531517415 | Epoch difference for Asia/Macau=50400
DateTime in format 'Y-m-d H:i:s T': 2018-07-13 15:30:15 CST | 1531467015 | 1531517415 | Epoch difference for Asia/Macau=50400
DateTime in format 'Y-m-d H:i:s T': 2018-07-13 15:30:15 CDT | 1531513815 | 1531513815 | Epoch difference for Canada/Central=0
DateTime in format 'Y-m-d H:i:s T': 2018-07-13 15:30:15 -05 | 1531513815 | 1531513815 | Epoch difference for Brazil/Acre=0
DateTime in format 'Y-m-d H:i:s T': 2018-07-13 15:30:15 CEST | 1531488615 | 1531488615 | Epoch difference for Europe/Berlin=0
 [2018-07-15 09:56 UTC] a at b dot c dot de
What timezone does IST name? Jerusalem, Kolkata, or Dublin?

<?php

$date2=date_create_from_format('Y-m-d H:i:s T', '2018-07-13 15:30:15 IST');
echo $date2->format('Y-m-d H:i:s e (T)'),"\t", $date2->format('U'),"\n";
echo "\n";
foreach(array_column(DateTimeZone::listAbbreviations()['ist'], 'timezone_id') as $tz)
{
	$date1 = new DateTime('2018-07-13 15:30:15', new DateTimeZone($tz));
	echo $date1->format('Y-m-d H:i:s e (T)'),"\t", $date1->format('U'),"\n";
}


Apparently it's interpreted as Israel Standard Time.

Suggest you avoid the ambiguity and stick with using "Asia/Kolkata".

$date2=date_create_from_format('Y-m-d H:i:s T', '2018-07-13 15:30:15 Asia/Kolkata');
echo $date2->format('Y-m-d H:i:s e (T)'),"\t", $date2->format('U'),"\n";
 [2018-07-15 10:06 UTC] requinix@php.net
-Status: Open +Status: Not a bug
 [2018-07-15 10:06 UTC] requinix@php.net
Well spotted, @a.

Indeed, there are three different "IST" timezones. Abbreviations are not unique.
https://en.wikipedia.org/wiki/List_of_time_zone_abbreviations
 [2018-07-15 13:23 UTC] jalaj dot chhalotre at gmail dot com
Oh ok, Thanks for highlighting Israel in IST.
However my two observations:
1. Inconsitency is not specific to IST, for other timezones as well as mentioned in my previous comment.
2. When existing date formatted with T, Asia/Kolkata is printed as IST, but when date is created with mentioned function and format T, IST is interpreted as Israel time. Isn't it be canonical.

My suggestion - if there are multiple representations, T format should output difference with UTC e.g. +5:30. The same way T format does for "Brazil/Acre" timezone.
 [2018-07-15 14:50 UTC] requinix@php.net
Any timezone abbreviation that is not unique will result in undefined behavior if you try to create a time using it. IST has three meanings. CST has three meanings. CDT has two meanings.

Do not create a time using those abbreviations and expect PHP to correctly guess which timezone you meant.

If you want to see the UTC offset like +05:30 then use the 'P' format. But you still must not use the abbreviation.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 14:01:32 2024 UTC