你有没有看过 API 返回这样的字段:"created_at": 1745913600?这个看似神秘的整数,其实是 UNIX 时间戳(Unix Timestamp)——一种在程序世界中传递时间的标准格式。理解它为什么存在、如何正确使用,是每位工程师都需要掌握的基础技能。
一、什么是 UNIX 时间戳?为什么程序要用它?
UNIX 时间戳是指「从 1970 年 1 月 1 日 00:00:00 UTC(称为 Unix Epoch)到某个时刻,所经过的秒数」。例如,1745913600 代表 2026 年 4 月 29 日 00:00:00 UTC。
程序选择用这个整数而非人类可读的字符串,主要有三个理由:
- 时区中立:
1745913600在全球所有系统上代表同一个绝对时刻,不存在「台北时间」还是「纽约时间」的歧义 - 易于计算:要计算两个时间点相差几秒、排序事件发生顺序,直接比较整数即可
- 格式统一:不同语言、不同数据库系统都能毫无歧义地解读同一个整数
立即转换时间戳:使用 Unix 时间戳转换工具,可以在时间戳与人类可读时间之间快速互换,支持秒级与毫秒级格式,并显示各时区对应时间。
二、秒 vs 毫秒:最常见的混淆陷阱
UNIX 时间戳本身定义为「秒数」,但现代系统(特别是 JavaScript 和许多 API)常用毫秒(milliseconds),在数字后面多加了三位数:
| 格式 | 示例值 | 说明 |
|---|---|---|
| 秒(seconds) | 1745913600 |
10 位数,UNIX 标准,C/Python/PHP 常用 |
| 毫秒(milliseconds) | 1745913600000 |
13 位数,JavaScript Date.now() 返回此格式 |
| 微秒(microseconds) | 1745913600000000 |
16 位数,部分数据库与高精度系统使用 |
识别方式:看数字的位数。10 位数 → 秒;13 位数 → 毫秒。如果你收到一个 13 位的时间戳,却用秒的方式解读,换算出来的时间会是 56000 年后——这是初学者最常踩的坑之一。
三、API 设计:时间字段的最佳实践
| 格式 | 示例 | 优点 | 缺点 |
|---|---|---|---|
| UNIX 时间戳(秒) | 1745913600 |
计算快、无时区歧义、数据量小 | 人类无法直接阅读 |
| ISO 8601 字符串 | 2026-04-29T00:00:00Z |
人类可读、含时区信息(Z 表示 UTC) | 字符串解析有语言差异 |
业界建议
- 内部系统间的 API:优先使用 UNIX 时间戳(整数),避免时区解读错误
- 对外公开 API:使用 ISO 8601 格式,方便开发者直接阅读
- 统一使用 UTC:无论选哪种格式,存储与传递都应使用 UTC,在前端才根据用户时区显示
API 返回了带时区的时间字符串?使用 世界时钟工具,可以快速查询各时区的当前时间,帮助你验证时区换算是否正确。
四、数据库存储:INT、DATETIME 还是 TIMESTAMP?
| 类型 | 示例值 | 适用场景 | 注意事项 |
|---|---|---|---|
BIGINT |
1745913600 |
高性能查询、跨数据库移植 | 推荐用 BIGINT 避免 2038 年问题 |
DATETIME |
2026-04-29 00:00:00 |
需要人类可读、不依赖时区设置 | MySQL DATETIME 不存储时区信息,需应用层统一 |
TIMESTAMP |
2026-04-29 00:00:00 |
MySQL 自动转换时区,适合多时区系统 | 范围限制到 2038 年;MySQL 8 已部分改善 |
2038 年问题:32 位有符号整数的最大值对应 2038 年 1 月 19 日 03:14:07 UTC,超过后会溢出归零。解决方法是改用 64 位整数(BIGINT)存储。
五、跨语言时间戳操作速查
JavaScript
// 获取当前时间戳(毫秒) const ms = Date.now(); // 1745913600000 // 转为秒 const sec = Math.floor(Date.now() / 1000); // 时间戳转 Date 对象 const date = new Date(1745913600 * 1000); // Date 对象转时间戳(秒) const ts = Math.floor(date.getTime() / 1000);
Python
import time, datetime, timezone ts = time.time() # 当前秒数(浮点) dt = datetime.datetime.fromtimestamp(1745913600, tz=timezone.utc) ts = dt.timestamp() # datetime 转时间戳
PHP
$ts = time(); // 当前秒数
echo date('Y-m-d H:i:s', $ts);
$ts = strtotime('2026-04-29 00:00:00 UTC');
六、常见错误整理
| 错误情境 | 症状 | 解决方式 |
|---|---|---|
| 毫秒当秒处理 | 时间显示为西元 56000 年 | 除以 1000 或确认字段单位 |
| 忘记时区,本地时间存入 UTC 字段 | 时间差 8 小时 | 统一在 UTC 存储,显示时转换 |
| 32 位整数存储 | 2038 年后溢出归零 | 使用 BIGINT |
| 字符串时间未指定时区 | 不同服务器解读不一致 | ISO 8601 结尾加 Z 或 +08:00 |
总结
- 时间戳是「从 1970-01-01 00:00:00 UTC 起的秒数」,与时区无关
- 10 位数 = 秒;13 位数 = 毫秒,混淆是最常见的 bug
- API 设计:内部用整数,对外用 ISO 8601,统一使用 UTC
- 数据库:用 BIGINT 存储时间戳,避免 2038 年问题
- 所有语言都有标准库处理时间戳转换,不需要手动计算