PHP DateTime с TimeZone в MongoDB \ BSON \ UTCDateTime

Мне нужна помощь с PHP DateTime с преобразованием TimeZone в MongoDB \ BSON \ UTCDateTime.
Если у меня есть строка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'))

Я получу правильный результат 5:02

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

НО, если входная строка имеет +2:00 Часовой пояс «2015-10-20T04: 02: 00,608000 + 02: 00«и использовать тот же подход, результат

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

Почему второй результат 04:02, если я ожидаю 6:02?

2

Решение

Ответ правильный. Когда вы добавляете + часовой пояс на метку времени, вы, по сути, идете на восток от UTC. Ты не добавление к времени UTC, вы на самом деле вычитая с какого времени в UTC. Это означает, что 2015-10-20T04:02:00.608000+01:00 3 утра по Гринвичу. 2015-10-20T04:02:00.608000+02:00 2:00 UTC. Вы можете увидеть это легче, если продолжите подниматься со смещением часового пояса.

$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». Для октября (летнее время) разница составляет 1 час.

На боковой ноте. Пробовать никогда микшировать +XXXX и Юникод / ​​Олсон часовые пояса (Europe/Bratislava). Вы получите очень странные ошибки из-за перехода на летнее время. Если вам нужно записать местное время пользователя для отображения в какой-то момент, создайте свой DateTime объекты с необязательным третьим параметром, например:

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

Также проверьте, действительно ли вам нужно создать DateTime вообще или просто новый UTCDateTime непосредственно с отметкой времени и иметь дело с tz в логике дисплея.

2

Другие решения

Других решений пока нет …