前言
nestjs
开发过程中,一些人可能会对时间有些疑惑,但是一旦对时间相关了解后,发现这都不是什么问题,甚至可以通过理论避免现实中的碰壁
正常时间分为两个时间 服务器时间
+ 数据库时间
,但一般我们写入数据库的时间也都是根据一台或多台
服务器时间来的,那么怎么统一时间,方便后续使用没问题呢
目前主流的解决方案是,时间存储均设置为 0 时区,这样我们的时间就可以完全独立不依赖服务器时间了,甚至不用运维调整服务器时区
下面简单讲讲时区,然后讲我们怎么做更好一些
时区
时区一共划分为 24 个区间,分别为东12区,西12区,分别位于0时区(本初子午线所在处)两侧
ps
:规定0时区也是为了方便参考一天的前后(不然东12区和西12区哪个在前那个在后怎么分辨是是吧,看着前后差了一个时区,实际上时间计算却差了23个小时,另外要是都认为自己早,那么没办法统一时间规范了😂)
说到时间就一定要提出时区,这是我们上学就学过的,我们中国使用时间处于东八区
,比零时区
(本初子午线)时间要快 8 个小时
,意味着我们的时间实际比零时区要大出 8 个小时(+8)
东边时间快,是原因地球是自西向东自转,东边的自然先见到太阳,新的一天就提前开始了(所以规定一个参考点很重要),举个例子:每个时区以春季一天的时间规则都是 6点日出、18点日落
,我们的时间和 0 时区的时间相比,即:当我们 东八区 6点看到日出时,0时区 还是前一天的 10点,当 0时区 时间到今天 6点看到日出时,我们东八区已经到达下午14点了
说到这里相信大家明白差不多了,东边的显示时间要比0时区大,西边的显示时间要比0时区小
(即:以0时区为基础时间时,东区显示要加时间,西区显示要减时间),时间上的加减相信就明白了
解决方案
目前储存时间按照主流肯定是要以 0时区时间格式保存的,这样我们的时间就可以完全独立不依赖服务器时间了(实际使用仍然可以按照需要依赖,毕竟有些就是一套代码不同服务器在不同地方设置不同时区显示的就可以不一样,看自己情况,但也只是给客户端显示的时候用的)
以 nestjs
为例,我们使用的 CreateDateColumn
等创建的时间戳默认也是存放的 0 时区的(最后一个 Z 就表示的 0 时区 zero),保存到数据库中是这样的 2024-01-01T00:00:00Z
,如果显示成后面那样那就是东八区了2024-01-01T00:00:00+08:00
(我没见过这么保存的,这是 dayjs 默认 format 打印的结果,用插件就不一样了)
扩展一下
: 默认 Date对象
可以理解为生成的就是 0 时区的时间,这种对象可以理解为不存在转化对应时区计算,因为只是需要格式化显示的时候才需要用到时区
ps
:我们使用的 CreateDateColumn等
创建的 Date
类型的参数返回时转化字符串就是上面的形式,上面的形式也是 dayjs
默认支持的格式,可以直接使用 dayjs
库来进行初始化和计算
我们保存的都是时间戳,可以直接使用 dayjs
或者 moment
直接参与计算即可
判断过期
js
//举个判断是否过去
//我们给定一个订单创建时间 2024-01-01T00:00:00Z,默认30分钟后到期,我们要用到当前时间做判
entity.create_time = new Date() //我们创建时这样,使用CreateDateColumn逻辑一样
取出时也是 Date 类型,只不过是创建时的类型,实际上我们判断时可以直接使用new Date,然后两个分别使用 getTime一减少就能判断,跟时区没有关系
const now = new Date
//时间间隔 ms,判断一下即可
const timeinterval = now.getTime() - entity.create_time.getTime()
timeInterval > 30 * 60 * 1000 //过期了
时间格式化
有时候需要返回给前端格式化后的时间类型,不然返回的都是零时区的样式,我们直接使用 dayjs、moment
直接格式化一下即可,这里以 dayjs 为例,moment
类似
js
//dayjs需要这样导入
const dayjs = require('dayjs')
//用到utc时导入
const utc = require('dayjs/plugin/utc')
dayjs.extend(utc)
//要想使用格式化样式导入这个
const customParseFormat = require('dayjs/plugin/customParseFormat')
dayjs.extend(customParseFormat)
//将我们的时间对象转化为 dayjs 然后format 即可,这个默认返回的是服务器设置时区
dayjs(new Date()).format()
//就想格式化成零时区怎么样,这样设置一下要格式化成utc返回就行了,实际计算不影响的
dayjs.utc(new Date()).format()
//格式化成固定样式
dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss')
//要转化外部传递的字符串时也可以,下面是分别把字符串当做服务器时区、零时区翻译的
//要是想让接收的字符串是东八区,服务器时区不是东八区,可以直接按照0时区算,然后时间加 8 h 即可
dayjs('2012-10-10 10:10:10')
dayjs.utc('2012-10-10 10:10:10')
dayjs.utc('2012-10-10 10:10:10').add(8, 'h') //严格按照东八区计算,不看服务区时区
ps
:如果有些时间需要前端、客户端、移动端传递时,让他们转化为 0 时区传递就完事了,或者这边以 0 时区格式化使用即可,那边传递的要是单纯字符串,后端的可以直接按照统一化的时区来使用即可(这边一般前后端都是东八区吧)