测试:新增 sys_clock 主机侧单测并修复 Zeller 星期缺陷
This commit is contained in:
+29
-19
@@ -62,24 +62,41 @@ static volatile uint32_t s_base_unix_secs = UINT32_MAX;
|
||||
/*
|
||||
* 函数功能:根据公历日期计算星期几
|
||||
* 入口参数:y - 年份 uint16_t 1970~2099
|
||||
* m - 月份 uint8_t 1~12
|
||||
* m - 月份 uint8_t 1~12(**1-based**,与 sd2506_time_t.month 一致)
|
||||
* d - 日 uint8_t 1~31
|
||||
* 返回值:星期编号 uint8_t 0=Sunday, 1=Monday, ... 6=Saturday
|
||||
* 限定条件:输入为公历合法日期
|
||||
* 函数说明:1. 采用 Zeller 公式(变种),结果 0 表示周日
|
||||
* 2. 与 unix_to_sd2506() 内星期算法保持一致
|
||||
* 函数说明:1. 采用 Zeller 同余式(Gregorian):
|
||||
* h = (d + ⌊13(m+1)/5⌋ + K + ⌊K/4⌋ + ⌊J/4⌋ + 5J) mod 7
|
||||
* 其中 mm 为调整月(1/2 月按上年 13/14 月处理),
|
||||
* K = wy % 100,J = wy / 100;h: 0=Saturday, 1=Sunday, ...
|
||||
* 结果映射 (h+6) mod 7 → 0=Sunday(sd2506 约定)。
|
||||
* 注:5J ≡ -2J (mod 7),取 5J 以保证各项非负(无符号安全)。
|
||||
* 2. 与 unix_to_sd2506() 内星期算法保持一致(后者按 0-based 月
|
||||
* 调用本函数前 +1,切勿再传 0-based 月)。
|
||||
* 修改记录:
|
||||
* 2026-10-02 修正:原式错用 (wy%100 + wy/100/4 - wy/100/15)(缺 K/4、
|
||||
* 5J/世纪项,且把 1-based 月当 2-based 用),实测 1970~2099
|
||||
* 全部日期星期皆错(主机侧单测 TC-CLK-014/019 发现)。
|
||||
*/
|
||||
static uint8_t rtc_calc_week(uint16_t y, uint8_t m, uint8_t d) {
|
||||
uint32_t wy = y;
|
||||
uint32_t wm = m;
|
||||
uint32_t wm = m; /* wm: 1-based 月,1/2 月上调为 13/14 月 */
|
||||
|
||||
if (wm <= 2) {
|
||||
if (wm <= 2u) {
|
||||
wy--;
|
||||
wm += 12u;
|
||||
}
|
||||
/* Zeller 公式:世纪项 + 月项 + 日项,模 7 得星期(0=周日) */
|
||||
return (uint8_t)(((uint32_t)(wy % 100u + wy / 100u / 4u - wy / 100u / 15u) +
|
||||
(uint32_t)((26u * (wm + 1u)) / 10u) + (uint32_t)(d % 100u)) % 7u);
|
||||
|
||||
{
|
||||
uint32_t K = wy % 100u;
|
||||
uint32_t J = wy / 100u;
|
||||
uint32_t h;
|
||||
/* 各项均非负:d + 月项 + K + K/4 + J/4 + 5J,模 7 得 0=Saturday */
|
||||
h = (uint32_t)(d + (13u * (wm + 1u)) / 5u + K + K / 4u + J / 4u + 5u * J) % 7u;
|
||||
/* h:0=Sat,1=Sun,... → 0=Sun 约定 */
|
||||
return (uint8_t)((h + 6u) % 7u);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -136,17 +153,10 @@ static void unix_to_sd2506(uint32_t unix_secs, sd2506_time_t *p_sd_time) {
|
||||
}
|
||||
d = (uint32_t)(day_count + 1uL);
|
||||
|
||||
/* 星期(Zeller's congruence,0=Sunday) */
|
||||
uint64_t wy = y;
|
||||
uint64_t wm = m;
|
||||
if (wm <= 2) {
|
||||
wy--;
|
||||
wm += 12uL;
|
||||
}
|
||||
/* Zeller 公式同 rtc_calc_week():世纪项 + 月项 + 日项,模 7 得星期(0=周日) */
|
||||
uint8_t week = ((uint32_t)(wy % 100uLL + wy / 100uLL / 4uLL - wy / 100uLL / 15uLL) +
|
||||
(uint32_t)(((uint64_t)26 * (wm + 1uL)) / 10uLL) +
|
||||
(uint32_t)(d % 100uLL)) % 7uLL;
|
||||
/* 星期:复用 rtc_calc_week()(1-based 月;此处 m 为 0-based → 传 m+1)
|
||||
* 2026-10-02 修正:原内联变种公式有误(与 rtc_calc_week 同缺陷),
|
||||
* 统一收敛到 rtc_calc_week,避免两处算法再次发散。 */
|
||||
uint8_t week = rtc_calc_week((uint16_t)y, (uint8_t)(m + 1u), (uint8_t)d);
|
||||
|
||||
/* sd2506_time_t.year 采用完整年份(如 2026),与 sd2506_set_time
|
||||
* 中 year-2000、sd2506_get_time 中 +2000 的约定保持一致;
|
||||
|
||||
Reference in New Issue
Block a user