← 全部文章

Epoch 转换器错误:如何避免错误的 Unix 时间戳转换

大多数 epoch 转换器的 bug 不在数学,而在单位、时区,以及你对输入所带的假设。这是一份会产生 1970 年日期和差一小时 bug 的转换错误现场指南,每个都配有能抓出它的那一个验证步骤。

产生错误日期的七个错误

epoch 转换器只做简单的算术,所以当输出错误时,原因几乎从来不是数学——而是输入。时间戳不带标签告诉你它是秒还是毫秒、UTC 还是本地、精度如何,而每次错误转换都来自把其中之一猜错。最快的线索是得出的年份:靠近 1970 年或在数千年之后的日期是单位混淆,而正确但差了整数小时的日期是时区错误。下表是现场指南;其后的各节深入解释单位与时区错误,并展示如何在代码中验证一次转换。

错误你看到的原因修复
把秒当作毫秒读日期落在 1970 年JS 的 Date 和 Date.now() 期望 ms;你传了 10 位的秒把秒乘以 1000
把毫秒当作秒读日期在数千年之后把 13 位值传给了秒函数先除以 1000
UTC 显示为本地时间日期对,但时钟差了你的偏移转换器默认选了另一个时区把转换器切到 UTC
复制本地时间却没带偏移在另一台机器上差了数小时保存了不带时区的挂钟时间保存 UTC 加上时区
夏令时下含糊的挂钟时间在切换附近恰好差一小时一个出现两次或从不出现的本地时间从 UTC 转换;固定 IANA 时区
把微/纳秒当作秒读日期在很远的未来(16 或 19 位)数据库或追踪的 µs 或 ns 值除以 1,000,000(µs)或 1,000,000,000(ns)
相信显示出的精度亚秒部分被悄悄丢弃转换器截断了毫秒确认目标 API 文档所述的单位

epoch 转换器做什么

epoch 转换器把数字时间戳变成可读日期,并把人类日期转回 epoch 时间戳。一个好的转换器处理 Unix 秒、Unix 毫秒、UTC 输出、本地时区输出和 ISO 8601 字符串,并在你把值复制进代码、数据库或 API 请求之前让单位一目了然。epoch 转换器、Unix 时间转换器、Unix 时间戳转换器和 Unix epoch 计算器描述的是同一件工作:在自 1970 年 1 月 1 日 UTC 起的秒(或毫秒)计数与人类可读的日期之间互译。转换器很少是问题——问题通常出在输入。

单位错误:秒、毫秒、微、纳

最常见的转换错误就是单位混淆,而且它有一个标志:日期落在 1970 年,或在数千年之外。JavaScript 是它最常咬人的地方,因为 Date 构造函数和 Date.now() 都以毫秒工作,而大多数 API、数据库和 Unix 的 date 命令以秒工作。把 10 位的秒值传给 new Date() 而不乘以 1000,你就早落了 53 年。反过来——把 13 位的毫秒喂给秒函数——会把日期抛向远方的未来。更高精度的来源让情况更糟:数据库常输出 16 位的微秒,追踪系统输出 19 位的纳秒,二者看起来都像有效的 Unix 值,直到它们解码到错误的千年。

  • 10 位 → 秒(如 1700000000);13 → 毫秒;16 → 微秒;19 → 纳秒
  • JavaScript:new Date(seconds * 1000),或直接 new Date(ms)
  • 微秒 → 转换前除以 1,000,000;纳秒 → 除以 1,000,000,000
  • 常识检查:结果应是当前十年里一个可信的日期

时区错误:UTC vs 本地与夏令时

单位一旦正确,剩下的错误就是时区错误,它们也共享一个标志:日期正确,但时钟差了整数小时。Unix 时间戳是一个没有自身时区的单一时刻;偏移只在格式化该时刻时才套用。所以设为不同时区的两个转换器会对同一个数字显示不同的时钟时间——谁都没错,它们只是显示不同的本地视角。陷阱在于复制一个本地挂钟时间却不记录它来自哪个时区,或转换一个落在夏令时切换上的时间,那里一个本地时间可能出现两次或一次也不出现。当结果恰好差一小时,先怀疑夏令时,再怀疑转换器。

  • 在 UTC 中比较值;只在显示它们的那一刻才套用本地时区
  • 切勿在不一并存储其 IANA 时区或 UTC 偏移的情况下保存本地时间
  • 在夏令时切换前后,从 UTC 推导该时刻,而非从含糊的本地时间

先选好方向

大多数时间戳任务朝两个方向之一进行:epoch 转日期,或日期转 epoch。先决定方向可以防止错误测试数据和损坏 API 负载的最常见原因——把对的值朝错的方向转换。

  • epoch 转日期:粘贴 1700000000 并读取 UTC 或本地日期
  • 日期转 epoch:选择 2026-01-01 00:00:00 UTC 得到 1767225600
  • 复制结果前,确认目标期望的是秒还是毫秒

复制转换值之前要核对什么

转换器只能在输入无歧义的限度内保持正确。在把时间戳复制进测试、cron 作业、迁移或 API 请求之前,核对单位、时区和期望精度。最快的常识检查是得出的年份:靠近 1970 年或在远方未来的日期,几乎总是表示单位混淆,而非转换器错误。

  • 接收系统期望的是秒还是毫秒?
  • 显示的日期是 UTC 还是本地时间?
  • 该时间戳表示一个时刻,还是一个本地日历日期?
  • 数据库列存储的是原生 datetime、Unix 秒,还是 Unix 毫秒?
  • 结果是否靠近 1970 年或在远方未来——这通常表示单位混淆?

在代码中验证一次转换

当一个转换值很重要时——一次迁移、一个计费边界、一个 cron 排程——不要只信一个工具。在你自己的运行时里重新推导同一个时刻,并核对二者在 UTC 中一致。下面每一行都打印一个带 Z 后缀、毫无歧义的 ISO 8601 字符串,因此没有可比较的本地时区猜测。

  • JavaScript: new Date(1700000000 * 1000).toISOString() // '2023-11-14T22:13:20.000Z'
  • Python: datetime.fromtimestamp(1700000000, tz=timezone.utc).isoformat()
  • Shell (GNU): date -u -d @1700000000 +'%Y-%m-%dT%H:%M:%SZ'
  • 如果工具与你的运行时不一致,可疑的是输入的单位或时区——而不是转换器

实例:一个时刻,三种表示

取时刻 2026-01-01 00:00:00 UTC。作为 Unix 秒是 1767225600;作为 Unix 毫秒是 1767225600000;作为 ISO 8601 是 2026-01-01T00:00:00Z。三者描述同一个时刻——只是格式和单位不同。这个时刻从不带有自身的时区;纽约会把同一个值显示为 2025-12-31 19:00:00,因为偏移是在显示时套用的,而非存储在数字里。

相关文章

FAQ

为什么我转换出的日期落在 1970 年?
几乎总是因为把秒当作毫秒来读了。JavaScript 的 Date 和 Date.now() 使用毫秒,所以传入 10 位的秒值会落在 1970 年 1 月。请先把秒乘以 1000。
为什么我转换出的时间恰好差一小时?
那是时区或夏令时错误,而不是计算错误。转换器套用了不同的时区,或本地时间正好落在夏令时切换上。把转换器切到 UTC 看到规范时刻,再套用你真正想要的时区。
最适合复制的 epoch 转换器格式是什么?
对于代码,按目标 API 文档所述复制 Unix 秒或毫秒。对于人类,复制带 Z 或显式时区偏移的 ISO 8601,使该时刻明确无歧义。
epoch 转换器和 Unix 时间转换器一样吗?
对大多数开发者搜索而言,是的。epoch 转换器、Unix 时间转换器、Unix 时间戳转换器和 Unix epoch 计算器都在 Unix epoch 时间戳与可读日期之间转换。
为什么不同的 epoch 转换器显示不同的本地时间?
它们套用了不同的时区。底层的 UTC 时刻是相同的;只有本地显示在变。把转换器切到 UTC 以比较规范值。
我怎么知道我的数字是秒还是毫秒?
数位数。现代的 10 位值是 Unix 秒;13 位值是 Unix 毫秒。如果一个 10 位值在 JavaScript 中落在 1970 年附近,它被当作了毫秒,需要乘以 1000。