一个时间字段引发的血案

开发 架构
之前因为存储时间的原因导致了一些Bug,然后发现自己对这块的知识也比较薄弱,所以系统的跟大家一起来学习学习。

[[437718]]

本文转载自微信公众号「六脉神剑的程序人生」,作者六脉神剑小六六 。转载本文请联系六脉神剑的程序人生公众号。

hi ,大家好,我是三天打鱼,两天晒网的小六六

前言

文本已收录至我的GitHub仓库,欢迎Star:https://github.com/bin392328206/six-finger

种一棵树最好的时间是十年前,其次是现在

之前因为存储时间的原因导致了一些Bug,然后发现自己对这块的知识也比较薄弱,所以系统的跟大家一起来学习学习。

Bug回顾

就是比如订单哈,我们一般会有这么几个时间,第一个是下单时间,第二个是订单更新时间,第三个是我方的完成时间,第四个是渠道的完成时间,但是当初设计的时候呢?我们的下单时间用了字符串去表示,这样就有一个问题,你用字符串表示,说明你当时存储的时候就已经默认了时区了,所以当前端去用这个时间的时候,就会和用户的本地时间去做比较,然后我这边又有做的是一些海外项目,那么就有这样一种可能就是你付款的时间比你订单的下单时间还早,因为渠道的完成时间可能用的是他们自己渠道的时区,而我们的服务器默认用的东八区的时区的字符串。

UTC时间

UTC时间又称协调世界时 协调世界时,又称世界统一时间、世界标准时间、国际协调时间。由于英文(CUT)和法文(TUC)的缩写不同,作为妥协,简称UTC。协调世界时是以原子时秒长为基础,在时刻上尽量接近于世界时的一种时间计量系统。中国大陆采用ISO 8601-1988的《数据元和交换格式信息交换日期和时间表示法》(GB/T 7408-1994)称之为国际协调时间,代替原来的GB/T 7408-1994;中国台湾采用CNS 7648的《资料元及交换格式–资讯交换–日期及时间的表示法》,称之为世界统一时间。

时区

地球的自转运动产生了太阳东升西落现象,日出为昼、日落为夜。世界各地以昼夜交替现象为基础确定日期变化和时间推移。

然而各地位置不同时间标准不一造成了时间上的混乱。为了克服这种局面,1884年,各国在华盛顿召开国际经度会议,与会国家创立了通用的标准时间制度——以180°经线为理论上的日界线,经度每隔15°,地方时相差1小时。

虽然我国横跨多个时区,但只采用了一个标准时区,这也是长期实践得来的结果。中美时区制度不同的根本原因在于人口分布的区别。受制于地形和经济发展水平问题,美国的大城市和人口聚集区在中部和东西海岸;而中国的人口分布相对集中,绝大多数在“黑河腾冲线”以东。

现在我们谈到的“北京时间”,并不是真正意义上的北京时间,而是以陕西省渭南市蒲城县授时中心发出的东八区时间(东经120度)作为统一称呼的“北京时间”。

时间戳

“时间戳是指格林威治时间自1970年1月1日(00:00:00GMT)至当前时间的总秒数。通俗的讲,时间戳是一份能够表示一份数据在一个特定时间点已经存在的完整的可验证的数据。”

在计算机中,「时间戳」一般是指 Unix 时间戳,即自从 Unix 纪元(格林威治时间 1970 年 1 月 1 日 00:00:00)到当前时间的秒数。

时间戳是可以转换成任何时区的时间

数据库如何存储时间

字符串存储日期

想必大家在刚开始接触开发的时候,这种做法是可取的,简单,容易上手,可识别性比较高,一看就懂

  • 字符串占用的空间更大
  • 字符串存储的日期比较效率比较低(逐个字符进行比对),无法用用日期相关的API进行计算比较。
  • 时区问题 你存字符串是你没办法存储时区的,如果是海外项目会有很多的问题,所以对于一些项目来说存它是非常不适合的

Datetime和Timestamp

Datetime 和 Timestamp 是 MySQL 提供的两种比较相似的保存时间的数据类型。他们两者究竟该如何选择呢?

首选TimeStamp。

datetime 更像日历上面的时间和你手表的时间的结合,就是指具体某个时间。

timestamp 更适合来记录时间,比如我在东八区时间现在是 2016-08-02 10:35:52, 你在日本(东九区此时时间为 2016-08-02 11:35:52),我和你在聊天,数据库记录了时间,取出来之后,对于我来说时间是 2016-08-02 10:35:52,对于日本的你来说就是 2016-08-02 11:35:52。所以就不用考虑时区的计算了。

时间范围是 timestamp 硬伤(1970-2038),当然 datetime (1000-9999)也记录不了刘备什么时候出生(161 年)。

DateTime类型没有时区信息的(时区无关) DateTime 类型保存的时间都是当前会话所设置的时区对应的时间。这样就会有什么问题呢?当你的时区更换之后,比如你的服务器更换地址或者更换客户端连接时区设置的话,就会导致你从数据库中读出的时间错误。不要小看这个问题,很多系统就是因为这个问题闹出了很多笑话。

数值型时间戳是更好的选择吗

很多时候,我们也会使用 int 或者 bigint 类型的数值也就是时间戳来表示时间。

这种存储方式的具有 Timestamp 类型的所具有一些优点,并且使用它的进行日期排序以及对比等操作的效率会更高,跨系统也很方便,毕竟只是存放的数值。缺点也很明显,就是数据的可读性太差了,你无法直观的看到具体时间。

总结

推荐 Timestamp,原因是数值表示时间不够直观

每种方式都有各自的优势,根据实际场景才是王道。下面再对这三种方式做一个简单的对比,以供大家实际开发中选择正确的存放时间的数据类型:

 

好了今天的分享就到这了,我是小六六,三天打鱼,两天晒网。

 

责任编辑:武晓燕 来源: 六脉神剑的程序人生
相关推荐

2021-07-27 07:12:11

Getter接口Setter

2018-11-22 15:50:27

MySQL数据库双引号

2021-01-25 08:08:22

APP机器人KOB

2021-02-01 10:42:47

MySQL双引号数据库

2017-05-22 08:35:07

MySQL双引号错位

2017-08-25 16:38:05

表达式正则血案

2010-08-09 09:46:40

2019-09-09 08:30:57

MYSQL代码数据库

2017-03-20 19:40:29

AndroidSwipeRefres下拉刷新

2012-02-13 09:42:41

备份服务器数据中心

2021-10-06 09:30:26

Below资源监控器系统运维

2021-01-11 05:30:04

Boot 单机片

2011-02-28 09:31:30

HashtableHashMap

2019-06-12 08:23:21

数据库时间序列开源

2015-02-04 14:36:07

格式串漏洞Ghost漏洞安全漏洞

2010-09-09 10:42:30

SQL函数时间

2011-11-25 13:04:43

空格usr

2013-12-05 10:50:13

2020-01-06 09:43:14

赔偿TSB迁移

2023-01-11 08:41:47

微服务循环依赖
点赞
收藏

51CTO技术栈公众号