我在一年前为一家私人飞机运营商编写的 PHP/MySQL 应用程序中广泛处理了这种情况。在这两个平台上处理时区有不同的策略,但我将解释我是如何做到的。我将 MySQL 服务器设置为 UTC,并在用户在用户配置文件注册过程中指定的时区运行每个 PHP 脚本。
MySQL 和 PHP(PHP 5.2 及更高版本)都具有本机日期时间数据类型。MySQL 的 datetime 是一种原始数据类型,而 PHP 5.2 及更高版本提供了内置的DateTime 类。MySQL datetime 数据类型不包含时区的元数据,但 PHP DateTime 对象始终包含时区。如果 PHP 日期时间构造函数未在第二个参数中指定可选时区,则 PHP 日期时间构造函数使用 php 环境变量。
MySQL 和 PHP 都在配置文件中设置了默认时区。MySQL 使用配置文件中为每个 db 连接设置的日期时间,除非用户在使用命令启动连接后指定不同的时区SET time_zone = [timezone];
。PHP 还使用服务器配置文件中设置的时区为每个脚本设置一个时区环境变量,并且可以date_default_timezone_set()
在脚本启动后使用 PHP 函数覆盖该环境变量。
PHP DateTime 类有一个名为timezone的属性,它是一个PHP DateTimeZone 对象。DateTimeZone 对象是使用字符串指定的确切时区。时区列表很全面,在世界各地有数百个单独的时区。 PHP 时区将自动考虑夏令时。
当用户在 Web 应用程序中生成日期时间时,在用户配置文件的时区中构造一个 PHP 日期时间对象。然后使用该setTimezone
方法将 DateTime 对象修改为 UTC 时区。现在您有了 UTC 格式的用户日期时间,您可以将值存储在数据库中。使用 DateTimeformat
方法将数据表示为 MySQL 接受的格式的字符串。
所以用户生成一个日期时间,你在用户指定的时区创建一个 PHP 日期时间对象:
// set using an include file for user profile
$user_timezone = new DateTimeZone('America/New_York');
// 1st arg in format accepted by PHP strtotime
$date_object1 = new DateTime('8/9/2012 5:19 PM', $user_timezone);
$date_object1->setTimezone(new DateTimeZone('UTC'));
$formated_string = $date_object1->format('Y-m-d H:i:s');
$query_string = "INSERT INTO `t_table1` (`datetime1`) VALUES('$formated_string')";
当您从数据库中检索值时,以 UTC 构造,然后转换为用户的时区。
$query_string = "SELECT `datetime1` FROM `t_table1`";
$date_object1 = new DateTime($datetime_string_from_mysql, new DateTimeZone('UTC'));
$date_object1->setTimezone($user_timezone);
$string_for_display_in_application = $date_object1->format('m/d/Y g:i a');
使用此方法,您的日期时间值始终以 UTC 格式存储在数据库中,并且用户始终会体验到他/她的个人资料时区中的值。如果需要,PHP 将针对每个时区更正夏令时。
一个问题:这个解释不包括 MySQL 时间戳数据类型。我建议使用 MySQL datetime 日期类型来存储日期时间值,而不是时间戳数据类型。此处的手册中介绍了时间戳数据类型。
编辑:您可以使用listIdentifiers
生成一个包含每个 PHP 时区字符串的数组,这是 DateTimeZone 类的静态方法。