【问题标题】:How do I get Greenwich Mean Time in PHP?如何在 PHP 中获得格林威治标准时间?
【发布时间】:2010-10-25 11:50:35
【问题描述】:

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

【问题讨论】:

    标签: php timezone


    【解决方案1】:

    我会强烈建议避免弄乱 UNIX 时间戳,使其看起来像一个不同的时区。这是我经历过很多次的惨痛教训。

    时间戳是自格林威治标准时间 1970 年 1 月 1 日午夜以来的秒数。无论您身在何处,给定的时间戳都代表完全相同的时刻,而与时区无关。是的,时间戳“0”表示澳大利亚 1 月 1 日上午 10 点,伦敦 1 月 1 日午夜,洛杉矶 69 年 12 月 31 日下午 5 点,但这并不意味着您可以简单地添加或减去值并保证准确性。

    每年都让我困扰太久的典型例子是夏令时出现的时候。夏令时意味着世界某些地区不存在“时钟时间”。例如,在美国大部分地区,没有 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
    

    这将使您的值保持干净(您不必担心添加偏移量,然后在保存之前减去),它将遵守所有夏令时规则,您甚至不必查找时区你想要的地方。

    【讨论】:

    • "至少直到时区偏移发生变化,无论是由于夏令时还是其他原因。" ......你说我的解决方案有问题?
    • “一个能够做到这一点的 PHP 库” - 它是内置的。“如果政客改变规则怎么办” - 好:你不必更改任何代码 - 如果 PHP 保持更新,那么它就可以工作了。 “如果您有其他代码可以获取本地日期怎么办” - 冲洗并重复。
    • nickf 说的太对了,让人心疼。您想依靠库或操作系统调用来避免自己进行时区偏移计算。与 nickf 类似,我也很辛苦地学会了这一点。
    • 在这里!任何处理这个问题的人都应该使用这个解决方案。两个答案都很好,但这个是两个中更好的一个。仅仅因为它可能会混淆 n3wbs 并不意味着它是一个不正确的解决方案。谢谢尼克!旁注:nickf 有 78k 的代表,而 p01nd3xt3r 有 62。这说明了很多关于用户和他们带来的东西。
    • @J.Bruni 到底是什么问题?几乎每一种编程语言(加上我所知道的每一种 SQL 实现)都有将时间戳转换为日期和时间的内置方法。
    【解决方案2】:

    无论服务器位于哪个 GMT 时区,这里都有一个非常简单的方法来获取任何时区的时间和日期。这是通过time()gmdate() 函数完成的。 gmdate() 函数通常为我们提供 GMT 时间,但通过使用 time() 函数,我们可以获得 GMT+N 或 GMT-N,这意味着我们可以获得任何 GMT 时区的时间。

    例如,如果你必须得到 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
    ?>
    

    【讨论】:

    • 这是一个很好的例子...但是我怎么知道必须减去或添加到 gmdate 时间的时间?
    • 我猜这个答案是错误的,因为 time() 函数将获取服务器本地时间。它不会获得 UTC,所以如果您不知道服务器时间是什么,那么您将无法获得预期的时区时间。
    • 这个答案很旧,会产生奇怪的结果
    • 这需要您在$offset=5*60*60 代码中硬编码GMT 偏移量。不理想,尤其是当您需要考虑夏令时或跨时区的服务器集群时。
    【解决方案3】:

    这里是与格林威治标准时间不同的时区列表,希望对您有所帮助!

    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】:

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

    例如

    在英国,有时 date('Z') 会给出 3600,有时会给出 0。

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

    给 0

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

    给 3600

    所以纯粹使用 strtotime($dbDateValue) - date('Z') 可能是错误的

    改为使用:

    $dbDateTimestamp = strtotime($dbDateValue); // where $dbDateValue something like 2012-01-01 22:34:00
    
    $utcTimestamp = strtotime($dbDateTimestamp) - date('Z', $dbDateTimestamp);
    

    这当然依赖于 PHP 和数据库都设置为相同的时区。

    【讨论】:

      【解决方案5】:

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

      因此,记录、显示(转换)时间的正确程序步骤:

      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 的有效替代品。 请随时发表您的意见。谢谢

      【讨论】:

        【解决方案6】:

        很多时候有任务需要在 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)
                );
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-03-10
          • 2011-05-13
          • 2011-03-01
          • 1970-01-01
          • 2019-11-25
          • 1970-01-01
          • 2011-10-30
          • 2013-06-01
          相关资源
          最近更新 更多