PHP DateTime с TimeZone в MongoDB \ BSON \ UTCDateTime - PullRequest
0 голосов
/ 28 декабря 2018

Мне нужна помощь с 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'))

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

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

НО, если входная строка имеет + 02:00 TimeZone " 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, если я ожидаю 06: 02 ?

1 Ответ

0 голосов
/ 29 декабря 2018

Ответ правильный.Когда вы добавляете часовой пояс + к отметке времени, вы фактически отправляетесь на восток от UTC.Вы не добавляете к времени UTC, вы фактически вычитаете из того, что время в UTC.Это означает, что 2015-10-20T04:02:00.608000+01:00 это 3:00 UTC.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 объекты с необязательным 3-м параметром, например:

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

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

...