PHP DateTime和TimeZone到MongoDB \ BSON \ UTCDateTime

时间:2018-12-28 17:41:13

标签: php mongodb datetime bson

我需要有关将TimeZone转换为MongoDB \ BSON \ UTCDateTime的PHP DateTime的帮助。 如果我有字符串“ 2015-10-20T04:02:00.608000 + 01:00 ”,它会给我一个DateTime

$date = DateTime::createFromFormat( 'Y-m-d\TH:i:s.uT', $string );

DateTime
date => "2015-10-20 04:02:00.608000"
timezone_type => 1
timezone => "+01:00"

如果我将其转换为MongoDB \ BSON \ UTCDateTime并转换回PHP DateTime

$mDate = new \MongoDB\BSON\UTCDateTime( $date->format('U') * 1000 );
$mDate->toDateTime()->setTimeZone(new DateTimeZone('Europe/Bratislava'))

我会得到正确的结果 05:02

DateTime
date => "2015-10-20 05:02:00.000000"
timezone_type => 3
timezone => "Europe/Bratislava"

但如果输入字符串具有 +02:00 时区“ 2015-10-20T04:02:00.608000 + 02:00 ”,则使用相同的方法得出结果是

DateTime
date => "2015-10-20 04:02:00.000000"
timezone_type => 3
timezone => "Europe/Bratislava"

如果我期望 06:02 ,为什么第二个结果是04:02?

1 个答案:

答案 0 :(得分:3)

响应正确。在时间戳上添加+时区时,实际上就是从UTC向东移动。您不是在UTC时间上添加 ,实际上是在从UTC时间中减去 。这意味着2015-10-20T04:02:00.608000+01:00是世界标准时间凌晨3点。 2015-10-20T04:02:00.608000+02:00是世界标准时间凌晨2点。如果您将时区偏移量保持在较高水平,则可以更轻松地看到这一点

$date = DateTime::createFromFormat( 'Y-m-d\TH:i:s.uT', "2015-10-20T04:02:00.608000+01:00");
$mDate = new \MongoDB\BSON\UTCDateTime( $date->format('U') * 1000 );
var_dump($date, $mDate->toDateTime());

object(DateTime)#1 (3) {
  ["date"]=>
  string(26) "2015-10-20 04:02:00.608000"
  ["timezone_type"]=>
  int(1)
  ["timezone"]=>
  string(6) "+01:00"
}
object(DateTime)#3 (3) {
  ["date"]=>
  string(26) "2015-10-20 03:02:00.000000"
  ["timezone_type"]=>
  int(1)
  ["timezone"]=>
  string(6) "+00:00"
}


$date = DateTime::createFromFormat( 'Y-m-d\TH:i:s.uT', "2015-10-20T04:02:00.608000+02:00");
$mDate = new \MongoDB\BSON\UTCDateTime( $date->format('U') * 1000 );
var_dump($date, $mDate->toDateTime());

object(DateTime)#1 (3) {
  ["date"]=>
  string(26) "2015-10-20 04:02:00.608000"
  ["timezone_type"]=>
  int(1)
  ["timezone"]=>
  string(6) "+02:00"
}
object(DateTime)#3 (3) {
  ["date"]=>
  string(26) "2015-10-20 02:02:00.000000"
  ["timezone_type"]=>
  int(1)
  ["timezone"]=>
  string(6) "+00:00"
}

MongoDB存储UTC时间戳。当您添加Europe/Bratislava时区时,您的意思是“此UTC时间戳在布拉迪斯拉发几点钟”。对于10月(夏令时),相差1小时。

在旁注。尝试永远不要 混合使用+XXXX和Unicode / Olson时区(Europe/Bratislava)。由于夏令时,您会遇到一些非常奇怪的错误。如果您需要记录用户的本地时间以便在某个时候返回显示,请使用可选的第3个参数创建DateTime对象,例如:

$customerTz = 'Europe/Bratislava';
$date = DateTime::createFromFormat( 'Y-m-d\TH:i:s.u', $dateString, $customerTz);

还要检查是否真的需要创建一个DateTime,或者只需要直接创建一个带有时间戳的新UTCDateTime并处理显示逻辑中的tz。