闹钟

在浏览器里同时挂多组提醒:设定小时与分钟、选重复规则、配贪睡时长与音量,到点用 AudioContext 现场合成蜂鸣声,不加载任何外部音频文件。

本机当前时间--:--:--
最近一次闹钟—
启用中的闹钟0 组
最近一次响铃尚未响过

提示:在「小时」或「分钟」输入框里按 Enter 可直接添加;页面打开时已经有 07:00、13:30、15:00 三组示例闹钟,可直接改成你要的时间。

时间标签重复贪睡音量下次响铃操作
07:00起床每天5 分60今天 07:00
13:30午休工作日10 分60今天 13:30
15:00喝水每天关闭60今天 15:00

使用方法

  1. 页面打开时表格里已经有三组示例:07:00 起床(每天、贪睡 5 分钟)、13:30 午休(工作日、贪睡 10 分钟)、15:00 喝水(每天、不贪睡),三组音量都是 60。可以直接把它们改成你要的时间,也可以全部删掉重建。
  2. 新增一组:先在「小时」填 0~23 的整数、「分钟」填 0~59 的整数,再写一个不超过 20 字的标签(例如「站起来活动」),然后选重复规则、贪睡时长和音量,点「添加提醒」。在小时或分钟输入框里直接按 Enter 也能添加。
  3. 「重复规则」有四档:仅一次只响一次,响完自动停用;每天每天都响;工作日只在周一至周五响;周末只在周六、周日响。判定依据是浏览器给出的本机星期(0 表示周日)。
  4. 表格里的「下次响铃」直接告诉你这组提醒下一次会在什么时候触发,用「今天 / 明天 / 周几 + 时刻」表示;倒计时数字每秒刷新一次,可以核对是不是和你想的一致。
  5. 到点后页面上方会出现红色提示条并循环蜂鸣。点停止响铃结束;点贪睡会按这组提醒设定的贪睡时长,在「当前时刻 + N 分钟」处临时插入一组新提醒,原来那一组的时间点不受影响。
  6. 「试听蜂鸣」只响一声,用来确认设备音量和浏览器音频是否正常,不会写入任何提醒记录;「导出 CSV」把整张表存成带 BOM 的 .csv;「复制对照表」把当前清单以 TSV 复制到剪贴板。

这个闹钟能解决什么问题

一是电脑前的时间锚点。长时间盯屏幕的人最需要的不是「几点起床」,而是「什么时候该停一下」——写代码、写方案、开长会的时候,抬头发现在椅子上坐了三个小时是常态。把几组提醒常驻在这个页面上,比在手机上单独设一个提醒更顺手,因为工作时注意力本来就在电脑上。

二是设备自带的定时功能不好表达的多组规则。手机自带的提醒通常一次只能选「每天」或某几天,而这里的重复规则是明确定义的四种,工作日与周末分开处理,不用手动去勾五个开关;一套规则配好就能长期挂在那,不用每天重设。

三是不需要安装、不需要任何权限。本页不申请通知权限、不读通讯录、不常驻后台进程,它是一个网页,关掉就彻底结束,不会在系统托盘里留东西。

四是配合会议、课堂、实验做限时提示。测试环境里定时提醒、直播前的准备时间、动手实验的计时节点,都可以用「仅一次」加一个长标签表达,到点蜂鸣提醒,不用盯着时钟。

本页不做这些事:不推送系统级通知、不在页面关闭后继续跑、不跨设备同步、不解析自然语言(「明早七点」这类描述请自己换算成 07:00)。所有数据只写在本机浏览器的 localStorage 里。

报时原理:轮询比对、半开区间与 AudioContext 蜂鸣

核心是一个每秒触发一次的 setInterval,但它不靠 tick 次数报时。很多用 setInterval 写的闹钟会把「触发了多少次」累加起来当时间用,这是错的:定时器只能保证「不早于」指定间隔,实际每次都会晚一点点。实测统计里常见 1~5 毫秒的抖动,按每次晚 5 毫秒算,3600 次(1 小时)就累计到 18 秒,24 小时能差 7.2 分钟。本页每一跳都直接读 new Date(),拿到的永远是本机真实时间,不累加任何计数。

判定用的是半开区间 (上次检查时刻, 本次检查时刻]。每一跳把「上一跳的时间戳」到「这一跳的时间戳」当成一个窗口,再看每组提醒在这个窗口里是否正好有一个触发点:命中就响,没命中就等下一跳。这样做有两个好处——同一分钟之内无论轮询触发多少次都不会重复响(因为窗口不重叠),而浏览器把后台标签页的定时器节流到每分钟一次、或者系统睡眠把整个进程冻住一段时间之后,恢复时那一跳的窗口会自动变宽,把漏掉的整分钟补回来,而不是像「当前秒数等于 0」那样直接错过。

蜂鸣声是现场合成的,没有任何音频文件。代码用 OscillatorNode 产生一个正弦波,频率固定为 880 Hz——这是十二平均律里的 A5(MIDI 音高 81),由 440 × 2(81−69)/12 算出;拿它当提醒音,是因为 880 Hz 落在听觉最敏感的 2~5 kHz 区间下方一点,穿透力足够又不像高频啸叫那样刺耳。音量由一个 GainNode 控制,包络是「0.0001 → 目标音量 → 0.0001」的指数渐变,单响持续 0.35 秒,然后停 0.25 秒,每 600 毫秒循环一次,所以一分钟内最多响 100 声。

音量 0~100 映射到增益 0~0.5。映射式是 gain = 音量 ÷ 100 × 0.5,所以默认的 60 对应 0.3。上限刻意只到 0.5 而不是 1.0:网页合成音在接近满幅时很容易削波,听起来反而更吵更糊,留一半余量既安全又不失真。音量填 0 时只会亮红色提示条,只是不发声。

音频需要一次用户手势才能解锁。所有现代浏览器都有自动播放限制:页面在没有用户交互前不允许出声,AudioContext 会停在 suspended 状态。本页在你第一次点击任意按钮(包括「添加提醒」和「试听蜂鸣」)时创建并 resume() 音频上下文,之后才会真正发声。这也解释了为什么刚打开页面就撞上整点,可能只弹提示条没有声音。

贪睡不是改写原来那一组,而是临时插入一组。点「贪睡」时,脚本用当前时间加上该组的贪睡分钟数,生成一组新的「仅一次」提醒,标签前面加「贪睡 · 」。原来那组每日提醒保持原样,所以明天同一时间照样会响。

完整示例(数值仅作演示)

示例条件是页面打开时的默认状态:三组提醒分别是 07:00 / 每天 / 贪睡 5 分钟、13:30 / 工作日 / 贪睡 10 分钟、15:00 / 每天 / 不贪睡,音量 60。假设现在是 06:59:30:

重复规则、蜂鸣参数与频率对照表

第一张表是四种重复规则的覆盖范围。判断依据是 JavaScript Date.getDay() 的返回值:0 是周日、1 是周一……6 是周六。「工作日」取 1~5,「周末」取 0 和 6。

重复规则触发星期每周次数每月约典型用途
仅一次不限,响过即停用1—会议、实验、直播前的单次提醒
每天日 一 二 三 四 五 六730.0 次起床、吃药、喝水
工作日一 二 三 四 五521.4 次上班打卡、站会、午休
周末六 日28.6 次周末课程、家庭安排

第二张表是蜂鸣用到的音高。所有频率都按十二平均律 f = 440 × 2(MIDI − 69)/12 计算,半音之间的比值是 21/12 ≈ 1.059463。本页只用其中最高那一档。

音名MIDI频率说明
A469440.00 Hz国际标准音,钢琴中央 C 上方的 A
C572523.25 Hz比 A4 高三个半音
E576659.26 Hz常用于提示音的柔和档
G579783.99 Hz接近本页选用的音高
A5(本页)81880.00 Hz正好是 440 Hz 的两倍,一个周期 1.136 毫秒
C6841046.50 Hz再高一档,部分人会觉得偏尖

输入范围、边界与误差说明

常见问题

关掉页面之后闹钟还会响吗?

不会。本页的全部逻辑跑在当前页面里,关掉标签页或浏览器,计时和蜂鸣就一起停了,也不会留下任何后台进程。需要「关掉也响」的场景请用手机或电脑自带的时钟应用,它们由操作系统调度。

标签页切到后台,会不会错过整点?

不会漏。判定用的是「上一跳的时间戳到这一跳的时间戳」这个半开区间,浏览器把隐藏标签页的定时器节流到每分钟一次之后,那一跳的窗口会覆盖被节流的整段时间,区间里落着的触发点会被补上。代价是响铃的准点性变差,最多可能晚几十秒——但不会不响。

为什么刚打开页面时到点只亮提示条、不出声?

浏览器的自动播放策略要求页面先收到一次用户交互,AudioContext 才能从 suspended 变成 running。本页在你第一次点任意按钮时创建并恢复音频上下文,之后才会真正发声。想提前确认,可以点一次「试听蜂鸣」。

点「贪睡」会改掉原来那组提醒吗?

不会。贪睡是在「当前时间 + 该组的贪睡分钟数」处插入一组新的「仅一次」提醒,标签前面加上「贪睡 · 」,原来那组提醒的重复规则完全不动,明天同一时间照响。贪睡填 0 的提醒按下去就只是停止当前这次响铃。

一次会响多久?怎么停下来?

一直响,直到你点「停止响铃」,或者关掉页面。循环周期是 600 毫秒:0.35 秒的发声加 0.25 秒的静音,也就是每分钟最多 100 声。这样设计的目的是避免「响一声你没听见就过去了」,但正常使用时建议尽快点停止。

为什么用每秒轮询,而不是直接算好时间用 setTimeout?

因为 setTimeout 只保证「不早于」目标时间,页面被冻结或系统休眠后会一次性延迟触发,醒来时可能已经在几分钟之后,且没有机会补响。轮询加区间判定既不会因为定时器抖动而漏掉,也不会因为页面恢复而重复触发,行为更好预测。

蜂鸣为什么定在 880 Hz?能换成别的音吗?

880 Hz 是十二平均律的 A5,正好是标准音 A4 的两倍频。它落在人耳较敏感的区域下方一点,穿透办公环境的背景噪声足够,又不像 2 kHz 以上那样容易让人烦躁。本页把它写死为一个常数,所有提醒共用;想区分不同的组,可以给每组设不同音量。

音量填 100 是不是最大声?和系统音量什么关系?

不是。音量 0~100 只映射到网页音频的增益 0~0.5(100 对应 0.5),最终响多大还要乘上系统的输出音量。这样映射是为了留一半余量避免削波失真。想让声音更大,请调设备的音量键,或者把播放设备切到音箱。

相关工具