时间戳的一些应用

536 阅读5分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第14天,点击查看活动详情

时区的概念

时区是怎么形成的

由于地球是圆的,在同一时刻,太阳相对于不同地方的人来说,角度和位置是不一样的。

这就导致了,有的地方是白天,有的地方是凌晨,有的地方是正午,有的地方是下午。

两个共同需求:

  • 都是24小时制, 不同地方的人都想把一天分成24个小时,每个小时60分钟,每分钟60秒,等等。

  • 都想根据太阳东升西落的时候,划分自己的凌晨,中午,下午,夜晚。

所以,来自两个不同地方的人,A可能是中午十二点,B可能是下午一点。

这两个人如果要沟通关于现在到底是几点的话,就必须带一个额外的信息,那就是:

  • 你说的时间是什么地方的时间

慢慢的,人们就有了时区的概念。

时区的特点

看看时区这两个字,其中的字不仅仅表示时间,也表示小时(Hour)

也就是说,两个时区的差别,是以小时来区分的。

也就是说不可能出现下面的情况:

  • A说:我这里是 中午12:31
  • B说:我这里是 下午1:55

你看,B说出的时间和A说出的时间相差的不是整数小时,这明显不可能出现。

时区的麻烦之处

就是在传达时间的时候,需要带上一个时区这个信息。经常这个信息被忽略,导致时间不准。

时间戳的概念

不管什么时区,几点,不考虑什么相对论相应的话,这个世界的时间是一致的。

所以要有一种绝对的,大家用起来都相同的东西来表示时间。

这就是UNIX时间戳

从 (UTC)1970.1.1 零点零分零秒。。。。。。 到现在所经历的时间,单位可以是秒,毫秒,纳秒,这个无所谓。

比如说,我们这里用秒级时间戳来表达

  • 北京时间 2022-4-14 凌晨零点零分零秒就是 1649865600
  • 北京时间 2022-4-14 凌晨零点零分一秒就是 1649865601
  • 北京时间 2022-4-14 凌晨零点零分二秒就是 1649865602。 这样,过一秒,就加一。

那么过一小时,就加 3600, 即 1649865600 + 3600 = 1649869200

那么 1649869200 这个时间戳,就是 2022-4-14 凌晨一点零分零秒

时间戳的好处

一致性

不管你在哪,用的什么系统,时间戳都是一样的。

简单存储

由于时间戳就是一个整数,存储起来比较方便,也可以比较大小,何乐而不为

关于时间的推算

比如说,当前时间戳是 tt ,

  • 那么一小时后就是 t+3600t + 3600
  • 一周后就是 7天后: t+3600247t + 3600 * 24 * 7

简单获取整点时间戳

比如说北京时间2022-04-14 12:12:12 的时间戳是 1649909532
那么如何得出2022-04-14 12:00:00的时间戳呢?

如果用整数乘除法的话:

整点时间戳 = (现在时间戳 / 3600) * 3600

做个验证:

  • 1649909532 / 3600 = 458308
  • 458308 * 3600 = 1649908800 恰好就是 2022-04-14 12:00:00的时间戳。

根据这个算法,整五分钟的时间戳:

整五分钟时间戳 = (现在时间戳 / 300) * 300

整十分钟时间戳 = (现在时间戳 / 600) * 600

以此类推。

获取今日凌晨零点时间戳

比如说,现在已经获取了当前时间戳是 1649909532 ->北京时间 2022-04-14 12:12:12

那么如何得知当前时间戳的凌晨零点时间戳呢, 也就是北京时间 2022-04-14 0:0:0的时间戳是多少?

根据上面的算法,一天就是24小时,就是86400秒,那么简单:

凌晨时间戳 = (当前时间戳 / 86400) * 86400

我们来验证一下:

  • 1649909532 / 86400 = 19096
  • 19096 * 86400 = 1649894400 -> 北京时间 2022-04-14 08:00:00

从这个结果可以看出,这样算不行。

为啥?

因为今日凌晨这个概念里包含了时区的划分了。不同的时区,关于今天描述是不同的时间。

这里给一种取巧型算法:

我们随便找一天时间的凌晨零点时间戳,比如说:北京时间 2011-1-1 0:0:0的时间戳是:1293811200

我们知道,一天就是 86400 秒,也就是说,2011-1-1 0:0:0 之后的每一天的凌晨零点时间戳都是:

1293811200 + N * 86400, 其中 N 是正整数。

假设当前时间戳是tt, 那么有:

t=1293811200+N86400+x      (1)t = 1293811200 + N * 86400 + x \ \ \ \ \ \ (1 式)

这个xx就是今天凌晨到现在为止的秒数,且 x<86400x < 86400

t凌晨=tx=1293811200+N86400t_{凌晨} = t - x = 1293811200 + N * 86400

我们现在的目的就是要知道 N * 86400。

根据(1)(1 式):

t1293811200=N86400+x      (2)t - 1293811200= N * 86400 + x \ \ \ \ \ \ (2 式)

看一下(2)(2 式)

右边是一个 86400 的整数倍 和一个不到 86400的数字相加,根据整数乘除法:

N86400=t12938112008640086400       (GOOD!)N * 86400 = \frac{t - 1293811200}{86400} * 86400\ \ \ \ \ \ \ (GOOD!)

得到了已经:

t凌晨=tx=1293811200+N86400=1293811200+t12938112008640086400t_{凌晨} = t - x = 1293811200 + N * 86400 = 1293811200 + \frac{t - 1293811200}{86400} * 86400

验证一下:

  • 当前时间戳是 1649909532 ->北京时间 2022-04-14 12:12:12
  • 1293811200+1649909532129381120086400864001293811200 + \frac{1649909532 - 1293811200}{86400} * 86400
  • = 1293811200+4121864001293811200 + 4121 * 86400
  • = 1293811200+3560544001293811200 + 356054400
  • = 16498656001649865600 --> 恰好就是 北京时间 2022-04-14 0:0:0, 成功。