DateTime格式和时区 [英] DateTime formatting and timezone

查看:201
本文介绍了DateTime格式和时区的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当尝试使用 DateTime :: createFromFormat解析日期时,PHP将无法识别时区。



示例:

  $ t = new \DateTime(); 
echo $ t-> format('Y-m-dTH:i:s');

将输出

 code> 2012-01-24MSK16:53:52 

现在,当我尝试解析字符串从相同的格式

  var_dump(\DateTime :: createFromFormat('Ym-dTH:i:s','2012 -01-24MSK16:53:52')); 

我得到

 code> bool(false)

当我没有将时区放入字符串时作品

  $ t = new \DateTime(); 
echo $ t-> format('Y-m-dH:i:s');

将给予

 code> 2012-01-2417:17:24 

并解析

  var_dump(\DateTime :: createFromFormat('Ym-dH:i:s',2012-01-2417:17:24 )); 

将给予

 code> object(DateTime)#3(3){
[date] =>
string(19)2012-01-24 17:17:24
[timezone_type] =>
int(3)
[timezone] =>
string(13)欧洲/莫斯科
}

/ p>


  • PHP 5.3.6-13ubuntu3.3与Suhosin-Patch(cli)(内置:2011年12月13日18:18:37)和

  • PHP 5.3.9(cli)(build:Jan 18 2012 20:02:33)



如果我们关心时区,问题就会出现。这是一个bug吗?还是我做错了?谢谢你提前!

解决方案

它看起来像一个错误(或至少一个未记录的限制)使用PHP ...如果我们尝试4个可能的空格排列:

  var_dump(\DateTime :: createFromFormat('Ym- dTH:i:s','2012-01-24MSK16:53:52')); 
var_dump(\DateTime :: createFromFormat('Y-m-d T H:i:s','2012-01-24 MSK 16:53:52'));
var_dump(\DateTime :: createFromFormat('Y-m-d TH:i:s','2012-01-24 MSK16:53:52'));
var_dump(\DateTime :: createFromFormat('Y-m-dT H:i:s','2012-01-24MSK 16:53:52'));

我们得到(测试PHP 5.3,5.4rc6和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)
对象(DateTime)#3(3){
[date] =>
string(19)2012-01-24 16:53:52
[timezone_type] =>
int(2)
[timezone] =>
string(3)MSK
}

时区标识符和/或小时对空格敏感...进一步测试:

  var_dump(\DateTime :: createFromFormat ('Ymd H:i:s','2012-01-24 16:53:52')); 
var_dump(\DateTime :: createFromFormat('Y-m-dH:i:s','2012-01-2416:53:52'));

产生正确的结果。和:

  var_dump(\DateTime :: createFromFormat('TY-m-d','MSK2012-01-24' )); 
var_dump(\DateTime :: createFromFormat('T Y-m-d','MSK 2012-01-24'));

收益:

 code> bool(false)
object(DateTime)#4(3){
[date] =>
string(19)2012-01-24 01:49:26
[timezone_type] =>
int(2)
[timezone] =>
string(3)MSK
}

看起来时区说明符对尾随空格敏感...



编辑:这是白色空间敏感的



如果我们查看 parse_date.c timelib_parse_from_format()在线25075 ,我们可以看到,所有4个时区格式都被解析为同样的方式!这意味着在解析的格式标识符之间根本没有区别,因此用于解析它们是可互换的。



的错误(或缺少功能)继续。但是,让我们看看在 中会发生什么timelib_get_zone() ,当您使用时区标识符时调用。那么看,我们可以看到我们打电话给 timelib_lookup_zone() 当不是GMT或时间偏移。



那里我们发现了错误。在 timelib_lookup_zone 的第768行,我们可以看到它将消耗整个输入字符串,直到 \0 )或空格:

  while(* * ptr!='\0&& ** ptr!=')'&& ** ptr!=''){
++ * ptr;
}

关于修复它,这有点更棘手。要解决这个问题,需要重新实现每个时区的格式解析器。对于 T 解析器,这很容易,因为它总是一个3字母的字符串。但是对于其他人来说,这有点更有趣,因为有可变的字母,因此这个空格的敏感度可能是一个问题。



所以简而言之,我会建议为您的时区标识符添加一个尾随的空白区域,并使用它完成...


When trying to parse a Date with DateTime::createFromFormat PHP will not recognize the timezone.

Example:

$t = new \DateTime(); 
echo $t->format('Y-m-dTH:i:s');

will output

2012-01-24MSK16:53:52

Now when I try to parse that string from the same format

var_dump(\DateTime::createFromFormat('Y-m-dTH:i:s', '2012-01-24MSK16:53:52'));

I get

bool(false)

When I do not put the Timezone into the string, it works

$t = new \DateTime(); 
echo $t->format('Y-m-dH:i:s');

will give

2012-01-2417:17:24

and parsing that

var_dump(\DateTime::createFromFormat('Y-m-dH:i:s', "2012-01-2417:17:24"));

will give

object(DateTime)#3 (3) {
  ["date"]=>
  string(19) "2012-01-24 17:17:24"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(13) "Europe/Moscow"
}

Tested on

  • PHP 5.3.6-13ubuntu3.3 with Suhosin-Patch (cli) (built: Dec 13 2011 18:18:37) and
  • PHP 5.3.9 (cli) (built: Jan 18 2012 20:02:33)

Problem appears just if we are take care about timezone. Is it a bug? Or what I do wrong? Thank you in advance!

解决方案

It looks like a bug (or at least an undocumented limitation) with PHP... If we try the 4 possible whitespace permutations:

var_dump(\DateTime::createFromFormat('Y-m-dTH:i:s', '2012-01-24MSK16:53:52'));
var_dump(\DateTime::createFromFormat('Y-m-d T H:i:s', '2012-01-24 MSK 16:53:52'));
var_dump(\DateTime::createFromFormat('Y-m-d TH:i:s', '2012-01-24 MSK16:53:52'));
var_dump(\DateTime::createFromFormat('Y-m-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"
}

So that seems to point that the timezone identifier and/or hour are sensitive to whitespace... Testing further:

var_dump(\DateTime::createFromFormat('Y-m-d H:i:s', '2012-01-24 16:53:52'));
var_dump(\DateTime::createFromFormat('Y-m-dH:i:s', '2012-01-2416:53:52'));

Yields the proper results. And:

var_dump(\DateTime::createFromFormat('TY-m-d', 'MSK2012-01-24'));
var_dump(\DateTime::createFromFormat('T Y-m-d', 'MSK 2012-01-24'));

Yields:

bool(false)
object(DateTime)#4 (3) {
  ["date"]=>
  string(19) "2012-01-24 01:49:26"
  ["timezone_type"]=>
  int(2)
  ["timezone"]=>
  string(3) "MSK"
}

So yes, it does appear that the timezone specifier is sensitive to trailing whitespace...

Edit: It is white-space sensitive

If we look at parse_date.c timelib_parse_from_format() on line 25075, we can see that all 4 timezone formats are parsed the same way! That means there is no difference at all between the format identifiers for parsing, and therefore for parsing they are interchangable.

That alone seems like enough of a bug (or lack of a feature) to go on. But, let's see what happens in timelib_get_zone() which is called when you use a timezone identifier. Well, looking on, we can see that we call timelib_lookup_zone() when it's not GMT or a time offset.

And there we found the bug. On line 768 of timelib_lookup_zone, we can see that it will consume the entire input string up to one of either \0 (null), ) or a space:

while (**ptr != '\0' && **ptr != ')' && **ptr != ' ') {
    ++*ptr;
}

With respect to fixing it, that's a little more tricky. To just fix this issue, would require re-implementing the format parsers for each timezone. For the T parser, this is easy, since it's always a 3 letter string. But for the others, it's a little more interesting, since there are variable letters, and as such whitespace sensitivity may be an issue.

So in short, I would suggest just adding a trailing white-space to your timezone identifiers and being done with it...

这篇关于DateTime格式和时区的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆