时间戳 10 位与 13 位:秒、毫秒与差 8 小时的真相

10 位是秒、13 位是毫秒,混用就差一千倍;「差 8 小时」不是时间戳错了,是 UTC 与本地时区的展示错位。一篇讲清互转换算、各语言取值写法对照和存储选型。

约 6 分钟读完 · 更新于 2026-10-21 · 文中每条都能在下面的配套工具里动手验证

10 位与 13 位:同一个时刻的两种计量

Unix 时间戳是「从 1970-01-01 00:00:00 UTC 起经过的时长」,与时区无关。10 位按秒计,13 位按毫秒计——JavaScript 的 Date.now() 给毫秒,多数后端语言默认给秒。混用的症状很固定:差一千倍。拿到一串数字先数位数,就能判断单位。

JavaScript:秒 ↔ 毫秒
Date.now()                    // 13 位毫秒
Math.floor(Date.now() / 1000) // 10 位秒
new Date(1727568000 * 1000)   // 秒 → Date 对象(先乘回 1000)
dateObj.getTime()             // Date 对象 → 13 位毫秒
Python
import time
time.time()              # 秒(float,取整用 int(time.time()))
int(time.time() * 1000)  # 毫秒
time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(1727568000))  # UTC 展示

「差 8 小时」的真相:UTC 与本地时区

时间戳本身没有时区,它只是 UTC 起点的偏移量。「差 8 小时」发生在展示层:同一时间戳,new Date() 的 toString 按浏览器本地时区渲染,toISOString 永远按 UTC 渲染(结尾带 Z)。中国是 UTC+8,两种展示正好差 8 小时——数据没坏,是读法不同。排查口诀:先确认数字对不对(单位),再确认字符串对不对(时区)。

同一时刻的两种字符串
const d = new Date(1727568000000);
d.toString()     // "Sun Sep 29 2024 08:00:00 GMT+0800"
d.toISOString()  // "2024-09-29T00:00:00.000Z"  ← 永远 UTC
// 数据库和接口之间传递,统一用 ISO 8601 带 Z 的写法最不易错

各语言「取当前秒级时间戳」对照

语言 / 环境写法单位
JavaScriptMath.floor(Date.now() / 1000)秒
Pythonint(time.time())秒
JavaSystem.currentTimeMillis() / 1000秒(原始为毫秒)
Gotime.Now().Unix()秒
MySQLUNIX_TIMESTAMP()秒
PostgreSQLextract(epoch from now())::int秒
Shelldate +%s秒

数据库该存什么:推荐两种,别存本地时间字符串

  • bigint 存 UTC 秒或毫秒时间戳——排序、比较、跨时区展示都简单;缺点是人眼不可读,且毫秒值要留意 64 位范围。
  • UTC + 类型化时间(PostgreSQL 的 timestamptz、MySQL 8 的 UTC DATETIME)——数据库理解时间语义,支持区间索引与内置运算。
  • 绝对别存「本地时间字符串」:一旦服务器搬迁、夏令时切换(中国虽无夏令时,跨境系统躲不开),历史数据直接变糊涂账。

高频陷阱清单

  1. new Date("10/11/2024")——按美式月/日解析还是英式日/月,各引擎实现有差异;跨环境传日期字符串一律用 ISO 8601(2024-11-10)。
  2. 「今天 0 点」用 new Date().setHours(0,0,0,0) 得到的是本地时区的 0 点,服务器与用户时区不同就会偏——明确传 UTC 或带偏移的 ISO 字符串。
  3. 32 位 signed int 只能存到 2038-01-19 的秒级时间戳(Y2038);与嵌入式、老系统对接前先确认位数。
  4. 毫秒时间戳传给只收秒的接口(或反之)不报错,只是时间飘到 1970 年或 5 万年后——接口文档里写死单位。
  5. 闰秒对 Unix 时间戳无影响(它不是物理秒表),别为闰秒做特殊处理;夏令时才需要当心。

常见问题

怎么快速判断一串数字是秒还是毫秒?

数位数:10 位是秒,13 位是毫秒,也有少见的 16 位微秒。最稳的办法是拿 时间戳转换工具试一下:按秒解读出合理日期就是秒,出荒谬年份就是毫秒。

前端传毫秒、后端收秒,有没有优雅的兼容方案?

约定优先:接口文档写死单位,并在服务端做位数自适应(绝对值大于 1e11 即毫秒,除以 1000)。但自适应是兜底不是设计——两个服务长期对接时,统一在边界层(网关 / SDK)转成同一种单位,内部各存各的。

为什么 new Date("2024-09-29") 和 new Date("2024/09/29") 结果差 8 小时?

ISO 格式按 UTC 午夜解析,斜杠格式按本地时区午夜解析——这是规范行为不是 bug。要本地时间就用斜杠或显式构造,要 UTC 就用完整 ISO 字符串(带 Z 或偏移),别混着写。

时间戳会被时区或夏令时影响吗?存库前要转换吗?

都不用。Unix 时间戳是从 UTC 纪元起的绝对偏移量,没有时区属性,夏令时切换、服务器搬迁都不影响它的值——受影响的只是「展示层」。存库存原始时间戳或 UTC 类型即可,任何时区偏移都留在渲染时做;唯一要防的是把「本地时间的字符串」当时间戳存进去。

📂

松开以自动格式化

支持 .json / .sql / .csv / .html / .css / .xml / .yaml 文件