Как получить среднее время по Гринвичу в PHP? - PullRequest
44 голосов
/ 12 мая 2009

У меня есть сервер, который настроен на EST, и все записи в базе данных установлены на EST. Я хотел бы знать, как установить его в GMT. Я хочу предложить пользователям часовой пояс.

Ответы [ 6 ]

68 голосов
/ 12 мая 2009

Я бы настоятельно предложил бы избегать путаницы с метками времени UNIX, чтобы он выглядел как другой часовой пояс. Это урок, который я усвоил трудным путем, слишком много раз.

Отметка времени - это количество секунд с полуночи 1 января 1970 года по Гринвичу. Неважно, где вы находитесь в мире, данная временная метка представляет один и тот же момент времени, независимо от часовых поясов. Да, отметка времени «0» означает 10:00 1/1/70 в Австралии, полночь 1/1/70 в Лондоне и 17:00 31/12/69 в Лос-Анджелесе, но это не значит, что вы можете просто добавлять или вычитать значения и гарантировать точность.

Золотой пример, из-за которого я слишком долго мучил меня каждый год, - это когда летние сбережения вырастут. Летнее время означает, что есть «часы», которых нет в некоторых частях мира. Например, в большинстве районов США не было такого времени, как 2:01, 2 апреля 2006 года.

Впрочем, достаточно квазиразборчивого разглагольствования. Мой совет - хранить ваши даты в базе данных в виде меток времени, а затем ...

  • Если вам нужно локальное время на сервере, используйте date()
  • Если вам нужно получить GMT, используйте gmdate()
  • Если вам нужен другой часовой пояс, используйте date_default_timezone_set(), а затем date()

Например,

$timestamp = time();

echo "BRISBANE: " . date('r', $timestamp) . "\n";
echo "     UTC: " . gmdate('r', $timestamp) . "\n";
date_default_timezone_set('Africa/Johannesburg');
echo "  JOBURG: " . date('r', $timestamp) . "\n";

// BRISBANE: Tue, 12 May 2009 18:28:20 +1000
//      UTC: Tue, 12 May 2009 08:28:20 +0000
//   JOBURG: Tue, 12 May 2009 10:28:20 +0200

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

47 голосов
/ 12 мая 2009

Независимо от того, в каком часовом поясе GMT ​​находится сервер, здесь крайне просто получить время и дату для любого часового пояса. Это делается с помощью функций time() и gmdate(). Функция gmdate() обычно дает нам время по Гринвичу, но, выполняя трюк с функцией time(), мы можем получить GMT + N или GMT-N, то есть мы можем получить время для любого часового пояса GMT.

Например, если вам нужно получить время по Гринвичу + 5, вы можете сделать это следующим образом

<?php 
  $offset=5*60*60; //converting 5 hours to seconds.
  $dateFormat="d-m-Y H:i";
  $timeNdate=gmdate($dateFormat, time()+$offset);
?>

Теперь, если вам нужно получить время для GMT-5, вы можете просто вычесть смещение из time() вместо добавления к нему, как в следующем примере, где мы получаем время для GMT-4 * 1011. *

<?php 
  $offset=4*60*60; //converting 4 hours to seconds.
  $dateFormat="d-m-Y H:i"; //set the date format
  $timeNdate=gmdate($dateFormat, time()-$offset); //get GMT date - 4
?>
4 голосов
/ 12 июля 2012

Важно отметить, что если вы используете дату ('Z') для преобразования даты, хранящейся в базе данных, в которой вы указали дату как метку времени в качестве второго аргумента, иначе ваш результат будет неточным. 1001 *

, например

В Великобритании иногда дата ('Z') даст 3600, иногда - 0.

echo date('Z', strtotime('2012-01-01'));

Дает 0

echo date('Z', strtotime('2012-07-01'));

Дает 3600

Так что просто использование strtotime ($ dbDateValue) - дата ('Z') может быть неправильной

Вместо этого используйте:

$dbDateTimestamp = strtotime($dbDateValue); // where $dbDateValue something like 2012-01-01 22:34:00

$utcTimestamp = strtotime($dbDateTimestamp) - date('Z', $dbDateTimestamp);

Конечно, это зависит от того, как PHP и база данных настроены на один и тот же часовой пояс.

3 голосов
/ 17 февраля 2012

Вот список часовых поясов, отличающихся от GMT, надеюсь, это полезно!

echo '<pre>';
$zones_array = array();        
$timestamp = time();         
# to maintain the original timezone, store before
$default_timezone = date_default_timezone_get();
foreach (timezone_identifiers_list() as $key => $zone) {    
    date_default_timezone_set($zone);
    $zones_array[$key]['zone'] = $zone;
    $zones_array[$key]['diff_from_GMT'] = date('P', $timestamp);
}
# to maintain the original timezone, re-set after
date_default_timezone_set($default_timezone);    
print_r($zones_array);

Спасибо! * * 1004

1 голос
/ 26 августа 2013

Этот вопрос вдохновил меня на написание альтернативной функции для преобразования временной метки в необходимый часовой пояс.

Итак, ПРАВИЛЬНЫЕ шаги процедуры для записи, отображения (преобразования) времени:

1) record timestamp with time()
2) If you need to get a different timezone, use:
   2.1) Class based:
       2.1.1) DateTime class + setTimezone
       or
       2.1.2) date_default_timezone_set() and then date()

       2.1.1) is better and more flexible than 2.1.2)

    Function:

      function getLTime_class($ts, $uTZ, $format_str="Y.m.d H:i", $sTZ="America/Toronto"){
        // $ts - timestamp recorded with time(); if have date => convert to timestamp: strtotime($date_input); //for ex strtotime('2012-02-17 12:00:00'); => 1345219200 - same value for summer and winter (for toronto timezone);
        // $uTZ - TZ string (ex: 'America/Toronto'); convert timestamp to this TimeZone
        // $sTZ - TZ string (ex: 'America/Toronto'); convert timestamp from this TimeZone
        $TimeZone_server=new DateTimeZone($sTZ);
        $date_obj=new DateTime("@$ts", $TimeZone_server);
        $TimeZone_local=new DateTimeZone($uTZ);
        $date_obj->setTimeZone($TimeZone_local);
        return $date_obj->format($format_str);
      }

    Usage:

     $date_input=$_POST['date_input']; //read from POST
     $ts=strtotime($date_input); //for ex strtotime('2012-02-17 12:00:00'); => 1345219200 - same value for summer and winter (for toronto timezone);
     $userTZ='America/Toronto'; //read from user params
     $result=getLTime_class($ts, $userTZ, 'Y-m-d H:i:s');


   2.2) Non-Class based:

Function:

      //this function replaces the function with DateTime class. It's faster. $uTZoffset is integer.
      function getLTime_nonclass($ts, $uTZoffset, $format_str="Y.m.d H:i"){
        // $ts - timestamp recorded with time(); if have date => convert to timestamp: strtotime($date_input); //for ex strtotime('2012-02-17 12:00:00'); => 1345219200 - same value for summer and winter (for toronto timezone);
        // $uTZoffset - TZ offset (integer) $uTZoffset must consider DTS (for ex: in summer $uTZoffset=-4; in winter $uTZoffset=-5)
        $ts_offset=date('Z',$ts);
        if ($uTZoffset) $add_offset=$ts_offset-date('Z'); //when not UTC
        else $add_offset=0; //when UTC
        return date($format_str,$ts-$ts_offset+$uTZoffset*3600+$add_offset);
      }

    Usage:

     $date_input=$_POST['date_input']; //read from POST
     $ts=strtotime($date_input); //for ex strtotime('2012-02-17 12:00:00'); => 1345219200 - same value for summer and winter (for toronto timezone);
     $uTZoffset=-4; //read from user params. $uTZoffset - TZ offset (integer) $uTZoffset must consider DTS (for ex: in summer $uTZoffset=-4; in winter $uTZoffset=-5)
     $result=getLTime_nonclass($ts, $uTZoffset, 'Y-m-d H:i:s');

Результаты:

$ date_input = 2012-08-17 12: 00: 00

Server date: summer (2013-08-26)
    getLTime_class      =>  $userTZ='America/Toronto'   =>  2012-08-17 12:00:00
    getLTime_nonclass   =>  $uTZoffset=-4               =>  2012-08-17 12:00:00
    getLTime_class      =>  $userTZ='UTC'               =>  2012-08-17 16:00:00
    getLTime_nonclass   =>  $uTZoffset=0                =>  2012-08-17 16:00:00

Server date: winter (2013-02-26)
    getLTime_class      =>  $userTZ='America/Toronto'   =>  2012-08-17 12:00:00
    getLTime_nonclass   =>  $uTZoffset=-5               =>  2012-08-17 12:00:00
    getLTime_class      =>  $userTZ='UTC'               =>  2012-08-17 16:00:00
    getLTime_nonclass   =>  $uTZoffset=0                =>  2012-08-17 16:00:00

$ date_input = 2012-02-17 12: 00: 00

Server date: summer (2013-08-26)
    getLTime_class      =>  $userTZ='America/Toronto'   =>  2012-02-17 12:00:00
    getLTime_nonclass   =>  $uTZoffset=-4               =>  2012-02-17 12:00:00
    getLTime_class      =>  $userTZ='UTC'               =>  2012-02-17 17:00:00
    getLTime_nonclass   =>  $uTZoffset=0                =>  2012-02-17 17:00:00

Server date: winter (2013-02-26)    
    getLTime_class      =>  $userTZ='America/Toronto'   =>  2012-02-17 12:00:00
    getLTime_nonclass   =>  $uTZoffset=-5               =>  2012-02-17 12:00:00
    getLTime_class      =>  $userTZ='UTC'               =>  2012-02-17 17:00:00
    getLTime_nonclass   =>  $uTZoffset=0                =>  2012-02-17 17:00:00 

Я решил получить lTime_nonclass, надеясь сделать преобразование быстрее, чем с помощью классов. Все, что я прошу, это подтвердить, что getLTime_nonclass является действительной заменой getLTime_class. Пожалуйста, не стесняйтесь высказывать свое мнение. Спасибо

0 голосов
/ 24 мая 2016

Часто возникает задача, когда необходимо записать время в БД в GMT + 0, но функция time () вернет время сервера. Возможное решение с помощью следующей функции:

/**
     * Converts a local Unix timestamp to GMT
     *
     * @param   int Unix timestamp
     * @return  int
     */
    function local_to_gmt($time = '')
    {
        if ($time === '')
        {
            $time = time();
        }

        return mktime(
            gmdate('G', $time),
            gmdate('i', $time),
            gmdate('s', $time),
            gmdate('n', $time),
            gmdate('j', $time),
            gmdate('Y', $time)
        );
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...