农历显示错误说明 & OTA 升级指引

2025-05-01

—— 祝大家五一劳动节快乐!—

各位朋友大家好,不知道在 4 月 27 日之后你有没有发现时钟的农历日期不对,先说下,这是一个软件BUG,目前已经修复。


事情经过

4月28日 收到一个用户反馈:“农历显示比实际多 1 天”。当时还怀疑是否真的有问题,经过验证确认了的确农历计算出错。当天查明了原因,修复并发布了新版本。


哪些设备会受到影响?

我们这边带农历的时钟都会存在这个问题。现象:农历日期显示比正常的多1 天,例如 4 月 27 日应为 三月三十 却显示 四月初一。


如何解决

  1. 影响时间段:20250427-20250526(5月26日后会恢复正常),所以影响不大的话等到5月27日就恢复正常了。
  2. 升级到1.9.x版本(WHEN时钟),如果有使用农历的用户联系我们进行升级,升级方法见文章后。
不使用农历的用户建议等到2.0.x,目前正在推进,计划5月中旬会发布。这次更新最重要的一个功能是增加了可选的登录密码机制,如下图: 密码设置界面

该问题广泛存在

这是一个广泛存在于各种设备中的BUG,比如万年历、钟表、考勤机等。

有农历显示的设备大家都可以确认下,我这边在网上搜了下,不少手机也中招了。

其他设备农历显示问题截图

技术原因及农历算法的来龙去脉

本段是给对技术考古、嵌入式开发感兴趣的读者准备的。

现象:
2025-04-27 ~ 2025-05-26 期间,农历比实际 +1 天。

直接原因:
经典的 “三字节年码” 农历算法其中的1个比特位错误。

三字节年码来历:
农历不是简单的偏差,需要复杂的计算才能得出,由于早期MCU资源限制无法直接进行计算,有人就提出既然 1901-2099 的农历早已有表,何不一次“烤”进 ROM?这就是“三字节年码表”算法的出发点,使用查表方法,避免复杂的浮点运算和存储占用。

据不完全不确定的考证:

时间资料 / 人物里程碑
1994《电脑编程技巧与维护》杂志发表了一篇用 4 byte×199 年储存农历的 Turbo C 代码
20028052.com / 电子工程大厦论坛网友 Campo 发布“3 字节农历年码 + C 例程”,标题含“仅 600 字节”
2004-2007各 MCU 方案商把该代码嵌入“电子万年历”“时钟语音芯片”DEMO,形成多条派生版本
2010 以后Arduino/ESP8266 中文社区再次流行,GitHub 出现十余个 fork

至此,“3 字节 × 199 年”几乎成了农历计算的业界默认实现方式。

以下原因导致潜在的风险:

  1. 手动计算整理:任何一位错写都会造成整月 +1/-1 的级联偏差。
  2. 延迟曝露:错位往往在10-20 年后才显现(如 2025、2033、2093)。
  3. 分叉难追溯:论坛时代的多次“热心修订”导致A表修2033、B表修2025,下游很难分辨对错。

继承下来的、大家都在使用的算法表,基本就没人再会去花精力去校对了。

很不巧,大家都在使用的表真的就有数据错误!


这边整理了下影响到的年份

年份届时可能存在的问题
2033闰月号写成闰十一 → “2033 Bug” 出现 8 个月错位
2025三月/四月大小月颠倒 → 三月三十 被显示成 四月初一
2036闰月号错误 → 6 月起农历全部错 1 月
2091春节日码 +1 → 春节显示 2 月 1 日而非 1 月 31 日
2093闰月号错误 → 冬季整月错位

直到今年才开始集中暴露出来,可以OTA的设备还好,但一些老旧设备,无人维护或无法升级的就没有办法了。不过好在是只是影响了农历的一个月时间,也不会造成太严重的后果。


为什么花不少精力来梳理这个"小BUG"事故

这段年码表被我直接用在项目里,如今轮到自己产品“中招”,不查清根因就无法彻底补漏。

这是一个很小的bug,却能潜伏十几年,遗留到了现在。可以预见如果这个错误没有被广泛获知,未来还会有更多的设备继续延用未修正过的代码。

这不是哪一家厂商的独家事故,而是“复制-粘贴文化”的缩影。

再次印证那句——“世界就是个草台班子”

小团队资源有限,被迫“拿来主义”还能理解。可资源、流程、QA 看似完备的大厂,遇到一段“能跑”的旧代码,也是复制 → 集成 → 量产 ,缺乏有效的验证测试。

想到了以前工作听到的一句话:要对技术有敬畏,做产品如履薄冰。


回到自家产品,如何OTA升级?

OTA升级指引