如何用PHP获得格林威治标准时间?

时间:2009-05-12 07:30:41

标签: php timezone

我有一台设置为EST的服务器,数据库中的所有记录都设置为EST。我想知道如何将其设置为GMT。我想为用户提供时区选项。

6 个答案:

答案 0 :(得分:68)

强烈建议避免弄乱UNIX时间戳,使其看起来像一个不同的时区。这是我多次学习困难的一课。

时间戳是格林威治标准时间1970年1月1日午夜以来的秒数。无论您在世界的哪个位置,无论时区如何,给定的时间戳都代表完全相同的时刻。是的,时间戳“0”表示澳大利亚上午10点1/1/70,伦敦午夜1/1/70和洛杉矶时间下午5点31点,但这并不意味着您可以简单地添加或减去值并保证精度。

每年让我疲惫不堪的黄金榜样是夏令时出现的时候。夏令时意味着世界某些地方不存在“时钟时间”。例如,在美国大部分地区,2006年4月2日凌晨2点01分没有这样的时间。

虽然有足够的可理解的咆哮。我的建议是将日期作为时间戳存储在数据库中,然后......

例如,

$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

这将保持您的价值清洁(您不必担心添加偏移,然后在保存前减去),它将尊重所有夏令时规则,您甚至不必查找时区你想要的地方。

答案 1 :(得分:47)

无论服务器在哪个GMT时区,这都是获取任何时区的时间和日期的极其简单的方法。这是通过time()gmdate()函数完成的。 gmdate()函数通常会给我们GMT时间,但通过使用time()函数进行操作,我们可以获得GMT + N或GMT-N,这意味着我们可以获得任何GMT时区的时间。 / p>

例如,如果你必须得到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时间的例子一样

<?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
?>

答案 2 :(得分:4)

重要的是要注意,如果您使用日期('Z')转换存储在数据库中的日期,您将时间戳作为第二个参数,否则您的结果将不准确。 / p>

e.g。

在英国,有时候日期('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 :(得分:3)

以下是与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);

谢谢!

答案 4 :(得分:1)

我受到这个问题的启发,编写了一个将时间戳转换为所需时区的替代函数。

因此,CORRECT程序步骤记录,显示(转换)时间:

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 

我决定getLTime_nonclass希望比使用类更快地进行转换。 我要问的是确认getLTime_nonclass是getLTime_class的有效替代品。 请随时表达您的意见。感谢

答案 5 :(得分:0)

很多时候在GMT + 0的DB中有必要的记录时间,但是函数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)
        );
    }