如何正确地处理时间

220 阅读2分钟

引言

涉及多国家时时常会被时间的时区所困惑。

MYSQL中的时间类型


根据所需时间的精度选择不同的类型进行存储。

存储范围

每种日期类型都有一个有效范围,超过则报错并以零值存储。


时区

需要注意的是即便 DATETIMETIMESTAMP 返回相同的格式,它们的工作方式很不同。在 INSERT 或 UPDATE 查询中,TIMESTAMP 自动把自身设置为当前的日期和时间。TIMESTAMP 也接受不同的格式,比如 YYYYMMDDHHMMSS、YYMMDDHHMMSS、YYYYMMDD 或 YYMMDD。

并且TIMESTAMP 带时区,DATETIME 不带时区。

TIMESTAMP具体效果为:

当插入日期时,会先转换为本地时区后再存放;当查询日期时,会将日期转换为本地时区后再显示。所以不同时区的人看到的同一时间是 不一样的。

例如:连接MYSQL设置的是serverTimezone=UTC 北京时间的时区为UTC+8

当我们存入2020-10-10 16:13:41 查看数据库得到 2020-10-10 8:13:41

若我们在泰国的服务器(UTC+7)查看,取出来时将会显示 2020-10-10 15:13:41

基于以上特性,该如何进行时间的存储?

我的想法是最好采用无时区类型进行存储。即要么采用datetime 要么使用bigint的整型时间戳(我们目前使用的)。

基于“数据的存储和显示相分离”的设计原则,只需要把Long或者Float表示的时间戳存到BIGINTREAL类型的列中,完全不用管数据库自己提供的DATETIMETIMESTAMP存入数据库,在显示的时候根据用户设置的时区格式化为正确的字符串。

但是有一个问题,分布式应用场景下,服务器处于不同时区,最好存储成某一个特定时区的时间戳整型。如都使用UTC+0的时间下的时间戳。

Reference

如何正确地处理时间

SQL 数据类型