一年多前,我在为私人飞机运营商编写的 PHP/MySQL 应用程序中广泛处理了这种情况。这两个平台有不同的策略来处理时区,但我将解释我是如何做到的。我将 MySQL 服务器设置为 UTC,并在用户配置文件注册过程中指定的时区运行每个 PHP 脚本。
MySQL 和 PHP(PHP 5.2 及更高版本)都具有本机日期时间数据类型。 MySQL 的 datetime 是一种原始数据类型,而 PHP 5.2 及以上版本提供了内置的日期时间类。 MySQL 日期时间数据类型不包含时区的元数据,但 PHP DateTime 对象始终包含时区。如果 PHP 日期时间构造函数未在第二个参数中指定可选时区,则 PHP 日期时间构造函数将使用 php 环境变量。
MySQL 和 PHP 都在配置文件中设置了默认时区。 MySQL 使用配置文件中设置的日期时间对于每个数据库连接,除非用户在使用命令启动连接后指定不同的时区SET time_zone = [timezone];
。 PHP 还使用服务器配置文件中设置的时区为每个脚本设置一个时区环境变量,并且可以使用 PHP 函数覆盖该环境变量date_default_timezone_set()脚本开始后。
PHP DateTime 类有一个名为timezone,这是一个PHP DateTimeZone 对象。 DateTimeZone 对象是使用准确时区的字符串指定的。这时区列表非常全面,在全球有数百个单独的时区。PHP 时区将自动考虑夏令时。
当用户在 Web 应用程序中生成日期时间时,在用户个人资料的时区中构造一个 PHP 日期时间对象。然后使用setTimezone方法将 DateTime 对象修改为 UTC 时区。现在您有了 UTC 格式的用户日期时间,并且可以将该值存储在数据库中。使用日期时间format方法将数据表示为 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 日期时间日期类型来存储日期时间值,而不是时间戳数据类型。手册中介绍了时间戳数据类型here.
Edit:您可以使用以下命令生成包含每个 PHP 时区字符串的数组列表标识符,它是 DateTimeZone 类的静态方法。