使用方法
- 「累计起始时长」单位是毫秒,默认 3725000,也就是 01:02:05.000。纯正计时填
0;要把之前已经计过的时长接着往下累计,就把那个数值换算成毫秒填进来。允许 0~359999999 的整数。 - 「刷新间隔」默认 100 毫秒,允许 50~1000。它只决定大字区多久重绘一次,不参与时间计算——改这个值不会让计时变快或变慢,只会让末两位数字跳得更密或更疏。
- 「计次备注前缀」默认
第 # 圈,里面的#会被替换成圈号;留空则备注列显示一个短横。 - 点「开始」往前走,「暂停」冻结当前用时,「继续」从冻结处接着跑,「重置」回到输入框里的累计起点并清空计次。打开页面时工具已经替你按下了「开始」。
- 键盘也能操作:空格切换开始与暂停、L 计次、R 重置。光标停在输入框里时这些键不生效,避免打字时误触。
- 计次表默认显示 12 行演示数据,点「加载更多行」展开余下 6 行;「复制计次表」以制表符分隔复制,「导出 CSV」写成带 BOM 的文件,Excel 打开不乱码。
这个在线计时器能解决什么问题
一是把已经跑掉的时长续上来。多数计时工具只能从 00:00:00 起算,一旦页面刷新、换了设备或者中途换人接手,前面那段就白计了。这就是累计计时的用法:「累计起始时长」填前一段已经计过的 3725000 毫秒,接着往下走就行。
二是长时间挂着也不走形。脚本按 performance.now() 相减显示用时,而不是每刷新一次就加 100 毫秒,所以连续跑一小时、中途切到别的标签页再回来,数字都对得上真实经过的时间。
三是一边跑一边分段记录。点「计次」会记下本圈用时与累计用时两列:前者是距上一次计次的间隔,后者是从起点算起的总时长。做实验记录、装配节拍、会议分段发言都能直接用。
四是把「为什么别人的计时器越跑越慢」讲清楚。下面给出 setInterval 漂移的模型和一次本机实测数据,你可以拿自己电脑上的表现对照。
本页不做这些事:不做从设定时长往回走的计时、不做固定周期自动换挡的循环、不做到点响铃提醒。它只做一件事——把从起点到现在经过了多少时间,如实显示出来。
为什么用 performance.now() 而不是 Date.now():单调时钟与 setInterval 漂移
这个在线计时器里只有一条时间公式:已用 = performance.now() - 基准时刻。performance.now() 由 W3C 的 High Resolution Time Level 2 规范定义,返回从页面导航开始(timeOrigin)到现在的毫秒数,是带小数的浮点数。按下「开始」时记下 基准时刻 = performance.now() - 起始时长,之后每次重绘都重新做这一减法,而不是在旧值上加一个间隔。
它是单调时钟,不受系统改时间影响。Date.now() 返回的是自 1970-01-01T00:00:00Z 起的墙钟毫秒,NTP 校时、用户手动改表、夏令时切换都会让它跳变;跳一下,用 Date.now() 相减的计时器就会瞬间多走或少走几秒甚至几小时。performance.now() 只朝一个方向增长,与墙上的时间无关,因此只适合量「经过了多久」,不适合对齐某个绝对时刻。这条取舍正好与本页「只做正计时」的定位一致。
真正会让计时器变慢的是「按次数累加」。常见写法是 setInterval(function () { el += 100 }, 100),把「回调触发一次」等同于「过去了 100 毫秒」。但规范只保证间隔不小于 100 毫秒,回调排队、样式重算、垃圾回收都会插在中间。设每次回调平均多花 d 毫秒,真实周期就是 100 + d,墙钟走过 T 毫秒后只触发 floor(T / (100 + d)) 次,累加式的亏欠是 T × d / (100 + d),随时间线性增长:d 取 1 毫秒时 1 小时少算 35643.6 毫秒(约 35.6 秒),8 小时少算 285148.5 毫秒(约 4 分 45 秒)。间隔越大这个比例越小:同样 d 取 1 毫秒,1000 毫秒间隔跑 1 小时只少算 3596.4 毫秒——但那是拿「秒针一跳」的粗糙显示换来的。
这不是纸上推算,本机实测对得上。在 Windows 上以 100 毫秒间隔用 setInterval 跑 20 秒,理论应触发 200 次,实测只有 183 次:真实周期 109.36 毫秒,单次平均晚 9.36 毫秒,累加式在这 20 秒里就少走了 1712.7 毫秒。109.375 毫秒恰好等于 15.625 × 7,而 15.625 毫秒正是 Windows 默认定时器分辨率——也就是说 100 毫秒的请求被对齐到了 7 个时间片上。用时间戳相减则完全不受这件事影响:晚触发只会让数字晚几十毫秒才跳,走出来的值仍然准确。
后台标签页会把这笔账放大几十倍。标签页隐藏后,Chrome 把 setInterval 压到最快 1000 毫秒一次;隐藏满 5 分钟进入 intensive throttling,最多每分钟一次。累加式因此断崖式欠账:按「前 5 分钟每秒 1 次、之后每分钟 1 次」估算,隐藏 30 分钟只触发 325 次,显示停在 00:00:32.50,而墙钟已经走了 00:30:00.00。本页的做法是:隐藏时直接 clearInterval,回到前台先按 performance.now() 重算一次再重建定时器,所以离开多久都不影响结果。可见性判据用 W3C Page Visibility 规范定义的 document.hidden 与 visibilitychange 事件,比监听窗口的 blur / focus 更可靠——切换应用、锁屏、最小化都会正确改变可见性。
完整示例(数值仅作演示)
这个在线计时器的示例条件与页面打开时的默认值完全一致:累计起始时长 3725000 毫秒、刷新间隔 100 毫秒。
- 页面一打开就已开始正计时,大字区首帧显示 01:02:05.00,起点卡片也写着 01:02:05.00。
- 计到第 1 圈时点「计次」,本圈用时 00:00:12.50,累计用时 01:02:17.50;第 2 圈再点一次,累计变成 01:02:29.50。表里那 18 行演示数据就是按「本圈 12.50 秒与 12.00 秒交替」推出来的。
- 若换成按次数累加的写法,跑满 1 小时会少算 35643.6 毫秒(约 35.6 秒);把刷新间隔改成 1000 毫秒再跑 1 小时,少算降到 3596.4 毫秒。
- 把 1 小时换成 8 小时:100 毫秒间隔少算 285148.5 毫秒,1000 毫秒间隔少算 28771.2 毫秒。
- 截到后台 30 分钟再回来:累加式只走了 00:00:32.50,本页回到前台的第一帧就恢复到真实用时。
刷新间隔与显示精度的对照表
下表按 T × d /(间隔 + d) 逐行算出,d 取 1 毫秒,即每次回调平均多花 1 毫秒;「累加式少算」是同一段时长下,用触发次数乘间隔的写法会比真实时间少算多少。
| 时长 | 毫秒 | 大字区显示 | 100 毫秒间隔·累加式少算 | 1000 毫秒间隔·累加式少算 |
|---|---|---|---|---|
| 100 毫秒 | 100 | 00:00:00.10 | 1.0 毫秒 | 0.1 毫秒 |
| 1 秒 | 1000 | 00:00:01.00 | 9.9 毫秒 | 1.0 毫秒 |
| 5 秒 | 5000 | 00:00:05.00 | 49.5 毫秒 | 5.0 毫秒 |
| 10 秒 | 10000 | 00:00:10.00 | 99.0 毫秒 | 10.0 毫秒 |
| 30 秒 | 30000 | 00:00:30.00 | 297.0 毫秒 | 30.0 毫秒 |
| 1 分钟 | 60000 | 00:01:00.00 | 594.1 毫秒 | 59.9 毫秒 |
| 2 分钟 | 120000 | 00:02:00.00 | 1188.1 毫秒 | 119.9 毫秒 |
| 5 分钟 | 300000 | 00:05:00.00 | 2970.3 毫秒 | 299.7 毫秒 |
| 10 分钟 | 600000 | 00:10:00.00 | 5940.6 毫秒 | 599.4 毫秒 |
| 15 分钟 | 900000 | 00:15:00.00 | 8910.9 毫秒 | 899.1 毫秒 |
| 30 分钟 | 1800000 | 00:30:00.00 | 17821.8 毫秒 | 1798.2 毫秒 |
| 1 小时 | 3600000 | 01:00:00.00 | 35643.6 毫秒 | 3596.4 毫秒 |
| 2 小时 | 7200000 | 02:00:00.00 | 71287.1 毫秒 | 7192.8 毫秒 |
| 4 小时 | 14400000 | 04:00:00.00 | 142574.3 毫秒 | 14385.6 毫秒 |
| 8 小时 | 28800000 | 08:00:00.00 | 285148.5 毫秒 | 28771.2 毫秒 |
| 12 小时 | 43200000 | 12:00:00.00 | 427722.8 毫秒 | 43156.8 毫秒 |
| 24 小时 | 86400000 | 24:00:00.00 | 855445.5 毫秒 | 86313.7 毫秒 |
| 99 小时 | 356400000 | 99:00:00.00 | 3528712.9 毫秒 | 356044.0 毫秒 |
把两列放在一起看就明白了:间隔越小,按次数累加的亏欠越大。100 毫秒间隔跑 1 小时少算 35.6 秒,1000 毫秒间隔只少算 3.6 秒——因为 d 固定为 1 毫秒,间隔越小它占的比例越高。想靠加大间隔来减少亏欠,代价是秒位数字跳得越来越粗;而按时间戳相减的写法根本没有这一列。
输入范围、边界与精度说明
- 累计起始时长允许 0~359999999 的整数,上限正好是 99 时 59 分 59 秒 999 毫秒。填负数、小数、字母或空值都会被拒绝,提示指出「累计起始时长请填 0~359999999 之间的整数,你填的是……」,不会静默当成 0。
- 刷新间隔允许 50~1000 的整数。低于 50 毫秒,浏览器每秒要重绘 20 次以上,而屏幕本身也就 60 Hz 左右,徒增开销;高于 1000 毫秒时末两位厘秒已经看不出在读秒。填错时提示「刷新间隔请填 50~1000 之间的整数」。
- 显示精确到厘秒,末位直接截断而不是四舍五入。359999999 毫秒显示成
99:59:59.99,最后 9 毫秒被丢掉;185.34 毫秒显示成00:00:00.18。计时器的习惯是「没走满就不算」,向上取整会让归零时刻看起来提前。 - 内部一直保留毫秒浮点数,只在显示时才取整。所以连续暂停、继续几十次也不会因为反复四舍五入而累积误差。
- 时间值的硬边界是 253 − 1 毫秒,约 285420 年,超过这个数量级整数运算才会丢精度;本页上限 359999999 毫秒连一天的 5 倍都不到,离边界极远。
- 定时器延时按 32 位有符号整数传递,最大 231 − 1 = 2147483647 毫秒(约 24.86 天),这是刷新间隔不能设得过大、也不能靠单个定时器跑超长周期的原因。本页上限 1000 毫秒远在这条线以下。
- performance.now() 被浏览器刻意降精度:Chrome 默认把它的分辨率限制到 100 微秒,开启跨源隔离后可到 5 微秒,这是为了阻止通过高精度计时做侧信道攻击。0.1 毫秒的分辨率对厘秒级显示完全够用。
- 计时在页面关闭时结束。本页不做持久化,刷新后按输入框里的累计起点重新开始;想保留记录就先「复制计次表」或「导出 CSV」。
常见问题
为什么不用 Date.now() 计时?
Date.now() 读的是墙钟。系统自动对时、你手动改时间、或者处在夏令时切换的时区,它都可能突然跳一大截,用它做减法的计时器会跟着跳。performance.now() 是单调时钟,只朝一个方向走,量「经过多久」不受影响——代价是它不能对齐墙上的某个时刻。
把刷新间隔改成 1000 毫秒,计时会变慢吗?
不会。刷新间隔只决定大字区多久重绘一次,用时始终由 performance.now() 与基准时刻相减得出,改成 1000 毫秒只是让数字一秒跳一次。反过来说,如果计时值是按「刷新一次加一个间隔」算的,改这个值才会改变结果——本页不是那种写法。
切到别的标签页,计时会停吗?回来后还准吗?
不会停,也不会少走。页面隐藏时本页主动清掉定时器、不在后台空转,回到前台先按 performance.now() 重算一次再重建定时器,所以离开多久都不影响累计用时。
「累计起始时长」是干什么用的?
用来把之前已经计过的时长续上。比如上一段计到 01:02:05 时被打断,把 3725000 毫秒填进来,新一段就从 01:02:05.00 接着往下走,而不是从零开始。填 0 就是纯正计时。
计次表里「本圈用时」和「累计用时」有什么区别?
「累计用时」是从起点算起的总时长,「本圈用时」是距上一次计次的间隔。第一次计次时,本圈用时等于当前用时减掉累计起点,所以示例里第 1 圈是 00:00:12.50 而不是 01:02:17.50。
为什么显示的最后两位是厘秒而不是毫秒?
厘秒就是 10 毫秒,是计时显示的通行档位:既能看出「在走」,又不会因为末位每秒变一百次而闪成一团。内部仍按毫秒保存,暂停再继续不会丢这部分精度。
键盘快捷键为什么有时候没反应?
因为光标停在输入框里。空格、L、R 在不聚焦输入控件时才生效,否则你填累计起点时按空格会被当成快捷键。想用快捷键先点一下页面空白处,或按 Tab 把焦点移出输入框。
数据会上传吗?刷新后记录还在吗?
不会上传,全部运算都在浏览器里完成,没有任何网络请求。但本页也不做本地存储:刷新后计时按输入框里的累计起点重新开始,计次表回到演示数据。要留下记录请先「复制计次表」或「导出 CSV」。
相关工具
- 时薪计时器记录:把计到的时长乘以时薪算出这一段值多少钱。
- 工时表生成器:按天或按周汇总工时,计完一段贴进去即可。
- 在线计分板:只记分不记时,多人对抗时比拿计时器兼着记分清楚。
- 点击统计计数统计:把「次数」单独抽出来统计时用它。
- 打字速度测试:同样基于时间测量,测的是每分钟输入多少字符。
- 在线记事本:计时过程中要随手记几笔,比在计时器里塞注释省事。
- 在线秒表:同样记分段与圈速,但侧重单次冲刺的高精度读取。
- 番茄钟计时器:固定周期自动换挡,不需要手动重开。
- 实用工具:查看全部实用工具。
需要从设定时长往回走(倒计时)、需要到点反复响铃的场景,本页不承担。