NOTE 04 / ENGINEERING

接口时间字段排查清单:
从联调到上线

时间字段的 bug 有一个共同特点:联调时看起来正常,上线后却在跨时区、跨年或数据量变大时出现。与其靠猜,不如在联调、测试和上线三个节点各跑一遍清单,把问题留在可控范围内。

时间字段的问题很少是某一行代码“写错了”,更多是约定没有写清楚:单位靠猜、时区靠默认、精度靠运气。下面这份清单按数据流排列,可以逐项对照现有接口。

01 单位与字段名

  • 字段名是否明确了单位?created_at_ms 比 created_at 更不容易误解。
  • 文档是否写了“秒”或“毫秒”,而不只是“时间戳”?
  • 整数是否可能超过 JavaScript 安全整数范围?超过 13 位时优先用字符串。
  • 同一个接口里是否存在秒和毫秒混用?如果无法避免,字段名必须区分。
  • 负数时间戳是否在业务范围内?如果是,序列化和展示是否支持?

02 格式与序列化

整数、ISO 字符串和带偏移的 RFC 3339 字符串各有适用场景。关键不是选哪一种,而是全链路统一,并在边界处显式转换。

THREE COMMON FORMATS
// 1. 秒级整数:短,但必须约定单位
{ "created_at": 1767225600 }

// 2. UTC ISO 字符串:无歧义,适合 JSON
{ "created_at": "2026-01-01T00:00:00.000Z" }

// 3. 带偏移的 RFC 3339:保留本地时间信息
{ "created_at": "2026-01-01T08:00:00+08:00" }

如果接口同时返回时间戳和格式化字符串,要确认两者指向同一时刻。曾经出现过的典型问题是:时间戳按 UTC 生成,字符串却按服务器本地时区格式化,前端无论用哪个都会得到不一致的结果。

03 时区约定

  • 存储层是否统一使用 UTC 或带时区类型?
  • 数据库会话时区是否固定?连接池、迁移任务和报表任务是否一致?
  • 应用服务器、容器和定时任务是否都设置了明确的 TZ?
  • 前端格式化是否显式传入时区,而不是依赖浏览器默认值?
  • 面向用户的页面是否标注了“北京时间”或具体城市,而不是只显示裸时间?

跨时区业务还应对夏令时做一次专项检查。北京时间没有夏令时,但纽约、伦敦、巴黎和悉尼有;固定偏移的代码在切换日会偏差一小时。

04 存储与精度

  • 秒级字段是否使用 BIGINT 或等价宽类型,而不是 32 位 INT?
  • 需要毫秒精度时,数据库列是否真的保留了小数秒?
  • 读取和写入是否使用同一种时间类型?是否发生了隐式时区转换?
  • 备份、数据仓库和导出文件是否也完成了字段升级?
  • 索引和排序是否按绝对时间进行,而不是按格式化字符串?

字符串排序在 ISO 8601 且统一带 UTC 的情况下通常可行,但一旦混入不同偏移或本地格式,顺序就会出错。排序和比较优先使用时间戳或数据库时间类型。

05 前端展示

前端至少需要回答三个问题:用哪个时区显示?显示到秒还是毫秒?空值和异常值怎么呈现?

EXPLICIT DISPLAY / 显式时区
const formatter = new Intl.DateTimeFormat('zh-CN', {
  timeZone: 'Asia/Shanghai',
  year: 'numeric',
  month: '2-digit',
  day: '2-digit',
  hour: '2-digit',
  minute: '2-digit',
  second: '2-digit',
  hourCycle: 'h23'
});

formatter.format(new Date(1767225600 * 1000));
// 2026/01/01 08:00:00

不要在组件里散落“减 8 小时”的魔法数字。所有时区处理应收敛到一个工具函数或日期库配置中,避免不同页面各自实现一套。

06 监控与回归

  • 日志是否同时记录原始时间戳、单位和格式化结果?
  • 是否对异常年份(例如 1970、1901、2100 以后)设置告警?
  • 是否有跨时区、跨夏令时、跨年和闰日的固定测试用例?
  • 发布后是否抽查一条真实数据,从接口到页面完整走通?

回归测试不必很复杂。保留一组固定的时间戳与期望日期,覆盖秒/毫秒、UTC/北京时间、正常值与边界值,就足以拦住大部分低级错误。

07 上线前 12 项清单

#检查项通过标准
1单位字段名和文档明确秒或毫秒
2类型时间戳使用 64 位或字符串,不溢出
3格式JSON 中无歧义,带 Z 或偏移
4存储统一 UTC 或带时区类型
5会话时区应用与数据库设置一致且可查
6精度毫秒/微秒按需保留,未被截断
7显示显式时区,标注城市
8跨日目标城市日期差异有提示
9夏令时切换日测试通过
10边界2038 前后与远期日期可用
11异常空值、负值、超大值有兜底
12监控异常年份与格式有告警

这份清单可以直接复制到团队的发布检查表里。遇到具体值时,用单个转换核对,用批量转换抽查一列数据,再用时区换算确认两端城市的日期是否一致。