PHP和MySQL存在时区问题

时间:2009-06-27 17:29:22

标签: php mysql timezone

我的服务器时间是GMT,每当有人上线时我会执行以下操作。

// Set a default timezone
$defaultTimeZone = 'America/Toronto';

// load the user, if they are online...
$onlineUser = new user();
if (isset($_SESSION['user_id']))
{
    if ($onlineUser->loadUser($_SESSION['user_id']))
    {
        $defaultTimeZone = $onlineUser->timeZone;
    }
}

// set time zones
date_default_timezone_set($defaultTimeZone);
$db->query("SET SESSION time_zone = '".$defaultTimeZone."'");

所以,我的问题是这样的......每当有人做某事时,它会在用户当地时间存储日期/时间......导致我一大堆问题。

我想要的只是将所有内容存储在GMT中,但让用户看到&与当地时区的数据进行交互。

修改

以下是我更新用户状态的方法:

public function updateStatus()
{
    global $db, $common, $config;

    // update the user record
    $data = array(
        'date_last_active'  => new Zend_Db_Expr('NOW()')
    );

    $db->update('users', $data, 'user_id='.$this->userId);
}

这是我将日期戳变成秒的功能......

public function dateTimeToUnixTime($dateString)
{
    if (strlen($dateString) < 10)
    {
        return "";
    }

    $parseDateTime = split(" ", $dateString);
    $parseDate = split("-", $parseDateTime[0]);

    if (isset($parseDateTime[1]))
    {
        $parseTime = split(":", $parseDateTime[1]);
    }
    else
    {
        $parseTime = split(":", "00:00:00");
    }

    return mktime($parseTime[0], $parseTime[1], $parseTime[2], $parseDate[1], $parseDate[2], $parseDate[0]);
}

最后,我如何比较日期:

    $date = $oUser->dateLastActive;

    $lastSeen = abs($common->dateTimeToUnixTime(date('Y-m-d H:i:s')) - $common->dateTimeToUnixTime($date));

    if ($lastSeen < 300 )
    {
        echo "<font size='1' color='green'><strong>Online</strong></font>";
    }

    if ($lastSeen >= 300)
    {
        echo "<font size='1' color='black'><strong>Offline</strong></font>";
    }

3 个答案:

答案 0 :(得分:9)

这里的技巧是知道列类型date_last_active是什么。我有足够的经验TIMESTAMPDATETIME知道一个人翻译(并尊重)MySQL time_zone会话变量,另一个则没有。

mysql> SET SESSION time_zone = 'America/New_York';
Query OK, 0 rows affected (0.00 sec)

mysql> create table timetest ( dt datetime NULL, ts timestamp NOT NULL DEFAULT 0 );
Query OK, 0 rows affected (0.06 sec)

mysql> INSERT INTO timetest ( dt, ts ) VALUES ( UTC_TIMESTAMP(), UTC_TIMESTAMP() );
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO timetest ( dt, ts ) VALUES ( NOW(), NOW() );
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM timetest;
+---------------------+---------------------+
| dt                  | ts                  |
+---------------------+---------------------+
| 2009-06-27 17:53:51 | 2009-06-27 17:53:51 | 
| 2009-06-27 13:53:54 | 2009-06-27 13:53:54 | 
+---------------------+---------------------+
2 rows in set (0.00 sec)

mysql> set session time_zone='UTC';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT * FROM timetest;
+---------------------+---------------------+
| dt                  | ts                  |
+---------------------+---------------------+
| 2009-06-27 17:53:51 | 2009-06-27 21:53:51 | 
| 2009-06-27 13:53:54 | 2009-06-27 17:53:54 | 
+---------------------+---------------------+
2 rows in set (0.00 sec)

所以,这就是我的工作:

  • 插入数据库时​​,在PHP和MySQL中使用UTC。在my.cnf我有:time_zone=UTC以避免MySQL中的任何问题,在PHP中我date_default_timezone_set('UTC')
  • 使用UTC_TIMESTAMP()代替NOW() - 一个是UTC,一个使用本地(会话)时区。如果您正在遵循上面的第一点,请使用UTC_TIMESTAMP()。
  • 在显示任何内容之前选择向用户显示set time_zone=' local_time_zone '
  • 如果你需要显示内容,然后更新,请确保使用PHP和MySQL中适当的时区更改来支持您的呼叫。

希望这足以弄清楚如何处理这个问题。如果您还有其他问题,请与我们联系。

答案 1 :(得分:0)

我认为Mysql的NOW()函数存储当前时区,这绝对是一个麻烦,我会查看CONVERT_TZ(dt,from_tz,to_tz),这可以解决你的问题,我相信php的time()返回服务器时间,你可以存储这个。唯一的缺点是你要么必须将返回值转换为日期时间/时间戳兼容值,要么将其存储为varchar。使用convert_tz的缺点是你可能会遇到一些丑陋的查询,并且每次使用它时都必须弄清楚当前的时区。

答案 2 :(得分:0)

我花了差不多半天时间来解决这个问题,我想我需要帮助别人。所以我为你提供了一些指导方针,以避免时区问题。

  

首先,您有两个选项可以使用 MYSQL TIMEZONE PHP   TIMEZONE 如果你想远离时区噩梦,不要把它们混在一起。

如果您选择 MYSQL TIMEZONE:

FOR INSERTION:

fieldname: yourfieldname

datatype: timestamp 

default: CURRENT_TIMESTAMP

FOR UPDATION:

UPDATE YOUR_TABLE SET youfieldname = NOW() WHERE CONDITION;

FOR SELECTION:

您唯一需要做的就是为您的应用程序设置需求时区mysql会自动将存储的时间戳转换为您指定的时区。

mysql>SET SESSION time_zone='offset'; 
mysql>SELECT NOW();

偏移示例: +05:30 对于印度,同样可以找到您所在地区的偏移量。

现在,您将从mysql获得所需的日期和时间。

如果您选择 PHP TIMEZONE

只需使用此功能设置您的期望时区:

date_default_timezone_set('America/Los_Angeles');

FOR INSERTION:

fieldname: yourfieldname

数据类型:日期时间

使用PHP日期函数存储日期和时间:

$sql = "INSERT INTO timetest ( YOURDATETIMEFIELD ) VALUES ('".date('Y-m-d H:i:s')."')";

FOR UPDATION:

$sql = "UPDATE YOUR_TABLE SET yourdatetimefield = '".date('Y-m-d H:i:s')."'";

FOR SELECTION:

$sql = "SELECT yourdatetimefield FROM yourtable";

我希望这对你有所帮助。