农历显示错误说明 & OTA 升级指引
—— 祝大家五一劳动节快乐!—
各位朋友大家好,不知道在 4 月 27 日之后你有没有发现时钟的农历日期不对,先说下,这是一个软件BUG,目前已经修复。
事情经过
4月28日 收到一个用户反馈:“农历显示比实际多 1 天”。当时还怀疑是否真的有问题,经过验证确认了的确农历计算出错。当天查明了原因,修复并发布了新版本。
哪些设备会受到影响?
我们这边带农历的时钟都会存在这个问题。现象:农历日期显示比正常的多1 天,例如 4 月 27 日应为 三月三十 却显示 四月初一。
如何解决
- 影响时间段:20250427-20250526(5月26日后会恢复正常),所以影响不大的话等到5月27日就恢复正常了。
- 升级到1.9.x版本(WHEN时钟),如果有使用农历的用户联系我们进行升级,升级方法见文章后。

该问题广泛存在
这是一个广泛存在于各种设备中的BUG,比如万年历、钟表、考勤机等。
有农历显示的设备大家都可以确认下,我这边在网上搜了下,不少手机也中招了。

技术原因及农历算法的来龙去脉
本段是给对技术考古、嵌入式开发感兴趣的读者准备的。
现象:
2025-04-27 ~ 2025-05-26 期间,农历比实际 +1 天。
直接原因:
经典的 “三字节年码” 农历算法其中的1个比特位错误。
三字节年码来历:
农历不是简单的偏差,需要复杂的计算才能得出,由于早期MCU资源限制无法直接进行计算,有人就提出既然 1901-2099 的农历早已有表,何不一次“烤”进 ROM?这就是“三字节年码表”算法的出发点,使用查表方法,避免复杂的浮点运算和存储占用。
据不完全不确定的考证:
| 时间 | 资料 / 人物 | 里程碑 |
|---|---|---|
| 1994 | 《电脑编程技巧与维护》杂志 | 发表了一篇用 4 byte×199 年储存农历的 Turbo C 代码 |
| 2002 | 8052.com / 电子工程大厦论坛 | 网友 Campo 发布“3 字节农历年码 + C 例程”,标题含“仅 600 字节” |
| 2004-2007 | 各 MCU 方案商 | 把该代码嵌入“电子万年历”“时钟语音芯片”DEMO,形成多条派生版本 |
| 2010 以后 | Arduino/ESP8266 中文社区 | 再次流行,GitHub 出现十余个 fork |
至此,“3 字节 × 199 年”几乎成了农历计算的业界默认实现方式。
以下原因导致潜在的风险:
- 手动计算整理:任何一位错写都会造成整月 +1/-1 的级联偏差。
- 延迟曝露:错位往往在10-20 年后才显现(如 2025、2033、2093)。
- 分叉难追溯:论坛时代的多次“热心修订”导致A表修2033、B表修2025,下游很难分辨对错。
继承下来的、大家都在使用的算法表,基本就没人再会去花精力去校对了。
很不巧,大家都在使用的表真的就有数据错误!
这边整理了下影响到的年份
| 年份 | 届时可能存在的问题 |
|---|---|
| 2033 | 闰月号写成闰十一 → “2033 Bug” 出现 8 个月错位 |
| 2025 | 三月/四月大小月颠倒 → 三月三十 被显示成 四月初一 |
| 2036 | 闰月号错误 → 6 月起农历全部错 1 月 |
| 2091 | 春节日码 +1 → 春节显示 2 月 1 日而非 1 月 31 日 |
| 2093 | 闰月号错误 → 冬季整月错位 |
直到今年才开始集中暴露出来,可以OTA的设备还好,但一些老旧设备,无人维护或无法升级的就没有办法了。不过好在是只是影响了农历的一个月时间,也不会造成太严重的后果。
为什么花不少精力来梳理这个"小BUG"事故
这段年码表被我直接用在项目里,如今轮到自己产品“中招”,不查清根因就无法彻底补漏。
这是一个很小的bug,却能潜伏十几年,遗留到了现在。可以预见如果这个错误没有被广泛获知,未来还会有更多的设备继续延用未修正过的代码。
这不是哪一家厂商的独家事故,而是“复制-粘贴文化”的缩影。
再次印证那句——“世界就是个草台班子”
小团队资源有限,被迫“拿来主义”还能理解。可资源、流程、QA 看似完备的大厂,遇到一段“能跑”的旧代码,也是复制 → 集成 → 量产 ,缺乏有效的验证测试。
想到了以前工作听到的一句话:要对技术有敬畏,做产品如履薄冰。
回到自家产品,如何OTA升级?
