PHP和MySQL DateTime-时区处理

问题描述

我想在我的数据库 MysqL 5.7 )中存储一个DateTime值。我正在尝试找出处理时区的最佳方法。乍一看,MysqL似乎只采用DateTime格式的Y-m-d H:i:s,而忽略了任何时区信息。但是,Timestamp数据类型允许您提供UTC字符串。不幸的是,只有在日期大于2038年之前,这种情况才被接受。

我想到的情况如下。可以说我们的应用程序服务器和MysqL服务器在一个时区中。该时区的用户创建一个文件,然后在数据库中建立索引。不同时区的其他用户希望在应用程序中查看此文件和一些元信息。我想显示相对于此用户时区创建文件的正确时间。

如何正确存储此日期和时间?我了解可能需要对JavaScript的toLocaleString()进行一些操作。

编辑:看来这在MysqL 8中已得到解决(大部分),但我正在寻找 5.7兼容的解决方

MysqL 8.0.19开始,您可以在插入时指定时区偏移量 TIMESTAMP和DATETIME值插入表中。偏移量附加到 日期时间文字的日期部分,中间没有空格,并且 使用与设置time_zone系统变量相同的格式, 除了以下例外:

对于小时值小于10的情况,要求前导零。

值'-00:00'被拒绝。

不能使用时区名称,例如“ EET”和“ Asia / Shanghai”; 在这种情况下,也不能使用“ SYstem”。

解决方法

以UTC时间存储所有数据。在与多区域和/或多服务器/数据库中的用户打交道时,它为您提供了最大的灵活性。

  • 如果您使用的是JavaScript,则可以通过使用
  • 拉用户的时区
Intl.DateTimeFormat().resolvedOptions().timeZone

从这里开始,您将使用用户的时区来重新格式化datetime字符串。

  • 如果在Laravel(PHP)中使用Eloquent之类的ORM,则可以通过在模型中声明一个方法来动态调整datetime字段。例如,更改“ created_at”字段:
    public function getCreatedAtAttribute($value)
    {
        return Carbon::createFromTimestamp(strtotime($value))
            ->timezone('America/Los_Angeles')
            ->toDateTimeString();
    }

此选项假定您将用户的时区存储在数据库的另一个字段中。