使用方法
- 单值换算:在「时间戳或日期时间字符串」里填 1790829045000(示例值,13 位毫秒),单位保持「自动识别」,按 Enter 或点「转换」。结果区会立刻列出毫秒、微秒、秒三种时间戳,以及本地时间、数据库格式、ISO 8601、RFC 2822 四类日期写法。
- 改单位:想让同一个数字按别的档位解释,把「单位」切成秒、毫秒或微秒。自动识别是按位数判定的——10 位算秒、13 位算毫秒、16 位算微秒,其余位数会直接报错,规则见下面的对照表。
- 选时区:结果里的「北京时间、数据库格式、ISO 8601 含偏移、RFC 2822」都会跟着「显示时区」下拉走,默认北京时间 UTC+8,另有两项 UTC 与美东 UTC−5。只有「ISO 8601(UTC)」那一行固定按 UTC 输出,不随选择变化,方便你对着服务端日志核对。
- 反方向用:把
2026-10-01 12:30:45或2026-10-01T04:30:45Z贴进同一个输入框,时间戳转换工具会先判断字符串属于哪种格式,再回推毫秒时间戳,不需要额外切模式。 - 批量解析:把日志整段粘到下面的大文本框(页面打开时已预置 16 行示例),点「解析全部」或按 Ctrl + Enter。每行可以是纯数字时间戳,也可以是数据库时间串、ISO 8601 或邮件头里的 RFC 2822 时间,四种可以混排在同一段里。
- 表格先渲染前 12 行,点「加载更多」每次再展开 12 行,上限 36 行。「导出 CSV」的文件带 UTF-8 BOM,Excel 双击打开中文不会乱码;「复制对照表」复制的是制表符分隔的 TSV,粘进 Excel 会自动分列。
这个时间戳转换工具能解决什么问题
一是看清日志里那串数字到底是什么时间。应用日志、埋点上报、消息队列的投递时间常常只留一个 13 位整数,肉眼无法判断是哪一天。贴进来立刻变成人能读的日期,并且同时给出 UTC 与带偏移两种写法。
二是把毫秒和微秒分清楚。同一台机器上,Java 的 System.currentTimeMillis() 给 13 位毫秒,而 System.nanoTime()、部分 Go 与 Rust 的性能打点、MySQL DATETIME(6) 落库的时间给到的却是微秒甚至纳秒。把 16 位微秒直接丢给 new Date(),得到的是公元 58719 年——复算脚本里算出来的就是 +058719-02-12。工具会按位数先判定单位再换回毫秒,避免这个坑。
三是对齐数据库里的时间字段。运维排查「订单时间比预期早 8 小时」这类问题时,需要把数据库里的 2026-10-01 12:30:45 和日志里的 1790829045000 摆在一起看。本页输出的「数据库格式」一行就是可直接对照 DATETIME 字段的写法。
四是批量清洗一段日志片段。一次贴 16 行、几百行都行,结果可以导出 CSV 交给同事。识别不了的行不会被静默丢掉,而是在「识别为」列标出原因(位数不对、日期不存在、找不到时间),方便回头去找上游格式问题。
本页不做这些事:不解析带夏令时规则的 IANA 时区名(如 Asia/Shanghai 的历史切换),只按固定 UTC 偏移换算;不把日期字符串的小数秒保留到微秒;不做时间戳加减运算。要按天推算日期请用「日期加天数计算器」,要算两个日期差几天请用「日期间隔天数计算器」。
换算原理:位数判定、ISO 8601 与数据库时间格式
这个时间戳转换工具的换算枢纽是一个数字:毫秒。JavaScript 的 Date 内部就是按「自 1970-01-01T00:00:00Z 起经过的毫秒数」存储的,所以本页的所有路径最后都归到毫秒,再分叉输出各种格式。具体用到 Date.UTC(按 UTC 组装并返回毫秒)、new Date(ms)、Date.prototype.toISOString(输出带 Z 的 UTC 写法)、Date.prototype.getUTC* 系列(按固定偏移取值)和字符串拼接补零。
关键参数为什么这样定。三处取值都不是拍脑袋:
- 单位靠位数判定,而不是猜数值大小。当前毫秒是 13 位(1790829045000),秒是 10 位(1790829045),微秒是 16 位(1790829045000000),三档位数天然不重叠,判定成本极低。代价是历史上有一段模糊区间:1970-01-12 到 1970-04-27 之间的毫秒时间戳刚好也是 10 位,会和秒级写法撞车,所以要强制解释时请用单位下拉指定。
- 显示时区做成显式下拉。如果按浏览器时区显示,同一串时间戳在不同机器上会得出不同文本,日志比对就失去意义,所以默认钉死 UTC+8。
- 数据库格式固定为「秒级、无小数」。MySQL 的
DATETIME(n)里 n 取 0 到 6,n=0 就是yyyy-MM-dd HH:mm:ss,是绝大多数后台系统实际写入的形态;带毫秒的那一份单独占一行,避免和数据库字段对不上。
输入经过怎样的转换得到输出。分两条路:
- 字符串 → 毫秒。用一条正则拆出年月日时分秒与小数位,再判断有没有时区后缀。带
Z或±HH:mm的,调Date.UTC(y, m-1, d, H, M, S, ms)得到 UTC 毫秒,然后减去偏移分钟数乘 60000;不带偏移的(例如2026-10-01 12:30:45),用new Date(y, m-1, d, H, M, S, ms)按所选时区解释。带空格的写法并不是 ECMAScript 规定的格式,Safari 上会返回Invalid Date,所以本页不依赖Date.parse的宽松解析。 - 毫秒 → 各种格式。先给毫秒加上「所选时区偏移 × 60000」,再把结果交给
getUTC*系列方法取值并补零,这样得到的文本与运行环境无关。ISO 8601(UTC)那一行例外,直接用toISOString(),输出固定带Z。
遵循的标准。日期文本格式依据 ISO 8601 及其互联网 profile RFC 3339(2026-10-01T04:30:45Z、2026-10-01T12:30:45+08:00);邮件与 HTTP 头里的写法依据 RFC 2822;字符串解析与毫秒语义依据 ECMAScript 规范,其中明确规定「只有日期没有时间的写法按 UTC 解释,带时间但不带偏移的写法按本地时区解释」——这就是下面 FAQ 里那个 8 小时差异的来源。
完整示例(数值仅作演示)
示例条件与页面默认值一致:输入 1790829045000、单位「自动识别」、显示时区「北京时间 UTC+8」。
- 毫秒时间戳 1790829045000;微秒时间戳 1790829045000000;秒级时间戳 1790829045。
- 北京时间 2026-10-01 12:30:45.000;数据库格式 2026-10-01 12:30:45。
- ISO 8601(UTC)2026-10-01T04:30:45.000Z;ISO 8601(含偏移)2026-10-01T12:30:45.000+08:00。
- RFC 2822 Thu, 01 Oct 2026 12:30:45 +0800;星期周四。
同一时刻换三个时区看:UTC 写作 2026-10-01T04:30:45.000Z,UTC+8 写作 2026-10-01T12:30:45.000+08:00,UTC−5 写作 2026-09-30T23:30:45.000-05:00。三串文本各不相同,但 Date.parse 回来都是同一个毫秒数 1790829045000。
批量框里预置的 16 行日志,前 8 行的实测结果如下(全部按 UTC+8 展示):
| 原始行 | 识别为 | 毫秒时间戳 | 转换结果 |
|---|---|---|---|
| 1790829045000 订单创建 | 13 位毫秒 | 1790829045000 | 2026-10-01 12:30:45.000 |
| 2026-10-01 12:30:45 数据库写入 | 数据库格式 | 1790829045000 | 2026-10-01 12:30:45.000 |
| 2026-10-01T04:30:45Z ISO 8601 日志 | ISO 8601 | 1790829045000 | 2026-10-01 12:30:45.000 |
| Thu, 01 Oct 2026 12:30:45 +0800 邮件头 | RFC 2822 | 1790829045000 | 2026-10-01 12:30:45.000 |
| 1790829045000000 微秒计时 | 16 位微秒 | 1790829045000 | 2026-10-01 12:30:45.000 |
| 1790829045 秒级日志(10 位) | 10 位秒 | 1790829045000 | 2026-10-01 12:30:45.000 |
| 1790829285999 优惠券核销 | 13 位毫秒 | 1790829285999 | 2026-10-01 12:34:45.999 |
| 2026-10-01T05:00:00Z 网关健康检查 | ISO 8601 | 1790830800000 | 2026-10-01 13:00:00.000 |
注意前六行里,六种完全不同的写法收敛到了同一个毫秒数 1790829045000:13 位毫秒、数据库格式、带 Z 的 ISO 8601、RFC 2822、16 位微秒、10 位秒。这正是批量模式最实用的地方——不管上游把时间写成什么样,清洗后都是同一根时间轴上的一个数。
输入范围与位数、格式对照表
先看位数。纯数字输入按十进制位数判定单位,选不中三档就直接报错、不做猜测:
| 位数 | 单位 | 十进制区间 | 对应的北京时间区间 |
|---|---|---|---|
| 10 位 | 秒 | 1000000000 ~ 9999999999 | 2001-09-09 09:46:40 ~ 2286-11-21 01:46:39 |
| 13 位 | 毫秒 | 1000000000000 ~ 9999999999999 | 2001-09-09 09:46:40.000 ~ 2286-11-21 01:46:39.999 |
| 16 位 | 微秒 | 1000000000000000 ~ 9999999999999999 | 2001-09-09 09:46:40.000 ~ 2286-11-21 01:46:40.000(超过 253 后不精确) |
| 9 位及以下 11、12、14、15、17 位及以上 | 不判定 | — | 报错,请用「单位」下拉手动指定 |
再看格式。本页支持的日期字符串写法与它们各自出现的地方:
| 格式 | 示例 | 是否带偏移 | 常见出处 |
|---|---|---|---|
| yyyy-MM-dd HH:mm:ss | 2026-10-01 12:30:45 | 不带 | MySQL DATETIME(0)、Java SimpleDateFormat、后台导出表 |
| yyyy-MM-dd HH:mm:ss.SSS | 2026-10-01 12:30:45.000 | 不带 | log4j / logback 的 %d{yyyy-MM-dd HH:mm:ss.SSS} |
| ISO 8601(UTC) | 2026-10-01T04:30:45Z | 带 Z | JSON 接口、Kubernetes、Docker、云厂商 API |
| RFC 3339(带偏移) | 2026-10-01T12:30:45+08:00 | 带 ±HH:mm | OpenAPI 里的 date-time、OAuth 令牌字段 |
| RFC 2822 | Thu, 01 Oct 2026 12:30:45 +0800 | 带 ±HHmm | 邮件 Date: 头、部分 HTTP 头 |
| 纯数字时间戳 | 1790829045000 | 取决于位数 | JavaScript Date.now()、埋点上报、Redis 有序集合分数 |
时间戳转换工具的单值输入框上限 64 个字符,批量文本框上限 20 万个字符(约 8000 行日志)。单值输入里的 2026-10-01 这种「只有日期」的写法也会被识别,但它按 UTC 解释,和按本地时区解释会差整整 8 小时(UTC+8 环境),详见 FAQ。
边界与精度:8.64×1015、253 与 2038 年
- 毫秒的上限是 Date 的范围,不是 253。ECMAScript 规定
Date可表示 ±8 640 000 000 000 000 毫秒,即8.64×1015,正方向到+275760-09-13为止。而安全整数上限253−1 = 9007199254740991比它还大,所以毫秒这一档是Date先卡住。超出范围时本页直接给出报错文案,不会静默变成Invalid Date。 - 微秒的实际上限是 253。微秒要除以 1000 才能喂给
Date,能精确表示的最大微秒数就是 9007199254740991,对应2255-06-05T23:47:34.740Z——离 2026 年还有 229 年。再往上每加 1 微秒就不再生效(+1与+2会得到同一个数),所以 16 位微秒的高位区间只能算到毫秒。 - 纳秒时间戳本页不接收。19 位纳秒已经越过 253,直接除以 1e6 会先丢精度,换算结果不可信。批量解析遇到 17 位以上的数字会报「这行没有可识别的时间」,不会假装算出一个结果。
- 日期字符串的小数秒只保留到毫秒。
2026-10-01T04:30:45.123456Z里的后 3 位会被截断,因为Date的最小单位就是毫秒,截断时页面会给出提示。ISO 8601 本身允许无限位小数,MySQL 的DATETIME(6)也确实能存 6 位,但那是数据库侧的精度。 - 数据库时间类型的上限与 2038 年。MySQL
TIMESTAMP是 32 位有符号整数秒,上限2147483647,即2038-01-19 03:14:07 UTC,换算成北京时间是 2038-01-19 11:14:07;TIMESTAMP(3)的毫秒上限是 2147483647999。DATETIME没有这个限制,能到9999-12-31 23:59:59;而 13 位毫秒的十进制上限 9999999999999 落在2286-11-21 01:46:39.999。 - 非法日期会被本页拒绝,而不是滚动。
new Date(2026, 1, 30)不会抛错,它会安静地变成 3 月 2 日;new Date(2026, 12, 1)会变成 2027 年 1 月 1 日。本页在构造后回读月日时分秒逐项比对,对不上就报「日历上不存在这一天」,避免把脏数据悄悄洗成另一个日期。 - 不带偏移的字符串按所选时区解释。同一行
2026-10-01 12:30:45,选 UTC+8 时对应毫秒 1790829045000,选 UTC 时会变成 1790819445000,两者差 28800000 毫秒(8 小时)。日志比对前请先确认上游落库用的是哪个时区。 - 表格最多渲染 36 行。这是渲染软上限,不是解析上限——解析仍然会处理文本框里的每一行,导出的 CSV 也包含全部行。想看完整结果用导出按钮,不要靠不停点「加载更多」。
常见问题
填 13 位毫秒,为什么结果和我以为的时间差了 8 小时?
多数情况是时区下拉还停在默认的「北京时间 UTC+8」,而你要对的是 UTC 日志。切到 UTC 后,同一串 1790829045000 会显示成 2026-10-01 04:30:45.000。时间戳本身不带时区信息,它只是 1970-01-01T00:00:00Z 起的一个毫秒偏移量。
10 位和 13 位怎么区分?10 位一定是秒吗?
现在这个年代基本成立:当前秒级是 10 位(1790829045),毫秒 13 位,微秒 16 位。但 1970-01-12 到 1970-04-27 之间的毫秒时间戳也落在 10 位区间(1000000000 ~ 9999999999),那时两者无法凭位数分开。遇到这种历史数据,直接用「单位」下拉指定,别依赖自动识别。
为什么输入 2026-10-01 得到的结果偏了 8 小时?
因为 ECMAScript 规定「只有日期、没有时间」的写法按 UTC 解释,而「带时间但不带偏移」的写法按本地时区解释。new Date('2026-10-01') 得到 1790812800000,而按北京时间构造 new Date(2026, 9, 1) 得到 1790784000000,两者相差 28800000 毫秒。要按本地零点算,请把时间补全成 2026-10-01 00:00:00。
16 位微秒时间戳为什么能显示到毫秒、显示不到微秒?
因为 Date 的最小粒度就是毫秒。工具的换算路径是「16 位微秒 ÷ 1000 取整 → 毫秒 → 格式化」,结果里最多保留 3 位小数。原始微秒数会原样显示在「微秒时间戳」一行里,需要精确到微秒时请看那一行。
日志行前面有方括号或级别前缀,还能识别吗?
能。[INFO] 2026-10-01 12:30:45 — 这类行会先被正则扫到中间的时间串,前缀被忽略,原始行会完整保留在「原始输入」列供你核对。同样地,Date: Thu, 01 Oct 2026 12:30:45 +0800 这种邮件头也能取到时间。
为什么 2026-02-30 报错,而不是像 Date 那样滚到 3 月 2 日?
因为静默滚动会把上游的脏数据洗成一个看起来合理的日期,排查时反而更难定位。本页在按年月日构造之后,会把月日时分秒逐项读回来比对,只要有一项对不上就报「日历上不存在这一天」。
2038 年 1 月 19 日之后时间戳会溢出吗?
取决于存的是毫秒还是秒。13 位毫秒时间戳表达 2038-01-19 11:14:07(北京时间)只需要 2147483647000,一路可以用到 2286-11-21。会溢出的是把秒数塞进 32 位有符号整数的 TIMESTAMP 字段,上限正好是 2038-01-19 03:14:07 UTC,换成 DATETIME 或 BIGINT 存毫秒即可绕开。
表格最多显示 36 行,那几百行的日志怎么办?
36 行只是页面渲染的软上限,不是解析上限。文本框里的每一行都会被解析,「导出 CSV」导出的也是全部行,不受显示条数影响。要一次性看完长日志,用导出而不是反复点「加载更多」。