It looks like an error (or at least an undocumented restriction) with PHP ... If we try 4 possible iterations of spaces:
var_dump(\DateTime::createFromFormat('Ym-dTH:i:s', '2012-01-24MSK16:53:52')); var_dump(\DateTime::createFromFormat('Ymd TH:i:s', '2012-01-24 MSK 16:53:52')); var_dump(\DateTime::createFromFormat('Ymd TH:i:s', '2012-01-24 MSK16:53:52')); var_dump(\DateTime::createFromFormat('Ym-dT H:i:s', '2012-01-24MSK 16:53:52'));
We get (tested PHP 5.3, 5.4rc6 and Trunk):
bool(false) object(DateTime)#2 (3) { ["date"]=> string(19) "2012-01-24 16:53:52" ["timezone_type"]=> int(2) ["timezone"]=> string(3) "MSK" } bool(false) object(DateTime)#3 (3) { ["date"]=> string(19) "2012-01-24 16:53:52" ["timezone_type"]=> int(2) ["timezone"]=> string(3) "MSK" }
Thus, it seems that the time zone identifier and / or hour is space-sensitive ... Next:
var_dump(\DateTime::createFromFormat('Ymd H:i:s', '2012-01-24 16:53:52')); var_dump(\DateTime::createFromFormat('Ym-dH:i:s', '2012-01-2416:53:52'));
Gets the correct results. A:
var_dump(\DateTime::createFromFormat('TY-m-d', 'MSK2012-01-24')); var_dump(\DateTime::createFromFormat('T Ym-d', 'MSK 2012-01-24'));
Productivity:
bool(false) object(DateTime)#4 (3) { ["date"]=> string(19) "2012-01-24 01:49:26" ["timezone_type"]=> int(2) ["timezone"]=> string(3) "MSK" }
So it seems that the time zone specifier is sensitive to the trailing space ...
Edit: it is white sensitive
If we look at parse_date.c timelib_parse_from_format() on line 25075 , we will see that all 4 time zone formats are analyzed the same! This means that there is no difference between format identifiers for parsing, therefore, for parsing, they are interchangeable.
This in itself seems to be a mistake (or lack of function) enough to continue. But let's see what happens in timelib_get_zone() , which is called when using the timezone identifier. Well, looking, we can see what we call timelib_lookup_zone() when it is not GMT or a time offset.
And there we found a mistake. On line 768 of timelib_lookup_zone we will see that it will consume the entire input line to one of \0 (null), ) or a space:
while (**ptr != '\0' && **ptr != ')' && **ptr != ' ') { ++*ptr; }
As for fixing it, it's a little trickier. To fix this problem, you will need to re-implement the format parsers for each time zone. For the T parser, this is easy, as it is always a 3-line string. But for others, this is a little more interesting, as there are variable letters, and as such sensitivity to a space can be a problem.
In short, I would suggest just adding a finite white space to your timezone identifiers and do with it ...