Мне нужна помощь с 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?
Ответ правильный. Когда вы добавляете +
часовой пояс на метку времени, вы, по сути, идете на восток от 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 в логике дисплея.
Других решений пока нет …