指南
时间戳无效?最快的排查与修复指南
快速自检清单
- 看 位数:10=秒,13=毫秒,16=微秒,19=纳秒。
- 看 字符:只能是数字,去掉空格/标点/字母。
- 看 范围:结果日期要落在合理区间;用 64 位存储。
- 看 时区:先解析为 UTC,再转目标时区。
- 看 DST:若需本地化,用 IANA 时区名避免夏令时缺口。
想立刻验证?打开 Unix Timestamp Converter 或 Batch Converter。
常见报错类型
- 长度错位:13 位当秒 → 远未来日期。
- 非数字:隐藏空格、逗号、字母。
- 超范围:32 位秒级 2038 溢出;负数在部分系统不支持。
- 时区不明:服务器本地时间与预期 UTC 不一致。
- DST 影响:落在缺失的那一小时导致解析失败。
校验与规范化
// JS:校验 & 归一化为毫秒
export function normalizeEpoch(raw) {
const trimmed = raw.trim();
if (!/^[0-9]+$/.test(trimmed)) throw new Error("仅允许数字");
const len = trimmed.length;
if (len === 10) return Number(trimmed) * 1000;
if (len === 13) return Number(trimmed);
if (len === 16) return Number(trimmed) / 1000;
if (len === 19) return Number(trimmed) / 1_000_000;
throw new Error("长度不合法");
}
# Python:校验并转为 UTC datetime
from datetime import datetime, timezone
def parse_epoch(raw: str) -> datetime:
if not raw.isdigit():
raise ValueError("仅允许数字")
n = len(raw)
if n == 10:
ts = int(raw)
elif n == 13:
ts = int(raw) / 1000
elif n == 16:
ts = int(raw) / 1_000_000
elif n == 19:
ts = int(raw) / 1_000_000_000
else:
raise ValueError("长度不合法")
return datetime.fromtimestamp(ts, tz=timezone.utc)
-- PostgreSQL:批量标记精度/异常
SELECT id, ts_raw,
CASE
WHEN ts_raw ~ '^[0-9]{10}$' THEN 'seconds'
WHEN ts_raw ~ '^[0-9]{13}$' THEN 'milliseconds'
WHEN ts_raw ~ '^[0-9]{16}$' THEN 'microseconds'
WHEN ts_raw ~ '^[0-9]{19}$' THEN 'nanoseconds'
ELSE 'invalid'
END AS ts_precision
FROM events
WHERE ts_raw !~ '^[0-9]{10}$'
OR ts_raw::numeric > 32503680000; -- > 3000-01-01 视为异常
修复模板
- 精度修复:按位数缩放到毫秒,再重新解析。
- 清洗字符:去掉空格、逗号后再走正则校验。
- 范围兜底:超出合理窗口(如
<2000或>2100)直接标记为异常。 - 时区修复:先以 UTC 解析,再转到目标偏移或 IANA 时区。
- DST 安全:尽量使用 UTC;若必须本地显示,用 IANA 区而非固定偏移。
FAQ
- 安全默认值是什么? 先解析为 UTC,再输出目标时区。
- 如何避免 2038 问题? 全链路使用 64 位整数,避免 32 位秒级存储。
- 批量清洗怎么做? 正则预过滤 + 位数缩放 + 转换校验;可用 Batch Timestamp Converter。