【问题标题】:How can I easily convert dates from UTC via PHP?如何在 PHP 中轻松地从 UTC 转换日期?
【发布时间】:2009-06-04 20:42:18
【问题描述】:

我将日期存储在 MySQL 数据库中的 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))));

有没有更短的方法?

【问题讨论】:

  • 单线有什么问题?
  • 没什么,如果这是标准的做法。如果有更简单的东西,我只是不想在我的代码库中粘贴几十个地方。
  • 不是你要求的,但以防万一:记得设置 MySQL 时区。或者 MySQL 会自行转换日期。见:dev.mysql.com/doc/refman/5.1/en/time-zone-support.html
  • phpphil,它会怎么做呢? DATETIME 字段应该与时区无关。您是说 MySQL 将使用系统的时区和 NOW() 和 CURDATE() 等函数吗?我已将 --timezone=UTC 添加到 MySQL 的 my.cnf。
  • 手册说:“当前会话时区设置会影响对区域敏感的时间值的显示和存储。这包括由 NOW() 或 CURTIME() 等函数显示的值,以及在 TIMESTAMP 列中存储和检索的值。TIMESTAMP 列的值从当前时区转换为 UTC 以进行存储,并从 UTC 转换为当前时区以进行检索。使用 my.cnf 中的条目,它应该可以正常工作!

标签: php timezone


【解决方案1】:

为什么不使用内置的DateTime/TimeZone 功能?

<?php

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

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

?>

日期时间类: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

【讨论】:

  • fyi:当已经使用 date_default_timezone_set() 设置了默认时区时,DateTime::setTimezone 是可有可无的。
  • 对,但如果他将 date_default_timezone_set() 设置为 UTC,并且他希望日期为 PDT 等格式,则必须明确设置。
【解决方案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);
}

【讨论】:

    【解决方案3】:

    使用单个函数将用户时区转换为服务器时区,反之亦然:

    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');
    

    【讨论】:

      【解决方案4】:

      您正在做的是正确的做事方式。我建议坚持只在 UTC 中工作,并在最后一分钟进行转换以进行显示。

      这是我使用 PHP 附带的 DateTime 类为时区转换整理的一个快速函数。它比你拥有的代码多一点,但我认为它更容易,也是一种更好的结构化方式......

      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/

      希望对您有所帮助。

      【讨论】:

      • 我其实很喜欢这个解决方案,我的 DateTime 存储在 MySQL 中,我可以根据用户的时区设置来转换时间。
      • 很好的解决方案,我唯一改变的是传递格式,因为有时我并不总是想要特定的格式,尤其是在向最终用户显示时。 +1 好答案
      【解决方案5】:

      这是我们对服务器所做的。我们将所有内容设置为使用 UTC,并通过即时转换 UTC 来显示在用户的时区中。本文底部的代码是如何使其工作的示例;您应该确认它适用于您的设置(即夏令时等)。

      配置 CentOS

      1. 编辑/etc/sysconfig/clock并将ZONE设置为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. 编辑 my.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);
          }
      
      }
      

      【讨论】:

      • 我们最终做了同样的事情,差不多。我们通过 date_default_timezone_set('UTC') 在 PHP 中将时区设置为 UTC,并且我们还更改了 MySQL 中的默认时区。然后,为了进行转换,我们使用 PEAR Date 类,它甚至可以处理夏令时。
      【解决方案6】:

      花了很多时间处理这个问题,不要试图自己实现时区转换。这是一个皇家 PIA,充满了困难,而且在国际上很难做到正确。

      也就是说,最好的选择是将 MySQL 中的 datetime 转换为 timestamp,然后使用数据库转换时间:

       mysql> set time_zone='America/New_York';
      

      timestamp在 MySQL 中更小,并且支持时区转换。 日期时间没有。

      在页面上显示站点信息之前,只需调用上面的命令,它就会正确显示,而无需任何 PHP 代码更改。

      注意事项:

      1. 如果您使用 NOW() 或任何本地时间函数,则应将它们更新为 UTC_TIMESTAMP()
      2. 时间戳有有趣的更新和插入属性,您可能想关闭它们。

      关闭时间戳属性:

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

      DEFAULT 0 会在您更新其他列时禁用正在更新的列。

      【讨论】:

      • 非常有趣,值得了解。这个线程--stackoverflow.com/questions/998523/… 不同意你的观点,说“TIMESTAMP 不打算用于存储一般的日期/时间信息。”你对此有什么想法吗?
      • 好吧,我完全不同意。 TIMESTAMP 可用于一般日期/时间信息,只要您不遇到它周围的问题,特别是它在数据库中存储为 UTC 无符号整数,并且它将在 2038 年(或所以...)如果您需要存储 1970 年之前或 2038 年之后的日期,请使用 DATETIME 并执行支持时区所需的操作。否则,省去你自己的努力,使用时间戳并(几乎)免费获得 TZ 翻译。
      【解决方案7】:
      <?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
      ?>
      

      【讨论】:

        【解决方案8】:
        ADDTIME($utcDate,$Site->getUTCOffset())
        

        【讨论】:

          猜你喜欢
          • 2010-12-27
          • 2014-11-11
          • 2021-03-26
          • 2011-04-17
          • 2011-11-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多