在不同时区处理PHP服务器和MySQL服务器

时间:2020-03-05 18:41:13  来源:igfitidea点击:

对于我们这些使用标准共享托管软件包(例如GoDaddy或者Network Solutions)的用户,当托管服务器(PHP)和MySQL服务器位于不同时区时,如何处理日期时间转换?

此外,是否有人可以提供一些最佳实践建议来确定我们网站的访问者所在的时区并适当地操作datetime变量?

解决方案

回答

将所有内容存储为UTC。我们可以在客户端级别或者使用客户端设置在服务器端进行转换。

PHP日期

MySQL的UTC时间戳

回答

从PHP 5.1.0开始,我们可以使用date_default_timezone_set()函数设置脚本中所有日期/时间函数使用的默认时区。

对于MySql(引自" MySQL服务器时区支持"页面)

Before MySQL 4.1.3, the server operates only in the system time zone set at startup. Beginning with MySQL 4.1.3, the server maintains several time zone settings, some of which can be modified at runtime.

我们感兴趣的是时区的每个连接设置,我们将在脚本开始时使用该设置

SET timezone = 'Europe/London';

至于检测客户端时区设置,我们可以使用一些JavaScript来获取该信息并将其保存到cookie,然后在后续页面读取中使用它来计算正确的时区。

//Returns the offset (time difference) between Greenwich Mean Time (GMT) 
//and local time of Date object, in minutes.
var offset = new Date().getTimezoneOffset(); 
document.cookie = 'timezoneOffset=' + escape(offset);

或者,我们可以为用户提供选择自己的时区的选择权。

回答

由于之前的dateTime类型存在问题,因此我将所有日期都保存为bigint。我将time()PHP函数的结果保存到其中,现在它们算在同一时区中了:)

回答

从?eljko?ivkovi?的答案来看,像"欧洲/伦敦"这样的时区描述符只有在mySQL管理员已将时区表添加到系统并保持更新的情况下才起作用。

否则,我们只能使用数字偏移量,例如" -4:00"。幸运的是php date('P')格式提供了它(从5.1.3开始)

因此,例如,我们可能拥有一个应用程序配置文件

define('TZ', 'US/Pacific');
....
if (defined('TZ') && function_exists('date_default_timezone_set')) {
    date_default_timezone_set(TZ);
    $mdb2->exec("SET SESSION time_zone = " . $mdb2->quote(date('P')));
}

这意味着PHP和mySQL将就使用哪个时区偏移量达成一致。

始终使用TIMESTAMP来存储时间值。该列实际上存储为UNIX_TIME(时期),但在写入时从当前time_zone偏移量隐式转换,在读取时从当前time_zone偏移量隐式转换。

如果要显示其他时区的用户时间,请在上面设置其给定的时区,而不是全局的define()。 MySQL会在应用看到结果集时自动将TIMESTAMP值转换(有时可能是个问题,如果我们实际上也需要知道事件的原始时区,则它需要在另一列中)

而且,"为什么不将所有时间都存储为int",这确实使我们失去了比较和验证日期的能力,这意味着我们始终必须在应用程序级别转换为日期表示形式(并且当我们正在直接快速查看数据,在1254369600发生了什么?)