来自:后端进阶
我发现数据库中有些日期居然保存为字符串? 于是我和几个朋友讨论了如何将日期保存到数据库中。 事实上,我一直建议直接用数值来保存时间戳。 我为什么建议这个?
下面,我将从时区的概念向大家解释为什么使用数值来保存时间戳是最好的解决方案。 同时也想分享出来,让更多的开发伙伴关注这些细节。
相信时区对于很多人来说都是熟悉的。 因为地球是圆的,所以从地球不同的角落看太阳会以不同的角度升起。 也就是说,每个人显示时间的方式不同。
例如:
此时,我们东8区的北京时间是10点,那么我们东1区的时间是3点,但他们的时间是相等的:
"2019-06-20 10:00 +8:00" = "2019-06-20 3:00 +1:00"
那么,对于不同时区的人来说,显示的时间是不同的,那么此时如何将时间保存到数据中呢?
我假设您正在使用 new Date() 方法来保存当前日期,但据我所知,数据库类型没有时区信息。 如果此时以某种格式保存日期,则会丢失时区信息。 如果你的服务器更新了地址,从数据库读取的日期数据是错误的!
也许你会说,那我按类型保存就不会丢失时区信息了吧? 确实没有什么缺失,也没有什么问题。 但据我所知,最长存储时间不能超过2037,而且你要考虑到每个数据的类型可能不同。
至于用字符串来存储时间,就更不推荐了。 无论时区如何,比较日期大小也是一个问题。 让我举一个例子:
to_char(SYSDATE, '2019-06-01 00:00:00') > START_TIME
为了比较时间,我需要这样做。 我还需要将系统时间转换为字符串进行比较,并且在转换为字符串进行比较时,数据库也会将其转换为时间进行比较。 您认为是这样吗? 查询条件会好多少?
我们也知道,JDK8中新的时间API中,有丰富的时区转换方法可供使用,但即使你说自己精通各种花哨的用法,你仍然要面对复杂的转换。
因此,我们需要有“绝对时间”的人来帮助我们记录日期,节省我们的转换时间。 这个“绝对时间”就是时间戳。 时间戳的定义是从基准时间开始。 该基地时间为“1970-1-1 00:00:00 +0:00”。 从此时开始,以整数表示,以秒为单位。 随着时间的推移,这个时间整数不断增加。 这样,我只需要一个值就可以完美的代表时间,而且这个值是一个绝对值,也就是说,无论你在地球的任何一个角落,代表时间的时间戳都是一样的,生成的值都是一样的,并且没有时区的概念,所以系统在传输时间的过程中不需要额外的转换。 仅在向用户显示时才会转换为字符串格式的本地时间。
而且很重要的一点是,现有的编程语言都提供了获取时间戳的方法。 这对于我们不同语言的项目交互来说应该不会太方便吧! 所以这里我强烈建议前端和后端使用时间戳来与时间交互。
这个时候,有的同学可能会再尝试一下。 您使用数值来表示时间。 当我查数据库时,凭我的眼力和口头计算,我根本不知道现在是什么时间。 我认为你根本不需要担心这个。 你检查数据库无非就是检查需要的数据。 您只需在 SQL 中的时间戳字段中添加转换函数即可,例如:
from_unixtime(1561053690000)
上面的时间戳是我写这篇文章的时间。
如果你还想继续争论说我只是想看数据库表中的时间,我想如果你想这么做,为什么还需要前端呢? 只需使用数据库的当前端显示即可。
让我总结一下使用数值在数据库中保存时间戳的诸多好处:
1、比较数据库中的日期不太方便。 是小学一年级就能学会的数学题,而且成绩不错; 2、任何系统与数值交互均无障碍; 3.基于绝对时间的数值存储,不存在时区问题; 4、交互过程中,放弃不必要的转换。 一个数字可以统治世界。 用户需要显示它。 前端只需要获取时间戳即可显示正确的本地时间; 5、解决因数据库不同而导致执行时间不一致的问题。 也会出现同样的问题。 比如Mysql的时间函数就会有些不同。 如果你当前的SQL有一定的时间函数,更改数据库后可能会出现错误。