Как я могу легко конвертировать даты из UTC через PHP?

Я храню даты в базе данных MySQL в полях datetime в UTC. Я использую PHP, и я вызвал date_timezone_set('UTC'), чтобы все вызовы date() (без метки времени) возвращали дату в UTC.

затем у меня есть это, чтобы данный веб-сайт мог выбрать свой часовой пояс. Теперь я хочу, чтобы даты отображались в часовом поясе сайта. Итак, если у меня есть дата, хранящаяся как "2009-04-01 15:36:13", она должна отображаться для пользователя в часовом поясе PDT (-7 часов) как "2009-04-01 08:36:13".

что является ли самый простой (наименее кодовый) метод для этого через PHP? До сих пор все, о чем я думал, это

date('Y-m-d H:i:s', strtotime($Site->getUTCOffset() . ' hours', strtotime(date($utcDate))));

есть ли более короткий путь?

8 ответов


вот что мы сделали с наших серверов. Мы устанавливаем все, чтобы использовать UTC, и мы показываем в часовом поясе пользователя, конвертируя из UTC на лету. Код в нижней части этого сообщения является примером того, как заставить это работать; вы должны подтвердить, что он работает во всех случаях с вашей настройкой (т. е. летнее время и т. д.).

Настройка CentOS

  1. редактировать /etc/sysconfig/clock и set ZONE to UTC
  2. ln -sf /usr/share/zoneinfo/UTC /etc/localtime

настройка В MySQL

  1. импорт часовых поясов в MySQL при необходимости:

    mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql

  2. редактировать мои.cnf и добавьте следующее В разделе [mysqld]:

    default-time-zone = 'UTC'

PHP-кода

<?php
/*
Example usage:
  $unixtime = TimeUtil::dateTimeToTimestamp('2009-04-01 15:36:13');
  echo TimeUtil::UTCToPST("M d, Y - H:i:s", $unixtime);
*/

// You should move this to your regular init method
date_default_timezone_set('UTC'); // make this match the server timezone

class TimeUtil {
    public static function timestampToDateTime($timestamp) {
        return gmdate('Y-m-d H:i:s', $timestamp);
    }

    public static function dateTimeToTimestamp($dateTime) {
        // dateTimeToTimestamp expects MySQL format
        // If it gets a fully numeric value, we'll assume it's a timestamp
        // You can comment out this if block if you don't want this behavior
        if(is_numeric($dateTime)) {
            // You should probably log an error here
            return $dateTime;
        }
        $date = new DateTime($dateTime); 
        $ret = $date->format('U');
        return ($ret < 0 ? 0 : $ret);
    }

    public static function UTCToPST($format, $time) {
        $dst = intval(date("I", $time));
        $tzOffset = intval(date('Z', time()));
        return date($format, $time + $tzOffset - 28800 + $dst * 3600);
    }

}

почему бы не использовать встроенный в DateTime / Часовой Пояс функциональность?

<?php

$mysqlDate = '2009-04-01 15:36:13';

$dateTime = new DateTime ($mysqlDate);
$dateTime->setTimezone(new DateTimeZone('America/Los_Angeles'));

?>

Класс DateTime:http://us3.php.net/manual/en/class.datetime.php Класс DateTimeZone:http://us3.php.net/manual/en/class.datetimezone.php

поддерживаемые часовые пояса PHP:http://php.net/manual/en/timezones.php


что вы делаете это правильный способ делать вещи. Я бы рекомендовал придерживаться работы только в UTC и просто конвертировать в последнюю минуту для отображения.

вот быстрая функция, которую я собрал для преобразования часового пояса, используя класс DateTime, который поставляется с PHP. Это немного больше кода, чем у вас есть, но я думаю, что это проще и лучший способ структурирования вещи...

function convert_time_zone($date_time, $from_tz, $to_tz)
    {
    $time_object = new DateTime($date_time, new DateTimeZone($from_tz));
    $time_object->setTimezone(new DateTimeZone($to_tz));
    return $time_object->format('Y-m-d H:i:s');
    }

http://richardwillia.ms/blog/2011/04/time-zone-conversion-using-datetime-class/

надеюсь, что это поможет.


потратив много времени на решение этой проблемы,не пытайтесь самостоятельно реализовать перевод часовых поясов. это королевский PIA, чреватый трудностями, и это очень трудно получить его прямо на международном уровне.

тем не менее, лучший вариант-конвертировать ваш datetimes в MySQL для меткаs, и просто использовать базу данных для преобразования раз:

 mysql> set time_zone='America/New_York';

меткаs в MySQL меньше, и поддержка перевод часовых поясов. datetime нет.

прежде чем отображать информацию о сайте на странице, просто вызовите вышеуказанную команду, и она будет отображаться правильно без каких-либо изменений кода PHP вообще.

предостережения:

  1. если вы используете сейчас() или любые функции местного времени, вы должны обновить их до UTC_TIMESTAMP ()
  2. меткаs имеют интересные свойства обновления и вставки, которые возможно, вы захотите выключить.

выключить метка свойства:

ALTER TABLE mytable CHANGE COLUMN Created Created timestamp NULL DEFAULT 0;

на по умолчанию 0 отключает обновление столбца при обновлении других столбцов.


<?php

  function getNoteDateTimeZone($date = null, $from_dtz = 'US/Central', $to_dtz = null) {
        //$from_zt = 'US/Central'; // Time Zone = -06:00
        if (is_null($date) == FALSE && is_null($from_dtz) == FALSE && is_null($to_dtz) == FALSE) {
            // set TimeZone from
            $time_object = new DateTime($date, new DateTimeZone($from_dtz));
            $time_now_object = new DateTime("now", new DateTimeZone($from_dtz));
            // Change TimeZone
            $time_object->setTimezone(new DateTimeZone(trim($to_dtz)));
            $time_now_object->setTimezone(new DateTimeZone(trim($to_dtz)));
            // Is day = day in $time_now_object, $time_object..?
            if ($time_now_object->format('d') == $time_object->format('d')) {
                return $time_object->format('H:i:s');
            } else {
                return $time_object->format('Y-m-d H:i:s');
            }
        } else {
            return '';
        }
    }
?>

использовать пример:

<?php 
 $date = '2008-06-02 20:32:46';
 $dtz = 'America/Argentina/Buenos_Aires';
 echo getNoteDateTimeZone($date, 'US/Central', $dtz); // Out = 2008-06-02 23:32:46
?>

ADDTIME($utcDate,$Site->getUTCOffset())

это работает для меня и это довольно чистый!--2-->

function convert_to_user_date($date, $userTimeZone = 'America/Los_Angeles', $serverTimeZone = 'UTC', $format = 'n/j/Y g:i A')
{
    $dateTime = new DateTime ($date, new DateTimeZone($serverTimeZone));
    $dateTime->setTimezone(new DateTimeZone($userTimeZone));
    return $dateTime->format($format);
}

function convert_to_server_date($date, $userTimeZone = 'America/Los_Angeles', $serverTimeZone = 'UTC', $format = 'n/j/Y g:i A')
{
    $dateTime = new DateTime ($date, new DateTimeZone($userTimeZone));
    $dateTime->setTimezone(new DateTimeZone($serverTimeZone));
    return $dateTime->format($format);
}

преобразовать часовой пояс пользователя на сервере. и наоборот, с единственной функцией:

function convertTimeZone($date, $convertTo = 'userTimeZone', $userTimeZone = 'America/Los_Angeles', $serverTimeZone = 'UTC', $format = 'n/j/Y g:i A')
{
    if($convertTo == 'userTimeZone'){
       $dateTime = new DateTime ($date, new DateTimeZone($serverTimeZone));
       $dateTime->setTimezone(new DateTimeZone($userTimeZone));
       return $dateTime->format($format);   
    } else if($convertTo == 'serverTimeZone'){
       $dateTime = new DateTime ($date, new DateTimeZone($userTimeZone));
       $dateTime->setTimezone(new DateTimeZone($serverTimeZone));
       return $dateTime->format($format);   
    }
}

echo convertTimeZone(date('Ydm h:i:s'),'serverTimeZone');