Unix Timestamp 是什么?一次搞懂时间戳的原理与应用

当你在数据库里看到 1711699200 这串数字,或是在 API 响应中见到 "created_at": 1711699200,你看到的就是 Unix timestamp(又称 Unix 时间戳)。它是计算机世界中最通用的时间表示法,几乎所有编程语言、操作系统、数据库都支持它。本文将从头说清楚 Unix timestamp 是什么、为什么要用它,以及你在开发中会遇到的各种场景。

1. Unix Timestamp 的定义

Unix timestamp 是一个整数,代表从 Unix Epoch(纪元)——即 1970 年 1 月 1 日 00:00:00 UTC——到某个特定时刻之间所经过的秒数

例如:

人类可读时间(UTC)Unix Timestamp
1970-01-01 00:00:000
2000-01-01 00:00:00946684800
2024-03-29 00:00:001711670400
2038-01-19 03:14:072147483647(32 位上限)

需要注意的是:Unix timestamp 以 UTC(协调世界时) 为基准,本身不含时区信息。同一个 timestamp 在北京(UTC+8)、伦敦(UTC+0)、纽约(UTC-5)代表的是同一个绝对时刻,只是显示出来的本地时间不同。

2. 为什么从 1970 年开始?

这个"0 点"并没有什么天文或历法上的特别意义,纯粹是历史因素。Unix 操作系统大约在 1969 到 1970 年间开发,设计者需要选一个"时间原点",就选了 1970 年 1 月 1 日 00:00:00 UTC。此后所有与 Unix 兼容的系统都沿用了这个惯例,最终成为事实标准(de facto standard)。

你也许见过其他时间原点:Windows NT Epoch 是 1601 年 1 月 1 日,NTP 时间是 1900 年 1 月 1 日,Apple Core Data 是 2001 年 1 月 1 日。彼此之间换算时需要特别注意。

3. Unix Timestamp 的核心优势

Unix timestamp 之所以在工程领域广泛使用,原因在于几个无可取代的特性:

  • 时区无关:timestamp 是绝对秒数,不依附任何时区。跨国系统只要传递 timestamp,接收端再根据本地时区转换显示,不会产生歧义。
  • 纯整数、易比较:要判断事件 A 是否在事件 B 之前,只需比较两个整数大小,不需要解析日期字符串,更不需要考虑闰年、月份天数等历法规则。
  • 易于存储与传输:一个 64 位整数,几乎没有空间开销。数据库字段、JSON 字段、HTTP Header 都能轻松放进去。
  • 计算简单:"这篇文章是 3 天前发布的吗?"只需拿现在的 timestamp 减去文章的 timestamp,再除以 86400(一天的秒数)即可判断。

4. 毫秒级 Timestamp

随着应用对精度要求提高,许多现代系统采用毫秒(millisecond)timestamp——即 Unix Epoch 以来的毫秒数,是秒数 × 1000。例如 JavaScript 的 Date.now() 返回的就是毫秒 timestamp。

这也是常见的混淆来源。1711670400(10 位数)是秒,1711670400000(13 位数)是毫秒;把毫秒 timestamp 当秒数处理,会得到公元 5 万年左右的输出。判断方式:10 位数 = 秒,13 位数 = 毫秒(在 2001 至 2286 年间适用)。

5. 各语言获取 Unix Timestamp 的方式

# PHP
time()                          // 秒
round(microtime(true) * 1000)  // 毫秒

# Python
import time
int(time.time())               // 秒
int(time.time() * 1000)        // 毫秒

# JavaScript
Math.floor(Date.now() / 1000)  // 秒
Date.now()                     // 毫秒

# Java
System.currentTimeMillis() / 1000  // 秒
System.currentTimeMillis()         // 毫秒

# Go
time.Now().Unix()              // 秒
time.Now().UnixMilli()         // 毫秒

# Bash / Shell
date +%s                       // 秒

6. 如何将 Unix Timestamp 转换为人类可读格式?

各语言都提供了标准函数,以 PHP 为例:

// timestamp → 日期字符串
$ts = 1711670400;
echo date('Y-m-d H:i:s', $ts);        // 2024-03-29 00:00:00(本机时区)
echo gmdate('Y-m-d H:i:s', $ts);      // 2024-03-29 00:00:00(强制 UTC)

// 日期字符串 → timestamp
$ts = strtotime('2024-03-29 00:00:00 UTC'); // 1711670400

7. 2038 年问题(Y2K38)

当 Unix timestamp 以 32 位有符号整数(signed int32) 存储时,最大值是 2147483647,对应到 2038 年 1 月 19 日 03:14:07 UTC。超过这个时刻,32 位整数溢出后会变成负数,导致系统误判时间回到 1901 年——这就是俗称的"2038 年问题(Y2038 problem)"。

现代操作系统与大多数 64 位编程语言已将 timestamp 改用 64 位整数,可表示到约西元 2920 亿年之后。但若维护的系统仍使用旧版 32 位 C 函数库或数据库的 INT(11) 字段,就需要评估升级计划。

开发注意
数据库的 INT UNSIGNED 可以存到 2106 年,BIGINT 则几乎没有上限。建议新系统一律使用 BIGINT 或数据库原生的 DATETIME/TIMESTAMP 类型(通常内部已采用 64 位)。

8. 常见应用场景

  • 数据库记录时间created_atupdated_atdeleted_at 字段经常以 timestamp 存放,节省空间且查询效率高。
  • API 响应:REST API 传递时间时,timestamp 比 ISO 8601 字符串更容易做数值比较与排序。
  • JWT 与认证 token:JSON Web Token 的 exp(过期时间)与 iat(签发时间)就是 Unix timestamp。
  • 日志系统:大量日志以 timestamp 记录事件,方便依时间范围过滤。
  • 前端相对时间显示:"3 分钟前"、"昨天"这类相对时间,通常由前端拿 Date.now() 减去后端传来的 timestamp 计算得出。

结语

Unix timestamp 看起来只是一串数字,却是整个现代软件生态赖以运作的时间语言。理解它的原理——从 1970 年起算的秒数、无时区偏移、纯整数操作——能帮助你在开发中读懂 API 文档、调试时间相关问题,以及设计出更健壮的系统架构。下次再看到 10 位数字,你就知道那是秒,13 位数字是毫秒,而且两者背后指的都是 Unix Epoch:1970 年 1 月 1 日的零时零分零秒。