HarmonyOS应用《玄象》开发实战:LunarCalendar.getTodayHeavenlyStems 干支计算在首页的接入
阅读时长约 19 分钟 | 难度★★★★☆ | 篇章第 3 篇 · 首页与功能导航 对应源码entry/src/main/ets/common/utils/LunarCalendar.ets、HeavenlyStems.ets前言玄象项目首页顶部标题栏的“甲辰年│肖龙“不是硬编码文本而是通过LunarCalendar.getTodayGanZhi()实时计算的今日干支。这一功能背后是玄象项目LunarCalendar工具类与HeavenlyStems工具类的协同。本篇将深入剖析玄象项目首页干支数据的计算与展示链路从LunarCalendar.getTodayGanZhi方法实现、HeavenlyStems.getYearGanZhi干支推算算法、aboutToAppear数据初始化到State绑定与 UI 展示。掌握这套干支计算接入方法论您就能为任何 HarmonyOS 应用接入实时数据。提示干支计算是玄象项目的核心算法之一涉及天干地支组合、五行属性、生肖推算等复杂逻辑。一、干支数据接入链路1.1 完整数据流用户打开首页 ↓ HomePage.aboutToAppear() ↓ LunarCalendar.getTodayGanZhi() ↓ HeavenlyStems.getYearGanZhi(year) ↓ HeavenlyStems.getShengXiao(year) ↓ 返回 甲辰年│肖龙 ↓ State todayGanZhi 甲辰年│肖龙 ↓ UI 渲染 Text(this.todayGanZhi)1.2 首页接入代码// HomePage.ets State todayGanZhi: string ; aboutToAppear(): void { this.todayGanZhi LunarCalendar.getTodayGanZhi(); const yiji LunarCalendar.getTodayYiJi(); this.yiItems yiji.yi; this.jiItems yiji.ji; } build() { Column() { Row() { // ... Column({ space: 4 }) { Text(玄象) Text(this.todayGanZhi) // ← 展示干支 } } } }二、LunarCalendar.getTodayGanZhi 方法2.1 完整源码static getTodayGanZhi(): string { const now new Date(); const year now.getFullYear(); const month now.getMonth() 1; const day now.getDate(); const ganZhi HeavenlyStems.getYearGanZhi(year); const shengXiao HeavenlyStems.getShengXiao(year); return ${ganZhi}年 | 肖${shengXiao}; }2.2 方法分解步骤操作结果1new Date()获取当前时间2now.getFullYear()20263HeavenlyStems.getYearGanZhi(2026)“丙午”4HeavenlyStems.getShengXiao(2026)“马”5字符串拼接“丙午年│肖马”2.3 模板字符串return ${ganZhi}年 | 肖${shengXiao};玄象项目使用 ES6 模板字符串将干支与生肖拼接为展示格式。三、HeavenlyStems 工具类3.1 完整源码export class HeavenlyStems { static readonly STEMS: string[] [甲, 乙, 丙, 丁, 戊, 己, 庚, 辛, 壬, 癸]; static readonly BRANCHES: string[] [子, 丑, 寅, 卯, 辰, 巳, 午, 未, 申, 酉, 戌, 亥]; static readonly SHENGXIAO: string[] [鼠, 牛, 虎, 兔, 龙, 蛇, 马, 羊, 猴, 鸡, 狗, 猪]; static getStem(index: number): string { return HeavenlyStems.STEMS[index % 10]; } static getBranch(index: number): string { return HeavenlyStems.BRANCHES[index % 12]; } static getYearGanZhi(year: number): string { const stemIndex (year - 4) % 10; const branchIndex (year - 4) % 12; return ${HeavenlyStems.STEMS[stemIndex]}${HeavenlyStems.BRANCHES[branchIndex]}; } static getShengXiao(year: number): string { const index (year - 4) % 12; return HeavenlyStems.SHENGXIAO[index]; } static getFiveElement(stem: string): string { const map: Recordstring, string { 甲: 木, 乙: 木, 丙: 火, 丁: 火, 戊: 土, 己: 土, 庚: 金, 辛: 金, 壬: 水, 癸: 水 }; return map[stem] || ; } }3.2 数据常量常量长度内容STEMS10甲、乙、丙、丁、戊、己、庚、辛、壬、癸BRANCHES12子、丑、寅、卯、辰、巳、午、未、申、酉、戌、亥SHENGXIAO12鼠、牛、虎、兔、龙、蛇、马、羊、猴、鸡、狗、猪3.3 干支推算算法getYearGanZhi 方法static getYearGanZhi(year: number): string { const stemIndex (year - 4) % 10; const branchIndex (year - 4) % 12; return ${HeavenlyStems.STEMS[stemIndex]}${HeavenlyStems.BRANCHES[branchIndex]}; }算法原理公元 4 年是甲子年天干索引 0 地支索引 0。year 2026 stemIndex (2026 - 4) % 10 2022 % 10 2 → 丙 branchIndex (2026 - 4) % 12 2022 % 12 6 → 午 结果丙午getShengXiao 方法static getShengXiao(year: number): string { const index (year - 4) % 12; return HeavenlyStems.SHENGXIAO[index]; }算法原理公元 4 年是鼠年索引 0。year 2026 index (2026 - 4) % 12 2022 % 12 6 → 马3.4 五行属性映射static getFiveElement(stem: string): string { const map: Recordstring, string { 甲: 木, 乙: 木, 丙: 火, 丁: 火, 戊: 土, 己: 土, 庚: 金, 辛: 金, 壬: 水, 癸: 水 }; return map[stem] || ; }玄象项目使用Recordstring, string映射表存储天干与五行属性天干五行甲、乙木丙、丁火戊、己土庚、辛金壬、癸水四、LunarCalendar 工具类4.1 农历数据编码private static readonly LUNAR_INFO: number[] [ 0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, // ... 1900-2100 年共 201 个 ];玄象项目使用位编码存储农历年份信息0x04bd8 0b 0000 0100 1011 1101 1000 ↑ ↑↑↑↑ ↑↑↑↑↑↑↑↑↑↑↑ 闰月位置 12 个月份天数30/294.2 农历月份天数算法static getLunarMonthDays(year: number, month: number): number { return (LunarCalendar.LUNAR_INFO[year - 1900] (0x10000 month)) ? 30 : 29; }0x10000 month移位到对应月份位。操作判断该月是否为 30 天1 表示 30 天0 表示 29 天。4.3 农历月名与日名static readonly MONTH_NAMES: string[] [ 正月, 二月, 三月, 四月, 五月, 六月, 七月, 八月, 九月, 十月, 冬月, 腊月 ]; static readonly DAY_NAMES: string[] [ 初一, 初二, ..., 三十 ];五、aboutToAppear 中初始化数据5.1 初始化时机aboutToAppear(): void { this.todayGanZhi LunarCalendar.getTodayGanZhi(); const yiji LunarCalendar.getTodayYiJi(); this.yiItems yiji.yi; this.jiItems yiji.ji; }玄象项目在aboutToAppear中同步初始化首页数据确保 UI 首次渲染时数据已就绪。5.2 同步 vs 异步玄象项目getTodayGanZhi()是同步方法无需等待aboutToAppear 开始 ↓ getTodayGanZhi() ← 同步计算毫秒级完成 ↓ 赋值给 State ↓ build 首次渲染数据已就绪六、State todayGanZhi 绑定6.1 状态定义State todayGanZhi: string ;6.2 UI 绑定Text(this.todayGanZhi) .fontSize(14) .fontColor(Colors.TEXT_SECONDARY)State绑定让 UI 在数据变化时自动更新。6.3 更新时机用户首次打开首页aboutToAppear中初始化。页面从后台切到前台onPageShow中刷新。onPageShow(): void { this.todayGanZhi LunarCalendar.getTodayGanZhi(); }七、GetTodayYiJi 宜忌数据7.1 方法调用const yiji LunarCalendar.getTodayYiJi(); this.yiItems yiji.yi; this.jiItems yiji.ji;7.2 YiJi 接口export interface YiJi { yi: string[]; ji: string[]; }八、干支显示的视觉设计8.1 视觉格式丙午年│肖马字号14vp颜色Colors.TEXT_SECONDARY对齐居中8.2 符号设计玄象项目使用│竖线分隔干支与生肖简洁大方。九、干支计算的扩展9.1 月干支static getMonthGanZhi(year: number, month: number): string { const stemIndex ((year - 4) * 2 month) % 10; const branchIndex (month 2) % 12; return ${HeavenlyStems.STEMS[stemIndex]}${HeavenlyStems.BRANCHES[branchIndex]}; }9.2 日干支static getDayGanZhi(year: number, month: number, day: number): string { const days this.getDaysFromBase(year, month, day); const stemIndex days % 10; const branchIndex days % 12; return ${HeavenlyStems.STEMS[stemIndex]}${HeavenlyStems.BRANCHES[branchIndex]}; }9.3 时干支static getHourGanZhi(dayGan: string, hour: number): string { const dayStemIndex HeavenlyStems.STEMS.indexOf(dayGan); const stemIndex (dayStemIndex % 5 * 2 Math.floor(hour / 2)) % 10; const branchIndex Math.floor((hour 1) / 2) % 12; return ${HeavenlyStems.STEMS[stemIndex]}${HeavenlyStems.BRANCHES[branchIndex]}; }十、玄象项目首页数据接入总结10.1 数据来源数据来源方法类型今日干支LunarCalendar.getTodayGanZhi()同步今日宜忌LunarCalendar.getTodayYiJi()同步中间状态State变量响应式10.2 数据流数据LunarCalendar→ State → UIText 数据层 ← 纯函数无副作用 状态层 ← State 响应式 UI 层 ← 自动更新总结本篇以玄象项目首页干支计算为蓝本深入剖析了数据从算法到 UI 的完整接入链路从LunarCalendar.getTodayGanZhi方法、HeavenlyStems.getYearGanZhi干支推算算法、aboutToAppear数据初始化到State绑定与 UI 展示。掌握这套数据接入方法论您就能为任何 HarmonyOS 应用接入实时计算数据。下一篇《30 · State currentTab 选中态切换与图标着色》将带您深入玄象项目首页底部导航栏的选中态交互。如果这篇文章对你有帮助欢迎点赞、收藏⭐、关注你的支持是我持续创作的动力相关资源HarmonyOS 官方文档State 装饰器HarmonyOS 官方文档Text 组件干支纪年法wikipedia.org/wiki/干支开源鸿蒙跨平台社区https://openharmonycrossplatform.csdn.net