我在一年前为一家私人飞机运营商编写的 PHP/MySQL 应用程序中广泛处理了这种情况。在这两个平台上处理时区有不同的策略,但我将解释我是如何做到的。我将 MySQL 服务器设置为 UTC,并在用户为用户配置文件注册过程中指定的时区运行每个 PHP 脚本。
MySQL 和 PHP(PHP 5.2 及更高版本)都具有本地日期时间数据类型。 MySQL 的 datetime 是一种原始数据类型,而 PHP 5.2 及更高版本提供了内置的DateTime class。 MySQL datetime 数据类型不包含时区的元数据,但 PHP DateTime 对象始终包含时区。如果 PHP 日期时间构造函数没有在第二个参数中指定可选时区,则 PHP 日期时间构造函数使用 php 环境变量。
MySQL 和 PHP 都在配置文件中设置了默认时区。 MySQL 对每个数据库连接使用datetime set in the config file,除非用户在使用命令SET time_zone = [timezone]; 启动连接后指定不同的时区。 PHP 还使用服务器配置文件中设置的时区为每个脚本设置了一个时区环境变量,并且可以在脚本启动后使用 PHP 函数date_default_timezone_set() 覆盖该环境变量。
PHP DateTime 类有一个名为timezone 的属性,即PHP DateTimeZone object。 DateTimeZone 对象是使用字符串指定的确切时区。 list of timezones 是全面的,在全球拥有数百个单独的时区。 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 日期类型来存储日期时间值,而不是时间戳数据类型。时间戳数据类型在手册here 中有介绍。
编辑:
您可以使用 listIdentifiers 生成一个包含每个 PHP 时区字符串的数组,这是 DateTimeZone 类的静态方法。