时间戳的定义与原点
Unix 时间戳是从 1970 年 1 月 1 日 00:00:00 UTC 起算的秒数,本身不含时区信息,也不含闰秒——规范上每天固定算 86400 秒,因此它表示的是 UTC 时刻,而不是「墙上时间」。往返转换的正确姿势是:先算成时刻,再按目标时区格式化;而不是直接对字符串做加减。
基本信息
| 原点 | 1970-01-01T00:00:00Z,即 UTC 时刻零点 |
|---|---|
| 单位 | 默认为秒,毫秒与微秒形式也普遍存在,入参必须确认 |
| 闰秒 | 计入方式是不计闰秒,每天按 86400 秒计 |
| 时区 | 时间戳本身无时区,显示时才套用偏移或时区名 |
| 上限 | 受存储类型限制,32 位有符号秒计数会在 2038 年 1 月 19 日溢出 |
典型使用场景
- 排查日志时间与业务记录对不上:确认两边都是 UTC 还是本地时间
- 计算耗时与超时:两点时间戳相减是最稳的做法
- 数据库与接口对时:统一以 UTC 存储,展示层再做时区换算
- 分析历史数据:注意时区历史变化,简单加固定偏移会错
- 写入配置或缓存键:时间戳比格式化字符串更安全
常用互转写法
常用互转写法
date -u -d @1700000000 # GNU date:转成 UTC 可读时间
date -u +%s # 当前时间转时间戳
date -d @1700000000 '+%F %T %z' # 按指定格式输出
python3 -c "import datetime as dt;print(dt.datetime.fromtimestamp(1700000000, dt.timezone.utc))"
python3 -c "import datetime as dt;print(int(dt.datetime(2023,11,15,tzinfo=dt.timezone.utc).timestamp()))"
node -e "console.log(new Date(1700000000*1000).toISOString())" # JS 需要毫秒工具对照
| 环境 | 时间戳转时间 | 时间转时间戳 |
|---|---|---|
| GNU date | date -u -d @<秒> | date -u +%s |
| Python | datetime.fromtimestamp(ts, timezone.utc) | int(dt.timestamp()) |
| JavaScript | new Date(ts*1000) | Math.floor(Date.now()/1000) |
| PowerShell | DateTimeOffset::FromUnixTimeSeconds | ToUnixTimeSeconds() |
| MySQL | FROM_UNIXTIME(ts) | UNIX_TIMESTAMP(dt) |
32 位有符号秒计数最大值为 2147483647,对应 2038-01-19T03:14:07Z。老系统的定时字段、旧数据库字段与嵌入式设备容易踩到这条界线,迁移时把类型换成 64 位,并预留足够大的边界值做兼容。
不同体系的起点并不相同:Windows 文件时间以 1601 年为起点按 100 纳秒计数,.NET 的计时单位以公元 1 年为起点,电子表格的序列号以 1900 年前后为起点,GPS 以 1980 年 1 月 6 日为起点。跨体系换算必须先确认起点,再谈单位。