比较好奇大家时间都是怎么存数据库的

2022-09-24 15:18:01 +08:00
 humbass

目前我的项目都是直接使用 UTC 时间戳存,但是时间戳是 13 位的,所以除 1000 后,以 int(11) 的方式存

主要是担心数据库有时区问题,造成时间有差异

9255 次点击
所在节点    Node.js
58 条回复
CEBBCAT
2022-09-24 23:30:13 +08:00
@humbass 也许需要把时间戳获取和存储分开思考。说起来我现在才明白你说的除 1k 是什么意思,`Date().getTime()`获取的是毫秒时间戳,除以 1k 就变成了秒时间戳。

关于怎么存,一两句话有点难以讲清楚,我推荐你配合 Google 计算一下 4 字节的 INT 能支持存储什么样的时间范围。
2NUT
2022-09-24 23:34:25 +08:00
@codehz #39 不能细想 坑很多
Jooooooooo
2022-09-24 23:37:56 +08:00
用 int 存 unixtime 基本没啥问题.
shiny
2022-09-25 00:36:16 +08:00
上次的润秒不知道有没有带来坑
colatin
2022-09-25 01:33:21 +08:00
i18n 是老大难问题,是考验是否合格程序员的最低标准。
iseki
2022-09-25 01:40:02 +08:00
@waising with time zone 并不是说数据库会存储输入的 timezone ,这是个比较迷惑的名字,存储的是一个绝对的时间点(实际上存的 UTC ),输入输出时按当前设定时区走
iseki
2022-09-25 01:43:45 +08:00
@CEBBCAT BUGINT 可太真实了
px920906
2022-09-25 01:54:06 +08:00
@codehz 除了最后一点,都不能理解... 求解释或者给些资料的链接,google 不过来😂
leonshaw
2022-09-25 02:17:51 +08:00
@px920906 大概看出来有润秒、公元前后、历法变更、夏令时这几点。时间戳本身就是绝对时空观的产物,是时候建立相对论时间系统了。
codehz
2022-09-25 08:07:38 +08:00
@px920906 时间戳的基本是关于闰秒的问题 https://alexwlchan.net/2019/05/falsehoods-programmers-believe-about-unix-time/
然后 24 点是因为某些地区 dst 在 0 点调整
年份的问题,0 不是一个有效的年份,公元一年的前一年是公元前一年
年份不同格式不同则是因为有种格式是周日历,而这个格式下为了确保同一周是属于同一年,就会对年份数字进行调整,我记得某 java 格式化就会遇到这个问题
月的长度: 1752 年 9 月历法变更
星期的问题也源于此
时区差异:印度在殖民地时期,三个时区分别为 GMT+4:51 GMT+5:21 和 GMT+5:54 (显然是人为故意设置的) https://en.wikipedia.org/wiki/UTC%2B04:51
时区差异变化是因为不同国家的 DST 不同
下一个星期的同一时间这个问题,除了历法变更这种不会再有(希望如此)的事情之外,主要还是闰秒,DST 的影响)
remarrexxar
2022-09-25 09:35:20 +08:00
时间戳能不能用 unsigned int 取决于你的业务是不是只需要处理 1970 以后的时间。如果真有生日之类的存储需求,考虑其他方式存储好了,没必要存到时间戳,只要存到日期好了,不需要精确到时分秒。
twinsdestiny
2022-09-25 11:30:20 +08:00
@CEBBCAT 那你发个 insert 成功给我看看?
mysql> insert into test values(1664076339000);
ERROR 1264 (22003): Out of range value for column 'id' at row 1
CEBBCAT
2022-09-25 15:08:36 +08:00
@twinsdestiny 确实不能存。但不是一回事儿。我理解的楼主的逻辑是 int(11) 只能存 11 位长的数字,即 9,99999,99999 。所以我给楼主说,不是这么理解的。

JS 获取时间戳返回的是以毫秒为单位的时间戳,但是实际上以秒为单位存就可以了。

以现在时间 2022-09-25T14:53:31+08:00 为例,它的 UNIX 时间戳是 1664088811 。通过 https://www.rapidtables.com/convert/number/decimal-to-binary.html 换算得到二进制 (1100011001011111111101011101011)2 ,最高位是第 31 位(从 1 起),而 MySQL 带符号 INT——共 4 字节——可用空间是 31 位,恰好可以存储,而乘 1000 以后,大约多占了 10 个 bit 位,自然溢出。

---
进一步计算得到,31 比特位存储的最大数字是 2147483647 。32 比特位则是 4294967295 。以 UNIX 时间戳记分别是 2038 年和 2106 年。
xuanbg
2022-09-25 19:42:50 +08:00
datetime ,方便查看
julyclyde
2022-09-26 09:36:57 +08:00
@wxf666 更新 tzdata 之后应该都能正确处理
数据库软件的名声比个人的名声重要的多,他们肯定会努力维护的
julyclyde
2022-09-26 09:37:55 +08:00
@reter 假设 1970 年之前是不存在的就可以了
用计算机处理的数据大部分都适用于这种假设
julyclyde
2022-09-26 09:38:48 +08:00
原则是:保存最原始的信息,展现个性化的信息
aboat365
2022-09-26 18:27:41 +08:00
如果你不需要国际化,那就简单很多,MySQL 建议直接使用 datetime 、date 、time 类型,人类可以直接读出。如果时间要国际化,那方案就复杂一些,但无非就是加入时区,成熟的开发语言都有对应的最佳实现。

顺便科普一下
世界时:地球自转时间系统(地球自转速度不均匀)。
协调世界时( UTC ):世界时因地球自转速度不均匀,引入闰秒,协调原子时和世界时而得出的一种时间系统。也是目前大家生活中使用的时间系统。
原子时:原子共振頻率(目前最为精准)。
Unix 时间:在计算机系统中,为了便于计算,规定每天 86400 秒,总秒数从协调世界时( UTC ) 1970 年 1 月 1 日 0 时 0 分 0 秒开始计算。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/882628

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX