feat(lunar): 双端农历换算层(Go + TS,同作者同算法)
日历要支持「每农历月十五」「农历生日」这类规则。公历与农历的换算不能
自己算,两端各引一个库:Go 用 6tail/lunar-go v1.4.6,前端用同作者的
lunar-javascript 1.7.7 —— 同算法保证两端结果一致(前端要在格子上显示
农历日、在编辑器里预览接下来几次触发)。
为什么要包一层而不直接用库:
**1. 库在非法日期上 panic 而不是返回 error。**
`NewLunarFromYmd(2027, 9, 30)` 直接 panic("only 29 days in lunar year
2027 month 9")。农历月是 29 或 30 天不定,「每月农历三十」这条规则必然
撞上短月份。调度器里一次 panic 就让那条提醒永久卡住。
修法是夹到该月实际天数并返回 clamped 标记 —— 夹而不滚:「每月三十」的
语义是「月末那天」,滚到下月初一会让提醒与前一次只隔一天。
**2. 闰月用负数月份表示**(-6 = 闰六月),这个约定藏在库内部。
2025 有闰六月、2028 有闰五月,2026/2027 没有。AddYears 从闰月出发而
目标年没有同一闰月时退回正月份 —— 静默让重复事件消失更糟。
**3. 按农历推进不能加固定天数。**
农历月 29~30 天、农历年 353~385 天(闰年多一整月),AddDate 近似一年
能偏半个月。
前端另有一个 TS 陷阱:日名有五种前缀形态(初一/十一/二十/廿一/三十),
原来用正则从 toString() 截取时漏了「二十」,20 号会显示整串「七月二十」。
改成查表。
测试:Go 12 例 / TS 37 例。含「同一农历日在六年公历里落到至少 4 个不同
月日上」—— 那正是农历重复存在的理由(公历 yearly 会固定在同一天)。
This commit is contained in:
@ -8,13 +8,14 @@
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"test": "node test/markdown-xss.test.mjs && node test/narrow-layout.test.mjs && vitest run",
|
||||
"test": "node test/markdown-xss.test.mjs && node test/narrow-layout.test.mjs && node test/theme.test.mjs && vitest run",
|
||||
"test:narrow": "node test/manual/narrow-verify.mjs",
|
||||
"test:wide": "node test/manual/wide-regression.mjs",
|
||||
"test:components": "vitest run",
|
||||
"test:watch": "vitest"
|
||||
},
|
||||
"dependencies": {
|
||||
"lunar-javascript": "1.7.7",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-markdown": "^9.0.1",
|
||||
|
||||
Reference in New Issue
Block a user