什么是 Unix 时间戳(以及开发者为什么要用它)?

Unix 时间戳是一个单一整数:从 1970 年 1 月 1 日 00:00:00 UTC 起经过的秒数。这个时间点被称为 Unix 纪元(Unix epoch),从那时起每一秒都连续计数。

现在此刻的时间戳大概在 1,750,000,000 左右。仅凭这个数字,任何计算机、数据库或 API 都能明确知道你指的是哪个时间点——没有歧义。

为什么是 1970?

Unix 诞生于 20 世纪 60 年代末的贝尔实验室。工程师需要一个固定的时间参考点时,选择了 1970 年 1 月 1 日:新十年的开始,容易理解,而且离当时并不久远,这样在当时存储日期时就不需要为实际用途引入负数。

这是一个务实的选择,而不是基于某种原则。它就这样延续下来。

Unix 时间戳解决了什么问题?

把日期表示成人类可读的字符串,会在每一层都产生歧义:

  • 格式分歧03/04/25 是 3 月 4 日还是 4 月 3 日?是 1925 年还是 2025 年?
  • 时区混乱:“周五下午 3 点”在伦敦和东京代表的是不同的瞬间
  • 地区差异:有的国家写“日-月-年”,有的写“月-日-年”

Unix 时间戳绕开了这些问题。1711929600 无论你在哪、偏好什么格式,都是一个明确的时间点。机器能一致理解;人类再去转换显示即可。

秒、毫秒与微秒

原始的 Unix 时间戳单位是 。但不同系统使用不同的分辨率:

格式单位示例
Unix(POSIX)1711929600
JavaScript Date.now()毫秒1711929600000
Python time.time()秒(浮点)1711929600.123
数据库时间戳常见为微秒1711929600000000

这也是跨系统工作时最常见的 bug 来源之一:把 JavaScript 的时间戳直接传给 Python 或 Go 的函数会变成大 1,000 倍。跨系统边界时务必确认分辨率。

读取与写入 Unix 时间戳

在 JavaScript / TypeScript 中

// 当前时间戳(秒)
Math.floor(Date.now() / 1000)

// 当前时间戳(毫秒)
Date.now()

// 时间戳(秒)转 Date 对象
new Date(timestamp * 1000)

// Date 转时间戳(秒)
Math.floor(new Date('2024-04-01').getTime() / 1000)

在 Python 中

import time, datetime

# 当前时间戳(浮点)
time.time()

# 转为 datetime
datetime.datetime.fromtimestamp(1711929600)

# datetime 转时间戳
datetime.datetime(2024, 4, 1).timestamp()

在 SQL(PostgreSQL)中

-- 当前时间戳
EXTRACT(EPOCH FROM NOW())::int

-- 转为 timestamp
TO_TIMESTAMP(1711929600)

时区不会影响时间戳本身

这一点很重要,也经常被误解。

Unix 时间戳始终表示一个 UTC 时刻。你在 显示 时把它转换为本地时区;在 存储 时存 UTC 值。时间戳本身与时区无关。

这意味着:

  • 不同时区的两位用户都存储“现在”,得到的时间戳相同
  • 显示时,各自会看到本地时间
  • 数据库层不需要做偏移调整——只在展示层处理

2038 年问题

如果 Unix 时间戳以 32 位有符号整数存储,最多只能计数到 2,147,483,647 秒——对应 2038 年 1 月 19 日 03:14:07 UTC。超过这一刻,32 位计数会回绕成很大的负数。

仍使用 32 位整数存储时间戳的系统会在那天出问题。大多数现代系统用 64 位整数,把溢出推到约 2920 亿年之后——对现实用途而言可以忽略。

如果你在处理嵌入式系统、遗留数据库或旧的 C 代码,值得检查时间戳的存储方式。

什么时候该用 Unix 时间戳?

适合使用 Unix 时间戳的场景:

  • 在数据库中存储日期,并希望用一个简单、可排序的整数表示
  • 在系统或 API 之间传递日期
  • 按时间顺序比较或排序事件
  • 计算持续时间(直接相减两个时间戳)
  • 缓存或过期逻辑(expires_at = now + 3600

适合使用格式化日期字符串的场景:

  • 向用户展示日期
  • 记录需要人类可读的日志
  • 在表格或 CSV 导出中处理

快速换算

内容秒数
1 分钟60
1 小时3,600
1 天86,400
1 周604,800
30 天2,592,000
1 年(约)31,536,000

Unix 时间戳转换器 可以把任意时间戳转换成可读日期,或把日期即时转换成 Unix 时间戳。