时间戳是什么
Unix 时间戳是自 1970-01-01 00:00:00 UTC 起经过的秒数。它与时区无关:全球同一时刻读到的值完全相同,这正是它适合存储和传输的原因。
秒、毫秒、微秒
- 10 位 = 秒(Linux/数据库常用);
- 13 位 = 毫秒(Java、JavaScript 常用);
- 16 位 = 微秒(部分高精度系统)。
位数混用会得到 1970 年或五万年后的日期。看到离谱的转换结果,先数一下位数。
时区只影响显示
同一时间戳在 UTC+8 显示 19:00,在 UTC 显示 11:00。变的是显示,不是值。多数“时间对不上”的问题,本质是把本地时间当 UTC 存了(或反过来)。
实用建议
- 数据库统一存 UTC 时间戳或 ISO 8601 字符串;
- 前端拿到后再按用户时区本地化显示;
- 留意 2038 问题:32 位秒级时间戳会溢出,新系统一律用 64 位。
各语言与数据库
| 环境 | 获取当前时间戳 | 位数 |
|---|---|---|
| JavaScript | Date.now() | 13 位(毫秒) |
| Python | time.time() | 10 位(秒,带小数) |
| Java | System.currentTimeMillis() | 13 位(毫秒) |
| Go | time.Now().Unix() | 10 位(秒) |
| MySQL | UNIX_TIMESTAMP() / FROM_UNIXTIME(1700000000) | 秒 |
| PostgreSQL | EXTRACT(EPOCH FROM now()) | 秒(带小数) |
命令行验证
# Linux / macOS:时间戳 → 可读 UTC 时间
date -u -d @1700000000
# 反向:可读时间 → 时间戳
date -u -d '2023-11-14 22:13:20' +%s
# 按指定时区渲染
TZ=Asia/Shanghai date -d @1700000000
四个最容易踩的坑
- 位数混用:把 10 位秒当毫秒读得到 1970-01-01;把 13 位毫秒当秒读得到五万年后;
- 把本地时间当 UTC 存:接口只传 "2026-09-23 10:00" 不带时区,跨时区用户就会看到错误时刻;
- 直接比较字符串:拿 ISO 字符串和时间戳比、或比带不同偏移量的时间,结果都不可靠;
- 忽略夏令时:部分地区一年两次跳变,跨时区调度务必以 UTC 为基准。
几个常被问到的问题
该存秒还是毫秒?存整数秒或毫秒都行,关键是全链路统一;毫秒精度更高,前端 Date.now() 默认毫秒。时间戳能为负吗?能,表示 1970 年之前。怎么避免 2038 问题?用 64 位整数存储。展示给用户该用什么?按用户时区格式化,别直接甩一串时间戳。