Проблемы с часовым поясом с PHP и MySQL - PullRequest
2 голосов
/ 27 июня 2009

Время моего сервера в 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, но пользователи могли видеть и взаимодействовать с данными в своем местном часовом поясе.

EDIT:

Вот как я обновляю статус пользователя:

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 ]

9 голосов
/ 27 июня 2009

Хитрость в том, чтобы узнать тип столбца date_last_active. У меня было достаточно опыта работы с TIMESTAMP и DATETIME, чтобы знать, что один переводит (и учитывает) переменную сессии 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)

Итак, вот что я делаю:

  • При вставке в базу данных используйте UTC в PHP и в MySQL. В my.cnf у меня есть: time_zone=UTC, чтобы избежать любых проблем в MySQL, а в PHP I date_default_timezone_set('UTC').
  • Используйте UTC_TIMESTAMP() вместо NOW() - один - UTC, другой - местный (сеансовый) часовой пояс. Если вы следуете первому пункту выше, используйте UTC_TIMESTAMP ().
  • При выборе отображения для пользователя, set time_zone=' local_time_zone ' перед отображением чего-либо.
  • Если вам нужно отобразить материал, а затем обновить, убедитесь, что ваши звонки заключены в соответствующие изменения часового пояса в PHP и MySQL.

Надеюсь, этого достаточно, чтобы понять, как к этому подойти. Дайте мне знать, если у вас есть дополнительные вопросы.

0 голосов
/ 30 сентября 2015

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

Прежде всего, у вас есть две опции: либо MYSQL TIMEZONE , либо PHP. TIMEZONE не смешивайте это друг с другом, если хотите держаться подальше от кошмаров часовых поясов.

ЕСЛИ ВЫ ВЫБИРАЕТЕ MYSQL TIMEZONE:

ДЛЯ ВСТАВКИ:

fieldname: yourfieldname

datatype: timestamp 

default: CURRENT_TIMESTAMP

ДЛЯ ОБНОВЛЕНИЯ:

UPDATE YOUR_TABLE SET youfieldname = NOW() WHERE CONDITION;

ДЛЯ ВЫБОРА:

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

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

пример смещения: + 05: 30 для Индии аналогично найдите смещение для региона вашей области.

Теперь вы получите желаемую дату и время из mysql.

ЕСЛИ ВЫ ВЫБИРАЕТЕ PHP TIMEZONE :

Просто установите желаемый часовой пояс, используя эту функцию:

date_default_timezone_set('America/Los_Angeles');

ДЛЯ ВСТАВКИ:

имя поля: ваше поле

тип данных: datetime

Используйте функцию даты PHP для хранения даты и времени:

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

ДЛЯ ОБНОВЛЕНИЯ:

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

ДЛЯ ВЫБОРА:

$sql = "SELECT yourdatetimefield FROM yourtable";

Надеюсь, это поможет вам.

0 голосов
/ 27 июня 2009

Я думаю, что функция Mysql NOW () хранит текущий часовой пояс, что определенно хлопотно, я бы проверил CONVERT_TZ (dt, from_tz, to_tz), это может решить вашу проблему, также я считаю, что php time () возвращает сервер время, вы могли бы хранить это вместо. Единственным недостатком является то, что вам нужно либо преобразовать возвращаемое значение в значение, совместимое с датой / временем, либо сохранить его как varchar. Недостаток использования convert_tz заключается в том, что вы можете получить несколько уродливых запросов, и вам придется выяснять текущий часовой пояс каждый раз, когда вы его используете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...