Unix时间戳为何从1970年开始?

strongerHuang 2026-06-16 08:00

来源 | 最后一个bug


做嵌入式软件开发的朋友,应该都听说过Unix时间戳选择1970年作为起始点,那问题了来了,为什么Unix时间戳为什么要从1970年开始算呀?从2000年开始不行吗?

1

Unix时间戳

Unix时间戳说白了就是一个计数器:从1970年1月1日 00:00:00 UTC开始,每过一秒就加一。你在代码里调用 time() 拿到的那个整数,就是这个计数器的当前值。

/******************************************
 * Fuction: 获取Unix时间戳
 * Author : (最后一个bug)
 ******************************************/

#include <stdio.h>
#include <time.h>

int main(void)
{
    time_t now = time(NULL);
    printf("当前时间戳: %ld\n", (long)now);
    return 0;
}

运行一下:

当前时间戳: 1781184000

这个数字看着挺大,但理解起来极其简单——就是个秒计数器。任何两个时间点的差值,两个整数一减就出来了,不需要考虑闰年、月份天数、时区这些乱七八糟的东西。这也非常符合Unix 时间戳最核心的设计哲学:用最简单的数据结构搞定时间表达问题

2

为什么是1970?

这应该是大部分人最开始了解Unix时间的疑问吧,为何是距离1970年的秒数,不是其他的比如2000年呢?

我大致了解了下背景,感觉挺有意思的:

Unix 操作系统是 1969 年夏天 Ken Thompson 在贝尔实验室的一台 DEC PDP-7 上开始写的。当时他老婆带着刚出生的儿子去加州探亲了,他一个人在家"闭关"了一个月,写下了 Unix 的文件系统、Shell、编辑器和汇编器——时间处理自然也是他一手搞的,简直不要太强~

但 1970 年这个日期,不是一开始就定好的

早期的 Unix(大约 1971 年的第一版),epoch 实际上是 1971 年 1 月 1 日,计数器单位用的还是 1/60 秒;但是32 位无符号整数,用 1/60 秒做单位,只能覆盖大概两年半,这显然不够用;后来他们把单位改成了整秒,范围一下扩展到了 136 年左右,算是能用了。

但 epoch 本身还在不停地变,因为计数器老是溢出,所以大家一直在改时间的起点,最后开发者们选了一个短期内不会溢出的日期,1970 年看起来也不错,就用它了~

到了 1973 年左右(大约 Unix 第四版),epoch 被最终锁死在 1970 年 1 月 1 日 00:00:00 UTC,一直用到了现在。

所以这个 1970 年不是什么"计算机历史的里程碑",它就是一群工程师被不停溢出的计数器搞烦了,随手选了一个整数年。

3

设计思想

Ken Thompson 和 Dennis Ritchie 这一代贝尔实验室的程序员,骨子里信奉一种设计理念—被称为 "Worse is Better"。即简单的东西比"完美"的东西更有生命力。

Unix 时间戳完美体现了这个理念:

一个整数,搞定一切。

时间差?整数减法。时间比较?整数比大小。存储成本?4 个字节。跨平台传输?不需要任何格式解析。

比如如果时间被设计成 "2026-06-12 15:30:00" 这样的字符串,那每次算时间差都得先解析字符串、处理闰年、处理月份天数差异……写个时间比较函数都能写出上百行代码来。

而 Unix 的做法呢?t2 - t1,一行完事。nice~

还有一个同样精妙的设计点:分离存储和展示

Unix时间戳为何从1970年开始?图1

内核只管维护一个单调递增的秒计数器,至于这个秒数怎么变成"2026年6月12日星期五下午3点45分",那是 gmtime()localtime()strftime() 这些库函数该操心的事。每一层只负责自己该管的,不越界。

还有一点容易被忽略——Unix 时间戳没有闰秒

国际原子时和天文观测时间之间的微小偏移,会让 UTC 时不时需要插入或删除一秒(闰秒)。但 Unix 时间戳假装闰秒不存在——它把每一天都当作精确的 86400 秒来处理。遇到真正的闰秒时刻,系统通过 NTP 做微调来慢慢消化掉这个偏移。

这个设计看起来"不够精确",但正是这种"不精确"让 Unix 时间戳变得非常可预测、非常好做算术——你不用维护一张"闰秒发生表"来判断某个时间点到底存不存在。

4

2038年问题

Unix 时间戳最初用的是有符号 32 位整数int32_t),能表示的最大正数是 2,147,483,647 秒。
从 1970 年 1 月 1 日开始数,32位time_t的尽头: 2038-01-19 03:14:07 UTC 
再溢出一秒后: 1901-12-13 20:45:52 UTC。

溢出之后,时间"倒流"回了 1901 年——这就是著名的 "2038 年问题"。本质上跟千年虫一样,都是固定位宽的计数器溢出。

Unix时间戳为何从1970年开始?图2

大家在搞嵌入式软件开发,特别是单片机开发中这个问题尤其值得留意。bug菌见过不少还在跑的工业设备软件不少还是 32 位的 time_t,这些大部分用的是比较早期的组件或者库,或者是开发者没有考虑到此问题。这些设备如果设计寿命超过 15 年,到 2038 年确实有可能踩到这个坑。

现代系统已经把 time_t 升级到了 64 位有符号整数,最大值大约是 2920 亿年。宇宙目前的年龄大概是 138 亿年——也就是说 64 位的 Unix 时间戳足够覆盖宇宙年龄的 20 多倍,那就不用再担心了~


------------ END ------------

声明:内容取材于网络,仅代表作者观点,如有内容违规问题,请联系处理。 
more
AT&S宣布:投资20亿扩产
微软投资芯片公司,围攻英伟达
总投资23亿元,一MLED/AMOLED项目完成备案
2026年中国MLCC产业链图谱及投资布局分析
“跨国汽车企业在华高质量发展”联合项目组调研科思创(上海)投资有限公司
2026年中国DRAM产业链图谱及投资布局分析
2026年中国储能电芯产业链图谱及投资布局分析
总投资120亿!合肥高端光掩膜版项目封顶
“跨国汽车企业在华高质量发展”联合项目组调研欧摩威投资(中国)有限公司
曝林俊旸获腾讯投资:首轮估值135亿,新一轮融资已开启
Copyright © 2025 成都区角科技有限公司
蜀ICP备2025143415号-1
  
川公网安备51015602001305号