日期的正确存储方式

微信公众号「后端进阶」,专一后端技术分享:Java、Golang、WEB框架、分布式中间件、服务治理等等。
老司机倾囊相授,带你一路进阶,来不及解释了快上车!前端

我发现数据库有些日期竟然用字符串保存?因而跟几个小伙伴讨论了关于数据库的日期应该要怎么保存的问题,其实我一直都建议直接用数值保存时间戳,为何我要这么建议呢?java

如下,我会从时区的概念来跟大家解释一下,为何用数值保存时间戳是最好的方案,同时也为了分享出来,让更多开发小伙伴留意这些细节性的东西。sql

相信时区对于不少人来讲的很熟悉,由于地球是圆的,在地球上不一样角落看到的太阳上升的角度都是不一样的,即每一个人对于时间的显示都是不同的,数据库

举个例子:编程

此时处于东 8 区的咱们北京时间是 10 点,那么处于东 1 区的时间就是 3 点,可是他们的时间是等价的:后端

"2019-06-20 10:00 +8:00" = "2019-06-20 3:00 +1:00"
复制代码

因此说,对于不一样时区的人来讲,显示的时间是不同的,那么此时你是如何将将时间保存到数据中的呢?bash

我姑且假设你用的是 new Date() 方法来保存当时日期,但据我所知道的,数据库的 DateTime 类型是没有时区信息的,若是你此时用 DateTime 格式保存日期,就会丢失时区信息,若是你的服务器更该地址,从数据库读出来的日期数据就是错误的!服务器

可能你会说,那我用 timeStamp 类型保存总不会丢失时区信息了吧?确实没丢失,没毛病。可是据我所知道的,timeStamp 保存的时间最长不能超过 2037 年,并且你要考虑每一个数据的 timeStamp 类型都有可能不同。微信

至于用字符串来存储时间,就更加不推荐了,姑且不从时区来讲,你比较日期大小也是个问题,我举个例子:框架

to_char(SYSDATE, 'yyyy-MM-dd') > START_TIME
复制代码

要比较一个时间大小,我须要这么作,还须要将系统时间转成字符串来给你对比,并且在转换成字符串比较时,数据库内部也会将其转换成时间来比较,你以为这种查询条件会好到哪里去?

咱们也知道在 JDK8 中新的时间 API LocalDateTime 中,有着丰富的时区转换的方法可用,但即使你说你精通 LocalDateTime 的各类花式用法,你也不得不面对繁杂的转换。

因此,咱们须要一个拥有「绝对时间」,来帮助咱们记录日期,帮咱们节省下转换的时间,这个「绝对时间」就是时间戳,时间戳的定义是从一个基准时间开始算起,这个基准时间是「1970-1-1 00:00:00 +0:00」,从这个时间开始,用整数表示,以秒计时,随着时间的流逝这个时间整数不断增长。这样一来,我只须要一个数值,就能够完美地表示时间了,并且这个数值是一个绝对数值,即不管的身处地球的任何角落,这个表示时间的时间戳,都是同样的,生成的数值都是同样的,而且没有时区的概念,因此在系统的中时间的传输中,都不须要进行额外的转换了,只有在显示给用户的时候,才转换为字符串格式的本地时间。

并且很重要的一点就是,在现有的编程语言中,都提供了方法来获取时间戳,这对于咱们不一样语言的项目交互来讲,不要太方便!因此在这里我强烈建议先后端关于时间的交互,都用时间戳来交互。

这时,可能有同窗又来杠一波,你用一个出数值来表示时间,我查数据库时,以个人眼力和口算,根本不知道时间是多少,我以为这个根本不须要担忧啊,你查数据库无非是查看须要的数据而已,你在 sql 里面对时间戳个时间转换函数就行了,好比:

from_unixtime(1561053690000)
复制代码

若是你还要继续杠,说我就是要在数据库表中看到时间,我以为若是你要这样,为何还须要前端,直接拿数据库当前端展现就行了。

我总结一下数据库用数值保存时间戳的诸多好处:

  1. 在数据库中日期比较不要太方便,小学一年级就会的数学题,并且性能好;
  2. 数值对于任何系统交互来讲都不存在障碍;
  3. 基于绝对时间的数值存储,不存在时区问题;
  4. 在交互过程当中,摒弃不必的重重转换,一个数字走天下,用户须要显示,前端只须要拿到时间戳显示正确的本地时间;
  5. 解决了因为各个数据库对于时间实现的不同致使的问题,好比说 Mysql 的时间函数跟 Oracle 会有一些差异,假如你如今的 sql 有时间函数,换了数据库极可能就会出错。

公众号「后端进阶」,专一后端技术分享!
相关文章
相关标签/搜索