惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

aimingoo的专栏
aimingoo的专栏
TaoSecurity Blog
TaoSecurity Blog
P
Palo Alto Networks Blog
S
Securelist
C
CXSECURITY Database RSS Feed - CXSecurity.com
Cisco Talos Blog
Cisco Talos Blog
WordPress大学
WordPress大学
S
Schneier on Security
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
AWS News Blog
AWS News Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
P
Privacy International News Feed
Security Latest
Security Latest
NISL@THU
NISL@THU
Cyberwarzone
Cyberwarzone
I
Intezer
Hugging Face - Blog
Hugging Face - Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Privacy & Cybersecurity Law Blog
博客园_首页
Know Your Adversary
Know Your Adversary
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
人人都是产品经理
人人都是产品经理
Y
Y Combinator Blog
博客园 - Franky
月光博客
月光博客
GbyAI
GbyAI
G
Google Developers Blog
V2EX - 技术
V2EX - 技术
W
WeLiveSecurity
Google Online Security Blog
Google Online Security Blog
S
Security Affairs
K
Kaspersky official blog
Apple Machine Learning Research
Apple Machine Learning Research
美团技术团队
T
Troy Hunt's Blog
阮一峰的网络日志
阮一峰的网络日志
大猫的无限游戏
大猫的无限游戏
The GitHub Blog
The GitHub Blog
T
Threat Research - Cisco Blogs
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
博客园 - 司徒正美
Cloudbric
Cloudbric
Blog — PlanetScale
Blog — PlanetScale
博客园 - 叶小钗
U
Unit 42
H
Hackread – Cybersecurity News, Data Breaches, AI and More
C
Check Point Blog
G
GRAHAM CLULEY

方寸之間

修复 Arch Linux 的内核缺失问题 - 方寸之間 安装定制化 Vim - 方寸之間 树莓派配置旁路由过程记录 - 方寸之間 Cloudflare Tunnel 不完全上手指南 - 方寸之間 解除 New Bing 地区和浏览器限制的方法 - 方寸之間 FRP 上手教程 - 方寸之間 深入理解 Linux nohup 命令 - 方寸之間 C++智能指针是什么 - 方寸之間 PGP 工作原理详解 - 方寸之間 如何恢复 Windows EFI 分区 - 方寸之間 Scaleway IPV6 server 申请及使用攻略 - 方寸之間 Arch Linux 升级系统提示签名无效 - 方寸之間 Arch Linux 音响有杂音的解决办法 - 方寸之間 Arch Linux 如何切换内核 - 方寸之間 超简单的 Arch Linux + Windows 双启动教程 - 方寸之間 使用 UFW 配置 Linux 防火墙 - 方寸之間 Git 中的一个特殊 hash - 方寸之間 深入理解数据库事务 - 方寸之間 CRLF 和 LF 之间的区别与联系 - 方寸之間 DNS 的更新是如何工作的? - 方寸之間 浅析 Linux 的 cron 命令 - 方寸之間 如何快速查看 github 代码库中早期 commits - 方寸之間 黑科技:使用 GitHub 搭建自己的短链接服务 - 方寸之間 Build site with Franklin.jl - 方寸之間 iwd 的使用教程 - 方寸之間 超好用的 UML 工具推荐 - 方寸之間 ArchLinux 安装配置笔记 (Updated) - 方寸之間 如何将 Julia 添加到 Jupyter Notebook - 方寸之間 费曼技巧:最好的学习方式 - 方寸之間 How to Create Linux Desktop Entry - 方寸之間 Make a TODO robot with Github Actions - 方寸之間 C++继承 多态 虚函数 - 方寸之間 C++ inline 关键字详解 - 方寸之間 C++ Static 关键字详解 - 方寸之間 C++ type conversion notes - 方寸之間 Solution for _CRT_SECURE_NO_WARNINGS error - 方寸之間 IR Homework - 方寸之間 Customize Ubuntu themes, icons and Shell - 方寸之間 恢复右键菜单的新建命令 - 方寸之間 Hugo+Github 搭建个人博客 - 方寸之間
Django 项目时区更改错误的解决方案 - 方寸之間
Mercas · 2022-03-04 · via 方寸之間

记录我在更改时区时踩到的坑和解决方案,以及一点小小的感想。

TL;DR#

  1. 修改 Django 项目的TIME_ZONE设置为Asia/Shanghai
  2. 填充 MySQL 时区表:mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql
  3. 向 MySQL 全局配置文件的mysqld中添加default-time-zone='Asia/Shanghai';或者在 MySQL shell 中执行SET GLOBAL time_zone = 'Asia/Shanghai';
  4. 向 Django 项目设置中的DATABASES字段添加时区,并设置为Asia/Shanghai
  5. (optional)更新已经存在数据的时间:update blog_article set column_name=DATE_ADD(column_name, INTERVAL 8 HOUR);

正文#

起因#

今天在博客迁移服务器之后,突然想起来之前部署的时候,使用的是之前服务器的时区(UTC),没有使用 CST,就想着把时区改一下,不然挺不方便,而且看着挺难受的。修改的时候碰到了一些问题,这里记录一下解决方案以及一些个人感想。

尝试#

最开始,我觉得修改时区应该很简单,直接修改一下 Django 的时区设置即可。然而一个报错直接给我整不会了。

image

根据错误提示,我推测应该是 MySQL 的时区设置也不对,也要更新一下时区,然后直接在 mysql 配置文件中设置了 CST 时区:

default-time-zone='Asia/Shanghai'

重启 MySQL,竟然失败了?!!!

Restarting mysql (via systemctl): mysql.serviceJob for mysql.service failed because the control process exited with error code.

See "systemctl status mysql.service" and "journalctl -xe" for details.

failed!

不知道什么原因,这个方法不行,就在网上找到了另一个如何设置 MySQL 时区的答案,发现了另一种解决方法,在 MySQL 的 shell 中更新全局变量@@global.time_zone。所以删除了之前添加的时区配置,进入 MySQL shell 中进行设置:

SET @@global.time_zone = '+08:00';

然后,输出时区设置:

mysql> SELECT @@global.time_zone;

+--------------------+

| @@global.time_zone |

+--------------------+

| +08:00 |

+--------------------+

1 row in set (0.00 sec)

感觉设置成功了,然后尝试运行服务,发现还是同样的错误。明明时区设置成功了,为什么不生效呢?

答案?#

然后突然想到一个问题,我直接 Google 报错信息不就行了?果然,立刻就发现了一个答案,直接使用这个命令就能搞定:

mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql

动手试了一下,发现还真的可以,只不过会提示一些 Warning 信息:

Warning: Unable to load '/usr/share/zoneinfo/iso3166.tab' as time zone. Skipping it.

Warning: Unable to load '/usr/share/zoneinfo/leap-seconds.list' as time zone. Skipping it.

Warning: Unable to load '/usr/share/zoneinfo/leapseconds' as time zone. Skipping it.

Warning: Unable to load '/usr/share/zoneinfo/tzdata.zi' as time zone. Skipping it.

Warning: Unable to load '/usr/share/zoneinfo/zone.tab' as time zone. Skipping it.

Warning: Unable to load '/usr/share/zoneinfo/zone1970.tab' as time zone. Skipping it.

问题来了,为什么呢?虽然这样可以,但是不知道原因,心里有点不舒服,所以就查了官方文档。然后在这里中找到了答案:

Several tables in the mysql system schema exist to store time zone information . The MySQL installation procedure creates the time zone tables, but does not load them. To do so manually, use the following instructions.

根据上面这句话我们可以很容易发现,MySQL 安装过程创建时区表,但不会加载它们,需要我们手动加载。加载方法也很简单,就是我们上面提到的那行命令:

mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql

其中,mysql_tzinfo_to_sqly 用来读取系统的时区文件并从中生成 SQL 语句。 mysqly 用来处理这些语句以加载时区表。

有一点要注意的是,上面的命令会加载/usr/share/zoneinfo下的所有时区信息,所以如果你不想这样的话,也可以选择加载自己需要的时区,命令的基本格式是:

mysql_tzinfo_to_sql tz_file tz_name | mysql -u root -p mysql

比如:只加载Asia/Shanghai时区,可以使用下面的命令:

mysql_tzinfo_to_sql /usr/share/zoneinfo/Asia/Shanghai ‘Asia/Shanghai’ | mysql -u root -p mysql

在更新时区表后,重新启动mysqld以确保它不会继续提供过时的时区配置。

然后在 MySQL shell 中确认一下是否成功:

mysql> SELECT * FROM mysql.time_zone_name;

+---------------+--------------+

| Name | Time_zone_id |

+---------------+--------------+

| Asia/Shanghai | 1 |

+---------------+--------------+

1 row in set (0.01 sec)

mysql> SELECT @@global.time_zone;

+--------------------+

| @@global.time_zone |

+--------------------+

| Asia/Shanghai |

+--------------------+

1 row in set (0.00 sec)

更新完 MySQL 时区设置,然后重新进入 admin 界面,时间已经改变成了 CST 时区时间。

此外,在文档中我还找到了设置时区为Asia/Shanghai导致 MySQL 启动失败的原因:

Note

Named time zones can be used only if the time zone information tables in the **mysql** database have been created and populated. Otherwise, use of a named time zone results in an error:

mysql> SET time_zone = 'UTC';

ERROR 1298 (HY000): Unknown or incorrect time zone: 'UTC'

我们从上面的粗体部分可以发现:之前之所以设置Asia/Shanghai不生效是因为**MySQL 仅当数据库中的时区信息表已创建并填充时,才能使用命名时区。**因为刚开始没有填充时区表,MySQL 不知道 Asia/Shanghai 代表什么意思,所以才会出错无法启动 MySQL 服务。

测试#

尝试创建了一篇文章,发现时间也是对的,感觉到这里应该没什么问题了。但是,有点强迫症的我还是进入 MySQL 查看了一下数据,结果。。。数据库中的时间竟然还是 UTC 时间??

虽然还是没有成功,但是现在有一点可以确认的是,MySQL 的配置已经没有了问题,所以失败的原因出在了 Django 配置上。然后直接查看官方文档,在其中找到了原因。

When support for time zones is enabled, Django stores datetime information in UTC in the database, uses time-zone-aware datetime objects internally, and translates them to the end user’s time zone in templates and forms.

换句话说,只要是项目使用时区支持,那么,无论你设置什么时区,Django 在数据库中存储数据默认都是使用 UTC 时间。所以,如果想要更改 Django 存储数据的时区,还需要在 setting 中的 DATABASES 里,将TIME_ZONE选项设置为你想要的时区。

更新了 Django 项目的配置,然后重新启动,进入 admin 界面,时间没问题,然后进入 MySQL shell 查看时间列,也没问题。终于,终于成功了!!!

收尾#

当然,还有一步,那就是更新 MySQL 数据库中已经存在的数据的时间,这个直接在原来的时间上加 8 小时即可:

update blog_article set column_name=DATE_ADD(column_name, INTERVAL 8 HOUR);

想法#

最后,虽然这只是个小问题,也解决了,但是也让我有点意识到了自己的一些不好的思维方式,本来只需要直接查找一下类似的错误,很快就能找到解决方案。