Почему преобразование даты и времени отличается в разные даты? - PullRequest
0 голосов
/ 01 марта 2019

У меня есть четыре даты с разными датами, но в то же время :

2019-03-02 20:00:00
2019-03-05 20:00:00
2019-03-10 20:00:00
2019-03-18 20:00:00

Эти даты и время указаны в UTC.Я хочу преобразовать его в часовой пояс, например, Лос-Анджелес.

Вот код:

$dateTime = '2019-03-02 20:00:00';

$dt = new DateTime($dateTime, new DateTimeZone('UTC'));
$dt->setTimeZone(new DateTimeZone('America/Los_Angeles'));
$new = $dt->format('Y-m-d H:i:s');

echo $new;

Появляются даты с 2019-03-10 и 2019-03-18как разные времена. ответ заключается в том, что 10 марта он будет на 1 час вперед из-за экономии дневного света.

Вот что получается:

2019-03-02 12:00:00
2019-03-05 12:00:00
2019-03-10 13:00:00
2019-03-18 13:00:00

Мой вопрос : как мне отформатировать дату, используя приведенный выше код, а НЕ учитывать экономию дневного света?Я просто хочу перевести свое время без перехода на летнее время.Как я могу это сделать?Вот мой ожидаемый результат:

2019-03-02 12:00:00
2019-03-05 12:00:00
2019-03-10 12:00:00
2019-03-18 12:00:00

Они все в 12:00:00.

Ответы [ 2 ]

0 голосов
/ 02 марта 2019

Я просто хочу перевести свое время без перехода на летнее время.

Извините, но такое мышление проблематично.Переход на летнее время не является обязательным для людей в тихоокеанском часовом поясе США (обозначается America/Los_Angeles).Они не могут выбирать, принимать или отказываться от участия.

Если вы пытаетесь выполнить какое-то заявленное деловое требование, такое как «Не беспокойтесь о летнем времени», - извините, но вы должны вернутьсятот.В противном случае ваш код будет генерировать неправильные результаты в течение большей части года.(В США период светового дня на самом деле длиннее, чем стандартный период!)

Однако, если вы действительно ищете не время в часовом поясе Тихоокеанского региона США, а просто время с фиксированным смещениемUTC-8, затем вместо America/Los_Angeles используйте часовой пояс Etc/GMT+8 (обратите внимание, что знак намеренно инвертирован).При этом будет использоваться UTC-8 независимо от того, в какое время года вы говорите.

Имейте в виду, что зоны Etc/GMT* в первую очередь предназначены для пограничных ситуаций, таких как время на борту морских судов.Если вы просто хотите отслеживать время в какой-либо другой части мира, выберите подходящий часовой пояс для этого места.Например, острова Питкэрн используют UTC-8 в течение всего года и называют его PST, а их идентификатор часового пояса равен Pacific/Pitcairn.

См. Полный список часовых поясов здесь.

Насколько вы отметили, что 20:00:00 UTC является 12:00:00 PST, но 13:00:00 PDT - действительно, такова реальность ситуации.Если вы отслеживаете 24-часовые периоды один за другим, то нет способа избежать этого факта.Даже если вместо этого вы отслеживаете «Полдень по тихоокеанскому времени» каждый день, вы получите различное соответствующее время UTC до и после переходов.

В то время как дни UTC равны 24 часам, дни перехода в тихоокеанском времени США23 часа, когда мы переключаемся с PST на PDT весной, и 25 часов, когда мы переключаемся с PDT на PST осенью.

И если вы думаете, , что сложный, учтите, что не каждый часовой пояс имеет 1 час дельты летнего времени.Остров Лорда Хау в Австралии (Australia/Lord_Howe) имеет 30-минутную дельту.Это UTC + 10:30 в стандартное время и UTC + 11 в дневное время.

0 голосов
/ 01 марта 2019

Поскольку объекты PHP DateTime всегда учитывают переход на летнее время, необходимо выполнить преобразование, вычтя разницу во времени, когда переход на летнее время не действует.Этот код должен делать то, что вы хотите:

$utctime = new DateTime('2019-01-01', new DateTimeZone('UTC'));
$localtime = new DateTime('2019-01-01', new DateTimeZone('America/Los_Angeles'));
$diff = $localtime->diff($utctime);
foreach ($dates as $date) {
    $dt = new DateTime($date, new DateTimeZone('UTC'));
    $dt->add($diff);
    echo $dt->format('Y-m-d H:i:s');
}

Вывод:

2019-03-02 12:00:00
2019-03-05 12:00:00
2019-03-10 12:00:00
2019-03-18 12:00:00

Демонстрация на 3v4l.org

Обновление

Как указывал @MattJohnson, существует часовой пояс Etc/GMT+8, который относится к 8 часам раньше, чем по Гринвичу (независимо от летнего времени).Вы можете использовать этот часовой пояс для настройки вашего времени:

$west_coast = new DateTimeZone('Etc/GMT+8');
foreach ($dates as $date) {
    $dt = new DateTime($date, new DateTimeZone('UTC'));
    $dt->setTimeZone($west_coast);
    echo $dt->format('Y-m-d H:i:s') . "\n";
}

Выход такой же, как указано выше. Демонстрация на 3v4l.org

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...