By东关

Laravel应用处理跨时区问题的解决思路,时区修改后created_at未改变
2021-03-03

Laravel自身支持通过修改config('app.timezone')改变时区,整个应用范围内获取到的时间均认为是该时区的时间。然而,这个便利的功能并不能解决我们的问题,数据库保存的时间是本地时间,当配置改变时,得到的本地时间就是错的。比如时区为Asia/Shanghai,在2020-04-01 08:00:00创建一个记录,created_at的值为2020-04-01 08:00:00,将时区改为Asia/Tokyocreated_at的值也不会变,得到的仍然是2020-04-01 08:00:00,正确的应该是2020-04-01 09:00:00。因此,Laravel自带的时区设置功能只适合于应用不会动态切换时区的情况,一旦开始使用就不能去改变,否则时间都是错误的。

要支持动态切换时区,需要做以下3个方面的改造:

  1. 将数据库存储的时间总是为UTC时间;
  2. Laravel的Model在获取本地时间时,应根据UTC时间config('app.timezone')动态计算;
  3. 从数据库配置读取时区信息,设置config('app.timezone'),以支持动态切换时区;

Laravel默认的时区配置是手动的。要支持动态切换时区,需要在数据库的配置表(假设配置项的表名为options,对应的ModelOption)增加timezone的配置项。在初始化阶段,读取该配置项,去设置config('app.timezone')的值和通过date_default_timezone_set改变时区。

centos7设置本地时区

设置时区同样, 在 CentOS 7 中, 引入了一个叫 timedatectl 的设置设置程序.

用法很简单:

# timedatectl # 查看系统时间方面的各种状态

# timedatectl list-timezones # 列出所有时区

# timedatectl set-local-rtc 1 # 将硬件时钟调整为与本地时钟一致, 0 为设置为 UTC 时间
# timedatectl set-timezone Asia/Shanghai # 设置系统时区为上海

其实不考虑各个发行版的差异化, 从更底层出发的话, 修改时间时区比想象中要简单:

cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

mysql全局参数system_time_zone
系统时区,在MySQL启动时会检查当前系统的时区并根据系统时区设置全局参数system_time_zone的值。

The system time zone. When the server starts, it attempts to determine the time zone of the host machine automatically and uses it to set thesystem_time_zone system variable. The value does not change thereafter.

 

全局参数time_zone

用来设置每个连接会话的时区,默认为system时,使用全局参数system_time_zone的值。

The current time zone. This variable is used to initialize the time zone for each client that connects. By default, the initial value of this is ‘SYSTEM’ (which means, “use the value of system_time_zone”).

 

参数log_timestamps
用于设置Error Log/Genaral Log/Slow Log这三种日志的时间信息。
有效值为UTC(默认)和SYSTEM(本地系统时区),当设置为system时,会使用参数system_time_zone的值。

 

修改参数time_zone

# 启动命令
--default-time-zone=timezone
# 配置文件
default-time-zone=timezone
# 运行期间
set global time_zone = timezone

set global time_zone='+8:00'
set global time_zone='Asia/Shanghai'

你必须 登录 才能发表评论.

  • 还没有人留下脚印噢,快来踩踩叭