处理PHP中的时区

时间:2008-12-06 21:05:52

标签: php database timezone

PHP中的时区的一些问题已经在我脑海中浮现了一段时间了,我想知道是否有更好的方法来处理它而不是我现在正在做的事情。

所有问题都围绕着重新格式化数据库存储日期:

在处理必须支持多个时区(对于用户)的站点时,为了规范化存储时间戳的时区,我始终使用CURRENT_TIMESTAMP属性或NOW()将其与服务器时区一起存储功能。

这样我就不必考虑在输入时间戳时为PHP设置了什么时区(因为PHP时间函数是时区感知的)。对于每个用户,根据他的偏好,我使用以下命令在我的引导程序文件中设置时区:

date_default_timezone_set($timezone);

当我想用php date()函数格式化日期时,由于MySQL目前以Y-m-d H:i:s格式存储时间戳,因此必须进行某种形式的转换。不考虑时区,你可以简单地运行:

$date = date($format,strtotime($dbTimestamp));

问题在于date()strtotime()都是时区感知功能,这意味着如果PHP时区设置与服务器时区不同,则时区偏移将应用两次(而不是一次)正如我们所希望的那样。)

为了解决这个问题,我通常使用UNIX_TIMESTAMP()函数检索MySQL时间戳,该函数不是时区感知的,允许我直接应用date() - 从而只应用一次时区偏移。

我真的不喜欢这种'hack',因为我不能像往常那样检索这些列,或者使用*来获取所有列(有时它会极大地简化查询)。此外,有时候它根本不是使用UNIX_TIMESTAMP()的选项(特别是在使用开源包时没有太多抽象的查询组合)。

另一个问题是,当存储时间戳时,如果不能使用CURRENT_TIMESTAMPNOW() - 存储PHP生成的时间戳将使用我想避免的时区偏移量存储它。 / p>

我可能在这里遗漏了一些非常基本的东西,但到目前为止我还没有能够提出处理这些问题的通用解决方案,所以我不得不逐个处理它们。非常欢迎你的想法

4 个答案:

答案 0 :(得分:12)

几个月前,我们花了一些时间思考这个问题。我们最终得到的技术非常简单:

  1. 以GMT / UTC格式存储日期(例如0时区偏移)。
  2. 从数据库中检索后应用当前用户时区偏移量(例如,在向用户显示之前或在您需要时)。
  3. 我们使用Unix时间戳格式。但这没关系。

答案 1 :(得分:6)

从PHP 5.2开始,您可以使用DateTime,这样可以轻松处理时区:

$datetime = new DateTime($dbTimestamp, $timezone);
echo $datetime->format('Y-m-d H:i:s');
$datetime->setTimezone(new DateTimeZone('Pacific/Nauru'));
echo $datetime->format('Y-m-d H:i:s');

答案 2 :(得分:1)

您可以尝试使用SET time_zone强制MySQL在任何地方使用UTC。

不幸的是我对strtotime / UNIX_TIMESTAMP事情没有任何答案,事实上我对Postgres也有同样的问题。

答案 3 :(得分:0)

我没有在网上找到任何优雅的解决方案,因此我创建了一个Timezone HTML select generator脚本,并且直接在这里output。它是这样的:

<select name="timezone" id="timezone">
    <optgroup label="UTC -11:00">
        <option value="Pacific/Midway">UTC -11:00 Midway</option>
        <option value="Pacific/Niue">UTC -11:00 Niue</option>
        <option value="Pacific/Pago_Pago">UTC -11:00 Pago_Pago</option>
    </optgroup>
    <optgroup label="UTC -10:00">
        <option value="America/Adak">UTC -10:00 Adak</option>
        <option value="Pacific/Honolulu">UTC -10:00 Honolulu</option>
        <option value="Pacific/Johnston">UTC -10:00 Johnston</option>
        <option value="Pacific/Rarotonga">UTC -10:00 Rarotonga</option>
        <option value="Pacific/Tahiti">UTC -10:00 Tahiti</option>
    </optgroup>
    . . . . . . . . . . . . . .
    <optgroup label="UTC +13:00">
        <option value="Pacific/Apia">UTC +13:00 Apia</option>
        <option value="Pacific/Enderbury">UTC +13:00 Enderbury</option>
        <option value="Pacific/Fakaofo">UTC +13:00 Fakaofo</option>
        <option value="Pacific/Tongatapu">UTC +13:00 Tongatapu</option>
    </optgroup>
    <optgroup label="UTC +14:00">
        <option value="Pacific/Kiritimati">UTC +14:00 Kiritimati</option>
    </optgroup>
</select>

享受!