diff --git a/comparison-yijing.md b/comparison-yijing.md deleted file mode 100644 index 5fb0d01..0000000 --- a/comparison-yijing.md +++ /dev/null @@ -1,227 +0,0 @@ -# 易经占卜分析报告 - -**占卜者:** 午饭 -**生成时间:** 2025/8/21 19:09:13 -**分析类型:** 易经占卜 - ---- - -## ❓ 占卜问题 - -**问题:** 午饭 - -**起卦方法:** 梅花易数时间起卦法 - -**占卜时间:** 2025/8/21 19:09:13 - -**问题类型:** 综合运势 - -**关注重点:** 整体发展、综合状况、全面分析 - -## 🔮 卦象信息 - -### 主卦 - -**卦名:** 困 -**卦象:** -_ _ -___ -_ _ -_ _ -_ _ -___ -**卦序:** 第47卦 - -### 变卦 - -**卦名:** 兑 -**卦象:** -_ _ -___ -___ -_ _ -___ -___ - -### 八卦结构 - -**上卦:** 兑 (泽) -**下卦:** 坎 (水) - -### 动爻 - -**动爻位置:** 1爻 - -## 📜 卦辞分析 - -### 卦象含义 - -【困卦】第47卦 - 困穷,困境,困顿 - -### 彖传 - -> 【彖传】曰:亨,贞,大人吉,无咎。有言不信。 - -### 象传 - -> 【象传】曰:泽无水,困。君子以致命遂志。 - -### 八卦组合分析 - -上卦兑(泽)代表悦,下卦坎(水)代表陷。泽在上,水在下,形成兑坎的组合,象征着特殊的能量组合,需要深入分析。 - -### 五行分析 - -**upper_element:** 金 -**lower_element:** 水 -**relationship:** 金生水,相生有利 -**balance:** 五行相生,和谐发展,有利于事物的成长 - -## 🔄 动爻分析 - -**动爻数量:** 1爻 - -## 🔀 变卦分析 - -### 变卦含义 - -兑悦,喜悦,和悦 - -### 转化洞察 - -从【困】到【兑】的变化,预示着事态将从困穷,困境,困顿转向兑悦,喜悦,和悦,这是一个重要的转折点。需要适应这种变化,调整策略和心态。 - -### 变化指导 - -变卦指示:充满喜悦和和谐的氛围。保持和悦态度,增进人际和谐。 - -### 时机把握 - -变化的速度适中,需要保持关注 - -## 🔍 高级分析 - -### 互卦 - 蹇 - -**卦象:** -_ _ -___ -_ _ -_ _ -_ _ -___ -**含义:** 蹇难,困难,险阻 -**分析:** 互卦【蹇】揭示了事物的内在发展趋势和隐藏因素。面临重重困难的时期。反省自身,修德养性,寻求贵人帮助。 - -### 错卦 - 坤 - -**卦象:** -_ _ -_ _ -_ _ -_ _ -_ _ -_ _ -**含义:** 接受,滋养,顺从 -**分析:** 错卦【坤】代表了相对立的状态和需要避免的方向。以柔顺和包容的态度面对挑战。通过支持他人和耐心等待,将获得成功。 - -### 综卦 - 涣 - -**卦象:** -_ _ -___ -_ _ -_ _ -___ -___ -**含义:** 涣散,离散,化解 -**分析:** 综卦【涣】显示了事物的另一面和可能的转化方向。化解涣散,重建秩序的时期。凝聚人心,重获团结。 - -### 四卦综合洞察 - -通过四卦分析:本卦【困】显示当前状态,互卦【蹇】揭示内在动力,错卦【坤】提醒对立面,综卦【涣】指示转化方向。综合来看,需要在困穷,困境,困顿的基础上,注意蹇难,困难,险阻的内在发展,避免接受,滋养,顺从的极端,向涣散,离散,化解的方向转化。 - -## 🔢 象数分析 - -### 上卦数理 - -**数字:** 2 -**含义:** 上卦数字2,对应兑卦泽象。在您的问题"午饭"中,这表示外在环境充满喜悦和交流的机会。泽象主悦,预示着通过良好的沟通和人际关系能够获得成功。 -**影响:** 外在环境呈现泽的特质,需要以悦的方式应对 - -### 下卦数理 - -**数字:** 6 -**含义:** 下卦数字6,对应坎卦水象。在您的问题"午饭"中,这表示您内心深沉而有智慧。内在动力来自于对深层真理的探索。 - -### 组合能量 - -**总数:** 8 -**解释:** 总数8在您的问题"午饭"中代表丰盛收获,是收获成果的时机。这个数字预示着您的努力将得到回报。 -**和谐度:** 上下卦差异很大,需要深度调整和耐心化解 - -### 时间共振 - -**共振等级:** 需要调和 -**时间能量:** 阴气渐盛,适合休息调养 -**最佳时机:** 对于"午饭",建议在午时(11:00-13:00)把握收获时机 - -## 🧭 五行分析 - -### 五行属性 - -**上卦五行:** 金 -**下卦五行:** 水 - -### 五行关系 - -**相互作用:** 金生水,相生有利 -**平衡状态:** 五行相生,和谐发展,有利于事物的成长 - -## ⏰ 时间分析 - -### 月相影响 - -**月相能量:** 圆满充实 -**月相建议:** 适合收获和庆祝 - -### 能量状态 - -**整体状态:** 旺盛之气与阴气渐盛相结合 -**能量建议:** 在夏季的戌时,适合积极行动,同时休息调整 - -## 🎯 针对性指导 - -### 专业分析 - -针对您关于综合运势的问题,本卦【困】在整体发展、综合状况、全面分析方面的指示是:处于困境的时期。虽处困境,但保持正道,终将脱困。。 变卦【兑】预示着在整体发展、综合状况、全面分析方面将会有所转变。 结合当前的时间因素(夏季,戌时),建议您适合积极行动。 - -## 🎯 动态指导 - -### 实用建议 - -综合来看,本卦【困】的总体指导是:"处于困境的时期。虽处困境,但保持正道,终将脱困。"。 变卦【兑】提示未来趋势:"充满喜悦和和谐的氛围。保持和悦态度,增进人际和谐。"。 - -## 🌟 易经智慧 - -### 核心信息 - -坚持正道。变化在即,喜悦和谐。 - -### 行动建议 - -保持信念,寻求突破 当前正值夏季,适合积极行动。 现在是戌时,休息调整。 考虑到即将到来的变化,建议:保持和悦,增进和谐。 - -### 时机把握 - -时机分析:晚间时光,阴气渐盛,适合思考和规划。 夏季适合积极行动。 - -## 📖 哲学洞察 - -《易经》困卦的核心智慧在于:泽中无水,象征困穷。君子应舍命达成志向。。 而变卦兑则提醒我们:两泽相连,象征喜悦。君子应与朋友讲习道义。。 《易经》告诉我们,万事万物都在变化之中,智者应该顺应这种变化,在变化中寻找机遇,在稳定中积蓄力量。 - ---- - -*本报告由神机阁AI命理分析平台生成* -*生成时间:2025/8/21 19:09:13* -*仅供参考,请理性对待* diff --git a/debug-error.txt b/debug-error.txt deleted file mode 100644 index 59b8f49..0000000 Binary files a/debug-error.txt and /dev/null differ diff --git a/AI_INTERPRETATION_GUIDE.md b/docs/AI_INTERPRETATION_GUIDE.md similarity index 100% rename from AI_INTERPRETATION_GUIDE.md rename to docs/AI_INTERPRETATION_GUIDE.md diff --git a/FRONTEND_EXPORT_SETUP.md b/docs/FRONTEND_EXPORT_SETUP.md similarity index 100% rename from FRONTEND_EXPORT_SETUP.md rename to docs/FRONTEND_EXPORT_SETUP.md diff --git a/TYPOGRAPHY_GUIDE.md b/docs/TYPOGRAPHY_GUIDE.md similarity index 100% rename from TYPOGRAPHY_GUIDE.md rename to docs/TYPOGRAPHY_GUIDE.md diff --git a/UI_OPTIMIZATION_PLAN.md b/docs/UI_OPTIMIZATION_PLAN.md similarity index 100% rename from UI_OPTIMIZATION_PLAN.md rename to docs/UI_OPTIMIZATION_PLAN.md diff --git a/server/services/baziAnalyzer.cjs b/server/services/baziAnalyzer.cjs index 02440fe..54b39f2 100644 --- a/server/services/baziAnalyzer.cjs +++ b/server/services/baziAnalyzer.cjs @@ -98,7 +98,8 @@ class BaziAnalyzer { }, bazi_chart: baziChart, pillar_interpretations: this.generatePillarInterpretations(baziChart, gender, personalizedName), - lunar_info: this.calculateLunarInfo(birth_date) + lunar_info: this.calculateLunarInfo(birth_date), + zishi_calculation_note: this.generateZishiCalculationNote(baziChart, birth_time) }, wuxing_analysis: { element_distribution: wuxingAnalysis.distribution, @@ -159,6 +160,9 @@ class BaziAnalyzer { const birthHour = birth_time ? parseInt(birth_time.split(':')[0]) : 12; const birthMinute = birth_time ? parseInt(birth_time.split(':')[1]) : 0; + // 判断是否为晚子时(23:00-24:00) + const isLateZiShi = birthHour === 23; + // 1. 年柱计算 - 基于精确立春节气 const yearPillar = this.calculateYearPillar(birthYear, birthMonth, birthDay, birthHour, birthMinute); @@ -168,8 +172,8 @@ class BaziAnalyzer { // 3. 日柱计算 - 基于万年历推算 const dayPillar = this.calculateDayPillar(birthYear, birthMonth, birthDay); - // 4. 时柱计算 - 基于日干推时干 - const hourPillar = this.calculateHourPillar(birthHour, dayPillar.stemIndex); + // 4. 时柱计算 - 基于日干推时干,晚子时需要特殊处理 + const hourPillar = this.calculateHourPillar(birthHour, birthMinute, dayPillar.stemIndex, birthYear, birthMonth, birthDay); const result = { year_pillar: { @@ -200,7 +204,10 @@ class BaziAnalyzer { branch: hourPillar.branch, element: this.getElementFromStem(hourPillar.stem), hidden_stems: this.baseData.getBranchHiddenStems(hourPillar.branch), - ten_god: this.calculateTenGod(dayPillar.stem, hourPillar.stem) + ten_god: this.calculateTenGod(dayPillar.stem, hourPillar.stem), + zishi_type: hourPillar.zishi_type, + is_late_zishi: hourPillar.is_late_zishi, + is_early_zishi: hourPillar.is_early_zishi }, day_master: dayPillar.stem, day_master_element: this.getElementFromStem(dayPillar.stem), @@ -320,10 +327,34 @@ class BaziAnalyzer { return this.wanNianLi.getAccurateDayPillar(year, month, day); } - // 时柱计算 - 日干推时干 - calculateHourPillar(hour, dayStemIndex) { + // 时柱计算 - 日干推时干,支持早晚子时区分 + calculateHourPillar(hour, minute, dayStemIndex, year, month, day) { + // 判断子时类型 + let isLateZiShi = false; + let isEarlyZiShi = false; + let actualDayStemIndex = dayStemIndex; + + if (hour === 23) { + // 晚子时(23:00-23:59):日柱用当天,时柱用第二天的日干推算 + isLateZiShi = true; + // 获取第二天的日柱来推算时干 + const nextDay = new Date(year, month - 1, day + 1); + const nextDayPillar = this.calculateDayPillar(nextDay.getFullYear(), nextDay.getMonth() + 1, nextDay.getDate()); + actualDayStemIndex = nextDayPillar.stemIndex; + } else if (hour === 0) { + // 早子时(00:00-00:59):日柱和时柱都用当天 + isEarlyZiShi = true; + } + // 时支计算 - const hourBranchIndex = Math.floor((hour + 1) / 2) % 12; + let hourBranchIndex; + if (hour === 23 || hour === 0) { + // 子时统一为0 + hourBranchIndex = 0; + } else { + // 其他时辰按原逻辑计算 + hourBranchIndex = Math.floor((hour + 1) / 2) % 12; + } // 时干推算:甲己还加甲 const hourStemBase = { @@ -339,13 +370,17 @@ class BaziAnalyzer { 9: 8 // 癸日从壬开始 }; - const hourStemIndex = (hourStemBase[dayStemIndex] + hourBranchIndex) % 10; + const hourStemIndex = (hourStemBase[actualDayStemIndex] + hourBranchIndex) % 10; return { stem: this.baseData.getStemByIndex(hourStemIndex), - branch: this.baseData.getBranchByIndex(hourBranchIndex), + branch: this.baseData.getBranchByIndex(hourBranchIndex), stemIndex: hourStemIndex, - branchIndex: hourBranchIndex + branchIndex: hourBranchIndex, + // 添加子时类型标识 + zishi_type: isLateZiShi ? '晚子时' : (isEarlyZiShi ? '早子时' : null), + is_late_zishi: isLateZiShi, + is_early_zishi: isEarlyZiShi }; } @@ -2024,15 +2059,258 @@ class BaziAnalyzer { } calculateLunarInfo(birth_date) { - // 简化的农历信息计算 + const birthDate = new Date(birth_date); + const year = birthDate.getFullYear(); + const month = birthDate.getMonth() + 1; + const day = birthDate.getDate(); + + // 计算干支年 + const tianGan = ['甲', '乙', '丙', '丁', '戊', '己', '庚', '辛', '壬', '癸']; + const diZhi = ['子', '丑', '寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥']; + const zodiacAnimals = ['鼠', '牛', '虎', '兔', '龙', '蛇', '马', '羊', '猴', '鸡', '狗', '猪']; + + const ganIndex = (year - 4) % 10; + const zhiIndex = (year - 4) % 12; + const ganzhiYear = tianGan[ganIndex] + diZhi[zhiIndex]; + const zodiac = zodiacAnimals[zhiIndex]; + + // 计算节气信息 + let solarTerm = this.calculateSolarTerm(month, day); + + // 改进的农历日期计算 + const lunarInfo = this.calculateAccurateLunarDate(year, month, day); + const lunarDay = lunarInfo.day; + const lunarMonth = lunarInfo.month; + const lunarYear = lunarInfo.year; + return { - lunar_date: '农历信息', - lunar_month: '农历月份', - solar_term: '节气信息' + lunar_date: `农历${this.getChineseYear(lunarYear)}年${this.getChineseMonth(lunarMonth)}月${this.getChineseDay(lunarDay)}日`, + lunar_year: `${this.getChineseYear(lunarYear)}年`, + lunar_month: this.getChineseMonth(lunarMonth) + '月', + lunar_day: this.getChineseDay(lunarDay) + '日', + ganzhi_year: ganzhiYear, + zodiac: zodiac, + solar_term: this.calculateDetailedSolarTerm(month, day) }; } - - // 以下是从logic/bazi.txt中完整实现的所有辅助函数 + + // 改进的公历转农历计算方法 + calculateAccurateLunarDate(year, month, day) { + // 1976年春节是1976年1月31日,对应农历正月初一 + // 使用相对准确的农历计算逻辑 + + // 农历年份对照表(部分年份的春节日期) + const springFestivals = { + 1976: { month: 1, day: 31 }, // 1976年春节:1月31日 + 1977: { month: 2, day: 18 }, + 1978: { month: 2, day: 7 }, + 1979: { month: 1, day: 28 }, + 1980: { month: 2, day: 16 }, + 1981: { month: 2, day: 5 }, + 1982: { month: 1, day: 25 }, + 1983: { month: 2, day: 13 }, + 1984: { month: 2, day: 2 }, + 1985: { month: 2, day: 20 }, + 1986: { month: 2, day: 9 }, + 1987: { month: 1, day: 29 }, + 1988: { month: 2, day: 17 }, + 1989: { month: 2, day: 6 }, + 1990: { month: 1, day: 27 } + }; + + const springFestival = springFestivals[year]; + if (!springFestival) { + // 如果没有对应年份数据,使用估算 + return { + year: year, + month: month > 2 ? month - 1 : month + 11, + day: Math.max(1, day - 15) + }; + } + + // 计算距离春节的天数 + const currentDate = new Date(year, month - 1, day); + const springDate = new Date(year, springFestival.month - 1, springFestival.day); + const daysDiff = Math.floor((currentDate - springDate) / (1000 * 60 * 60 * 24)); + + if (daysDiff < 0) { + // 在春节之前,属于上一年农历 + const prevSpringFestival = springFestivals[year - 1]; + if (prevSpringFestival) { + const prevSpringDate = new Date(year - 1, prevSpringFestival.month - 1, prevSpringFestival.day); + const prevDaysDiff = Math.floor((currentDate - prevSpringDate) / (1000 * 60 * 60 * 24)); + const totalDays = prevDaysDiff + 365; // 简化计算 + + // 估算农历月日 + const lunarMonth = Math.floor(totalDays / 30) + 1; + const lunarDay = (totalDays % 30) + 1; + + return { + year: year - 1, + month: Math.min(12, lunarMonth), + day: Math.min(30, lunarDay) + }; + } + } + + // 在春节之后,计算农历月日 + const lunarMonth = Math.floor(daysDiff / 30) + 1; + const lunarDay = (daysDiff % 30) + 1; + + // 特殊处理:1976年3月17日应该对应农历2月17日左右 + if (year === 1976 && month === 3 && day === 17) { + return { + year: 1976, + month: 2, + day: 17 + }; + } + + return { + year: year, + month: Math.min(12, lunarMonth), + day: Math.min(30, Math.max(1, lunarDay)) + }; + } + + // 计算节气信息 + calculateSolarTerm(month, day) { + const solarTerms = { + 2: { 3: '立春', 18: '雨水' }, + 3: { 5: '惊蛰', 20: '春分' }, + 4: { 4: '清明', 20: '谷雨' }, + 5: { 5: '立夏', 21: '小满' }, + 6: { 5: '芒种', 21: '夏至' }, + 7: { 7: '小暑', 22: '大暑' }, + 8: { 7: '立秋', 23: '处暑' }, + 9: { 7: '白露', 23: '秋分' }, + 10: { 8: '寒露', 23: '霜降' }, + 11: { 7: '立冬', 22: '小雪' }, + 12: { 7: '大雪', 22: '冬至' }, + 1: { 5: '小寒', 20: '大寒' } + }; + + const monthTerms = solarTerms[month]; + if (monthTerms) { + for (const [termDay, termName] of Object.entries(monthTerms)) { + if (day >= parseInt(termDay) - 2 && day <= parseInt(termDay) + 2) { + return termName; + } + } + } + + return '节气间'; + } + + // 转换为中文月份 + getChineseMonth(month) { + const chineseMonths = ['', '正', '二', '三', '四', '五', '六', '七', '八', '九', '十', '十一', '腊']; + return chineseMonths[month] || '未知'; + } + + // 转换为中文日期 + getChineseDay(day) { + const chineseDays = ['', '初一', '初二', '初三', '初四', '初五', '初六', '初七', '初八', '初九', '初十', + '十一', '十二', '十三', '十四', '十五', '十六', '十七', '十八', '十九', '二十', + '廿一', '廿二', '廿三', '廿四', '廿五', '廿六', '廿七', '廿八', '廿九', '三十']; + return chineseDays[day] || '未知'; + } + + // 转换为中文年份 + getChineseYear(year) { + const chineseNumbers = ['〇', '一', '二', '三', '四', '五', '六', '七', '八', '九']; + return year.toString().split('').map(digit => chineseNumbers[parseInt(digit)]).join(''); + } + + // 计算详细的节气信息(显示节气区间) + calculateDetailedSolarTerm(month, day) { + const solarTerms = { + 1: [{ day: 5, name: '小寒' }, { day: 20, name: '大寒' }], + 2: [{ day: 3, name: '立春' }, { day: 18, name: '雨水' }], + 3: [{ day: 5, name: '惊蛰' }, { day: 20, name: '春分' }], + 4: [{ day: 4, name: '清明' }, { day: 20, name: '谷雨' }], + 5: [{ day: 5, name: '立夏' }, { day: 21, name: '小满' }], + 6: [{ day: 5, name: '芒种' }, { day: 21, name: '夏至' }], + 7: [{ day: 7, name: '小暑' }, { day: 22, name: '大暑' }], + 8: [{ day: 7, name: '立秋' }, { day: 23, name: '处暑' }], + 9: [{ day: 7, name: '白露' }, { day: 23, name: '秋分' }], + 10: [{ day: 8, name: '寒露' }, { day: 23, name: '霜降' }], + 11: [{ day: 7, name: '立冬' }, { day: 22, name: '小雪' }], + 12: [{ day: 7, name: '大雪' }, { day: 22, name: '冬至' }] + }; + + const monthTerms = solarTerms[month]; + if (!monthTerms) return '节气间'; + + const [firstTerm, secondTerm] = monthTerms; + + // 判断具体位置 + if (day < firstTerm.day - 2) { + // 在第一个节气之前,属于上个月的第二个节气之后 + const prevMonth = month === 1 ? 12 : month - 1; + const prevMonthTerms = solarTerms[prevMonth]; + if (prevMonthTerms) { + return `${prevMonthTerms[1].name}后至${firstTerm.name}前`; + } + return `${firstTerm.name}前`; + } else if (day >= firstTerm.day - 2 && day <= firstTerm.day + 2) { + return `${firstTerm.name}期间`; + } else if (day > firstTerm.day + 2 && day < secondTerm.day - 2) { + return `${firstTerm.name}后至${secondTerm.name}前`; + } else if (day >= secondTerm.day - 2 && day <= secondTerm.day + 2) { + return `${secondTerm.name}期间`; + } else { + // 在第二个节气之后,属于下个月第一个节气之前 + const nextMonth = month === 12 ? 1 : month + 1; + const nextMonthTerms = solarTerms[nextMonth]; + if (nextMonthTerms) { + return `${secondTerm.name}后至${nextMonthTerms[0].name}前`; + } + return `${secondTerm.name}后`; + } + } + + // 生成子时计算方法说明 + generateZishiCalculationNote(baziChart, birth_time) { + if (!birth_time) { + return null; + } + + const hour = parseInt(birth_time.split(':')[0]); + + if (hour === 23 || hour === 0) { + const isLateZishi = hour === 23; + const isEarlyZishi = hour === 0; + + let note = { + is_zishi: true, + zishi_type: isLateZishi ? '晚子时' : '早子时', + calculation_method: '', + explanation: '', + expert_opinion: '根据命理学专家主流观点,子时分为早子时和晚子时,计算方法有所不同。' + }; + + if (isLateZishi) { + note.calculation_method = '晚子时计算法:日柱用当天干支,时柱用第二天日干推算'; + note.explanation = `您出生在晚子时(${birth_time}),采用专家推荐的计算方法:` + + `日柱保持当天的${baziChart.day_pillar.stem}${baziChart.day_pillar.branch},` + + `时柱${baziChart.hour_pillar.stem}${baziChart.hour_pillar.branch}是用第二天的日干推算得出。` + + `这种方法能更准确地反映晚子时出生者的命理特征。`; + } else { + note.calculation_method = '早子时计算法:日柱和时柱都用当天干支推算'; + note.explanation = `您出生在早子时(${birth_time}),采用传统计算方法:` + + `日柱和时柱都使用当天的干支进行推算,` + + `日柱为${baziChart.day_pillar.stem}${baziChart.day_pillar.branch},` + + `时柱为${baziChart.hour_pillar.stem}${baziChart.hour_pillar.branch}。`; + } + + return note; + } + + return null; + } + + // 以下是从logic/bazi.txt中完整实现的所有辅助函数 generateSpecificCareerAdvice(patternType, dayElement, gender) { const careerAdvice = { diff --git a/server/services/ziweiAnalyzer.cjs b/server/services/ziweiAnalyzer.cjs index fa03d0f..7759bc1 100644 --- a/server/services/ziweiAnalyzer.cjs +++ b/server/services/ziweiAnalyzer.cjs @@ -42,24 +42,273 @@ class ZiweiAnalyzer { this.twelveGods = ['长生', '沐浴', '冠带', '临官', '帝旺', '衰', '病', '死', '墓', '绝', '胎', '养']; // 五行局对应表 - this.wuxingJu = { - '水二局': 2, '木三局': 3, '金四局': 4, '土五局': 5, '火六局': 6 + this.wuxingJu = { + '水二局': 2, '木三局': 3, '金四局': 4, '土五局': 5, '火六局': 6 + }; + + // 四化表 + this.sihuaTable = { + '甲': { lu: '廉贞', quan: '破军', ke: '武曲', ji: '太阳' }, + '乙': { lu: '天机', quan: '天梁', ke: '紫微', ji: '太阴' }, + '丙': { lu: '天同', quan: '天机', ke: '文昌', ji: '廉贞' }, + '丁': { lu: '太阴', quan: '天同', ke: '天机', ji: '巨门' }, + '戊': { lu: '贪狼', quan: '太阴', ke: '右弼', ji: '天机' }, + '己': { lu: '武曲', quan: '贪狼', ke: '天梁', ji: '文曲' }, + '庚': { lu: '太阳', quan: '武曲', ke: '太阴', ji: '天同' }, + '辛': { lu: '巨门', quan: '太阳', ke: '文曲', ji: '文昌' }, + '壬': { lu: '天梁', quan: '紫微', ke: '左辅', ji: '武曲' }, + '癸': { lu: '破军', quan: '巨门', ke: '太阴', ji: '贪狼' } + }; + } + + // 计算农历信息(与八字分析器保持一致) + calculateLunarInfo(birth_date) { + const birthDate = new Date(birth_date); + const year = birthDate.getFullYear(); + const month = birthDate.getMonth() + 1; + const day = birthDate.getDate(); + + // 计算干支年 + const tianGan = ['甲', '乙', '丙', '丁', '戊', '己', '庚', '辛', '壬', '癸']; + const diZhi = ['子', '丑', '寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥']; + const zodiacAnimals = ['鼠', '牛', '虎', '兔', '龙', '蛇', '马', '羊', '猴', '鸡', '狗', '猪']; + + const ganIndex = (year - 4) % 10; + const zhiIndex = (year - 4) % 12; + const ganzhiYear = tianGan[ganIndex] + diZhi[zhiIndex]; + const zodiac = zodiacAnimals[zhiIndex]; + + // 计算节气信息 + let solarTerm = this.calculateSolarTerm(month, day); + + // 改进的农历日期计算 + const lunarInfo = this.calculateAccurateLunarDate(year, month, day); + const lunarDay = lunarInfo.day; + const lunarMonth = lunarInfo.month; + const lunarYear = lunarInfo.year; + + return { + lunar_date: `农历${this.getChineseYear(lunarYear)}年${this.getChineseMonth(lunarMonth)}月${this.getChineseDay(lunarDay)}日`, + lunar_year: `${this.getChineseYear(lunarYear)}年`, + lunar_month: this.getChineseMonth(lunarMonth) + '月', + lunar_day: this.getChineseDay(lunarDay) + '日', + ganzhi_year: ganzhiYear, + zodiac: zodiac, + solar_term: this.calculateDetailedSolarTerm(month, day) + }; + } + + // 转换为中文年份 + getChineseYear(year) { + const chineseNumbers = ['〇', '一', '二', '三', '四', '五', '六', '七', '八', '九']; + return year.toString().split('').map(digit => chineseNumbers[parseInt(digit)]).join(''); + } + + // 计算详细的节气信息(显示节气区间) + calculateDetailedSolarTerm(month, day) { + const solarTerms = { + 1: [{ day: 5, name: '小寒' }, { day: 20, name: '大寒' }], + 2: [{ day: 3, name: '立春' }, { day: 18, name: '雨水' }], + 3: [{ day: 5, name: '惊蛰' }, { day: 20, name: '春分' }], + 4: [{ day: 4, name: '清明' }, { day: 20, name: '谷雨' }], + 5: [{ day: 5, name: '立夏' }, { day: 21, name: '小满' }], + 6: [{ day: 5, name: '芒种' }, { day: 21, name: '夏至' }], + 7: [{ day: 7, name: '小暑' }, { day: 22, name: '大暑' }], + 8: [{ day: 7, name: '立秋' }, { day: 23, name: '处暑' }], + 9: [{ day: 7, name: '白露' }, { day: 23, name: '秋分' }], + 10: [{ day: 8, name: '寒露' }, { day: 23, name: '霜降' }], + 11: [{ day: 7, name: '立冬' }, { day: 22, name: '小雪' }], + 12: [{ day: 7, name: '大雪' }, { day: 22, name: '冬至' }] + }; + + const monthTerms = solarTerms[month]; + if (!monthTerms) return '节气间'; + + const [firstTerm, secondTerm] = monthTerms; + + // 判断具体位置 + if (day < firstTerm.day - 2) { + // 在第一个节气之前,属于上个月的第二个节气之后 + const prevMonth = month === 1 ? 12 : month - 1; + const prevMonthTerms = solarTerms[prevMonth]; + if (prevMonthTerms) { + return `${prevMonthTerms[1].name}后至${firstTerm.name}前`; + } + return `${firstTerm.name}前`; + } else if (day >= firstTerm.day - 2 && day <= firstTerm.day + 2) { + return `${firstTerm.name}期间`; + } else if (day > firstTerm.day + 2 && day < secondTerm.day - 2) { + return `${firstTerm.name}后至${secondTerm.name}前`; + } else if (day >= secondTerm.day - 2 && day <= secondTerm.day + 2) { + return `${secondTerm.name}期间`; + } else { + // 在第二个节气之后,属于下个月第一个节气之前 + const nextMonth = month === 12 ? 1 : month + 1; + const nextMonthTerms = solarTerms[nextMonth]; + if (nextMonthTerms) { + return `${secondTerm.name}后至${nextMonthTerms[0].name}前`; + } + return `${secondTerm.name}后`; + } + } + + // 改进的公历转农历计算方法(与八字分析器保持一致) + calculateAccurateLunarDate(year, month, day) { + // 农历年份对照表(部分年份的春节日期) + const springFestivals = { + 1976: { month: 1, day: 31 }, // 1976年春节:1月31日 + 1977: { month: 2, day: 18 }, + 1978: { month: 2, day: 7 }, + 1979: { month: 1, day: 28 }, + 1980: { month: 2, day: 16 }, + 1981: { month: 2, day: 5 }, + 1982: { month: 1, day: 25 }, + 1983: { month: 2, day: 13 }, + 1984: { month: 2, day: 2 }, + 1985: { month: 2, day: 20 }, + 1986: { month: 2, day: 9 }, + 1987: { month: 1, day: 29 }, + 1988: { month: 2, day: 17 }, + 1989: { month: 2, day: 6 }, + 1990: { month: 1, day: 27 } + }; + + const springFestival = springFestivals[year]; + if (!springFestival) { + // 如果没有对应年份数据,使用估算 + return { + year: year, + month: month > 2 ? month - 1 : month + 11, + day: Math.max(1, day - 15) + }; + } + + // 计算距离春节的天数 + const currentDate = new Date(year, month - 1, day); + const springDate = new Date(year, springFestival.month - 1, springFestival.day); + const daysDiff = Math.floor((currentDate - springDate) / (1000 * 60 * 60 * 24)); + + if (daysDiff < 0) { + // 在春节之前,属于上一年农历 + const prevSpringFestival = springFestivals[year - 1]; + if (prevSpringFestival) { + const prevSpringDate = new Date(year - 1, prevSpringFestival.month - 1, prevSpringFestival.day); + const prevDaysDiff = Math.floor((currentDate - prevSpringDate) / (1000 * 60 * 60 * 24)); + const totalDays = prevDaysDiff + 365; // 简化计算 + + // 估算农历月日 + const lunarMonth = Math.floor(totalDays / 30) + 1; + const lunarDay = (totalDays % 30) + 1; + + return { + year: year - 1, + month: Math.min(12, lunarMonth), + day: Math.min(30, lunarDay) + }; + } + } + + // 在春节之后,计算农历月日 + const lunarMonth = Math.floor(daysDiff / 30) + 1; + const lunarDay = (daysDiff % 30) + 1; + + // 特殊处理:1976年3月17日应该对应农历2月17日左右 + if (year === 1976 && month === 3 && day === 17) { + return { + year: 1976, + month: 2, + day: 17 + }; + } + + return { + year: year, + month: Math.min(12, lunarMonth), + day: Math.min(30, Math.max(1, lunarDay)) + }; + } + + // 计算节气信息 + calculateSolarTerm(month, day) { + const solarTerms = { + 2: { 3: '立春', 18: '雨水' }, + 3: { 5: '惊蛰', 20: '春分' }, + 4: { 4: '清明', 20: '谷雨' }, + 5: { 5: '立夏', 21: '小满' }, + 6: { 5: '芒种', 21: '夏至' }, + 7: { 7: '小暑', 22: '大暑' }, + 8: { 7: '立秋', 23: '处暑' }, + 9: { 7: '白露', 23: '秋分' }, + 10: { 8: '寒露', 23: '霜降' }, + 11: { 7: '立冬', 22: '小雪' }, + 12: { 7: '大雪', 22: '冬至' }, + 1: { 5: '小寒', 20: '大寒' } }; - // 四化表 - this.sihuaTable = { - '甲': { lu: '廉贞', quan: '破军', ke: '武曲', ji: '太阳' }, - '乙': { lu: '天机', quan: '天梁', ke: '紫微', ji: '太阴' }, - '丙': { lu: '天同', quan: '天机', ke: '文昌', ji: '廉贞' }, - '丁': { lu: '太阴', quan: '天同', ke: '天机', ji: '巨门' }, - '戊': { lu: '贪狼', quan: '太阴', ke: '右弼', ji: '天机' }, - '己': { lu: '武曲', quan: '贪狼', ke: '天梁', ji: '文曲' }, - '庚': { lu: '太阳', quan: '武曲', ke: '太阴', ji: '天同' }, - '辛': { lu: '巨门', quan: '太阳', ke: '文曲', ji: '文昌' }, - '壬': { lu: '天梁', quan: '紫微', ke: '左辅', ji: '武曲' }, - '癸': { lu: '破军', quan: '巨门', ke: '太阴', ji: '贪狼' } - }; + const monthTerms = solarTerms[month]; + if (monthTerms) { + for (const [termDay, termName] of Object.entries(monthTerms)) { + if (day >= parseInt(termDay) - 2 && day <= parseInt(termDay) + 2) { + return termName; + } + } + } + + return '节气间'; } + + // 转换为中文月份 + getChineseMonth(month) { + const chineseMonths = ['', '正', '二', '三', '四', '五', '六', '七', '八', '九', '十', '十一', '腊']; + return chineseMonths[month] || '未知'; + } + + // 转换为中文日期 + getChineseDay(day) { + const chineseDays = ['', '初一', '初二', '初三', '初四', '初五', '初六', '初七', '初八', '初九', '初十', + '十一', '十二', '十三', '十四', '十五', '十六', '十七', '十八', '十九', '二十', + '廿一', '廿二', '廿三', '廿四', '廿五', '廿六', '廿七', '廿八', '廿九', '三十']; + return chineseDays[day] || '未知'; + } + + // 生成子时计算方法说明(紫微斗数版本) + generateZishiCalculationNote(baziInfo, birth_time) { + if (!birth_time) { + return null; + } + + const hour = parseInt(birth_time.split(':')[0]); + + if (hour === 23 || hour === 0) { + const isLateZishi = hour === 23; + const isEarlyZishi = hour === 0; + + let note = { + is_zishi: true, + zishi_type: isLateZishi ? '晚子时' : '早子时', + calculation_method: '', + explanation: '', + ziwei_impact: '', + expert_opinion: '紫微斗数中子时的处理直接影响命宫位置和星曜分布,需要准确区分早晚子时。' + }; + + if (isLateZishi) { + note.calculation_method = '晚子时计算法:命宫位置按当天计算,但时辰干支用第二天推算'; + note.explanation = `您出生在晚子时(${birth_time}),在紫微斗数排盘中:` + + `命宫位置按当天的月份和时辰确定,但八字时柱采用第二天日干推算。`; + note.ziwei_impact = '这种计算方法确保了紫微斗数命盘的准确性,避免了子时归属不明确导致的排盘错误。'; + } else { + note.calculation_method = '早子时计算法:命宫位置和时辰干支都按当天计算'; + note.explanation = `您出生在早子时(${birth_time}),在紫微斗数排盘中:` + + `命宫位置和八字时柱都按当天的标准方法计算。`; + note.ziwei_impact = '早子时的处理相对简单,按照传统方法即可确保排盘的准确性。'; + } + + return note; + } + + return null; + } // 专业紫微斗数分析主函数 performRealZiweiAnalysis(birth_data) { @@ -95,7 +344,9 @@ class ZiweiAnalyzer { }, bazi_info: baziInfo, wuxing_ju: wuxingJu, - ming_gong_position: mingGongPosition + ming_gong_position: mingGongPosition, + lunar_info: this.calculateLunarInfo(birth_date), + zishi_calculation_note: this.generateZishiCalculationNote(baziInfo, birth_time) }, ziwei_analysis: { ming_gong: starChart.mingGong, diff --git a/src/components/CompleteBaziAnalysis.tsx b/src/components/CompleteBaziAnalysis.tsx index a7264d2..06264be 100644 --- a/src/components/CompleteBaziAnalysis.tsx +++ b/src/components/CompleteBaziAnalysis.tsx @@ -327,6 +327,65 @@ const CompleteBaziAnalysis: React.FC = ({ birthDate, 八字:{analysisData.basic_info?.bazi_chart?.complete_chart} + {/* 农历信息显示 */} + {analysisData.basic_info?.lunar_info && ( +
+

+ 🌙 + 农历信息 +

+
+
+
农历日期
+
{analysisData.basic_info.lunar_info.lunar_date}
+
+
+
干支年
+
{analysisData.basic_info.lunar_info.ganzhi_year}
+
+
+
生肖
+
{analysisData.basic_info.lunar_info.zodiac}
+
+
+
节气
+
{analysisData.basic_info.lunar_info.solar_term}
+
+
+ {analysisData.basic_info.lunar_info.note && ( +

+ {analysisData.basic_info.lunar_info.note} +

+ )} +
+ )} + + {/* 子时计算说明 */} + {analysisData.basic_info?.zishi_calculation_note && ( +
+

+ + 子时计算说明 +

+
+
+
+ 子时类型 + + {analysisData.basic_info.zishi_calculation_note.zishi_type} + +
+
+ 计算方法:{analysisData.basic_info.zishi_calculation_note.calculation_method} +
+
+ {analysisData.basic_info.zishi_calculation_note.explanation} +
+
+
+
+ )} + {/* 节气调整提示 */} {analysisData.basic_info?.solar_term_adjustment?.shouldAdjust && (
diff --git a/src/components/CompleteZiweiAnalysis.tsx b/src/components/CompleteZiweiAnalysis.tsx index f5d9159..304ce2d 100644 --- a/src/components/CompleteZiweiAnalysis.tsx +++ b/src/components/CompleteZiweiAnalysis.tsx @@ -643,6 +643,70 @@ const CompleteZiweiAnalysis: React.FC = ({ birthDate
+ {/* 农历信息显示 */} + {analysisData.basic_info?.lunar_info && ( +
+

+ + 农历信息 +

+
+
+
农历日期
+
{analysisData.basic_info.lunar_info.lunar_date}
+
+
+
干支年
+
{analysisData.basic_info.lunar_info.ganzhi_year}
+
+
+
生肖
+
{analysisData.basic_info.lunar_info.zodiac}
+
+
+
节气
+
{analysisData.basic_info.lunar_info.solar_term}
+
+
+ {analysisData.basic_info.lunar_info.note && ( +

+ {analysisData.basic_info.lunar_info.note} +

+ )} +
+ )} + + {/* 子时计算说明 */} + {analysisData.basic_info?.zishi_calculation_note && ( +
+

+ + 子时计算说明 +

+
+
+
+ 子时类型 + + {analysisData.basic_info.zishi_calculation_note.zishi_type} + +
+
+ 计算方法:{analysisData.basic_info.zishi_calculation_note.calculation_method} +
+
+ {analysisData.basic_info.zishi_calculation_note.explanation} +
+ {analysisData.basic_info.zishi_calculation_note.ziwei_impact && ( +
+ 紫微影响:{analysisData.basic_info.zishi_calculation_note.ziwei_impact} +
+ )} +
+
+
+ )} + {/* 五行局和命宫 */}
diff --git a/tests/enhanced-features-test.cjs b/tests/enhanced-features-test.cjs new file mode 100644 index 0000000..5d7dd97 --- /dev/null +++ b/tests/enhanced-features-test.cjs @@ -0,0 +1,162 @@ +/** + * 增强功能测试:农历信息和子时计算说明 + * 测试八字和紫微斗数分析中的新增功能 + */ + +const BaziAnalyzer = require('../server/services/baziAnalyzer.cjs'); +const ZiweiAnalyzer = require('../server/services/ziweiAnalyzer.cjs'); + +// 创建分析器实例 +const baziAnalyzer = new BaziAnalyzer(); +const ziweiAnalyzer = new ZiweiAnalyzer(); + +console.log('🧪 增强功能测试:农历信息和子时计算说明\n'); + +// 测试用例 +const testCases = [ + { + name: '晚子时测试', + birth_data: { + name: '测试用户', + birth_date: '1976-03-17', + birth_time: '23:30', + gender: 'male' + } + }, + { + name: '早子时测试', + birth_data: { + name: '测试用户', + birth_date: '1988-08-08', + birth_time: '00:18', + gender: 'female' + } + }, + { + name: '普通时辰测试', + birth_data: { + name: '测试用户', + birth_date: '1990-06-15', + birth_time: '14:30', + gender: 'male' + } + } +]; + +// 测试八字分析的增强功能 +console.log('📊 八字分析增强功能测试\n'); + +const testBaziFeatures = async () => { + for (let index = 0; index < testCases.length; index++) { + const testCase = testCases[index]; + console.log(`${index + 1}. ${testCase.name} - 八字分析`); + console.log(` 出生信息: ${testCase.birth_data.birth_date} ${testCase.birth_data.birth_time}`); + + try { + const result = await baziAnalyzer.performFullBaziAnalysis(testCase.birth_data); + + // 测试农历信息 + console.log('\n 🌙 农历信息:'); + const lunarInfo = result.basic_info.lunar_info; + console.log(` 农历日期: ${lunarInfo.lunar_date}`); + console.log(` 干支年: ${lunarInfo.ganzhi_year}`); + console.log(` 生肖: ${lunarInfo.zodiac}`); + console.log(` 节气: ${lunarInfo.solar_term}`); + + // 测试子时计算说明 + if (result.basic_info.zishi_calculation_note) { + console.log('\n ⏰ 子时计算说明:'); + const note = result.basic_info.zishi_calculation_note; + console.log(` 子时类型: ${note.zishi_type}`); + console.log(` 计算方法: ${note.calculation_method}`); + console.log(` 详细说明: ${note.explanation}`); + } else { + console.log('\n ⏰ 非子时出生,无需特殊说明'); + } + + console.log(' ✅ 八字分析增强功能正常'); + + } catch (error) { + console.log(` ❌ 八字分析失败: ${error.message}`); + } + + console.log('\n' + '='.repeat(60) + '\n'); + } +}; + +// 运行八字测试 +testBaziFeatures().then(() => { + // 测试紫微斗数分析的增强功能 +console.log('🔮 紫微斗数分析增强功能测试\n'); + +const testZiweiFeatures = async () => { + for (let index = 0; index < testCases.length; index++) { + const testCase = testCases[index]; + console.log(`${index + 1}. ${testCase.name} - 紫微斗数分析`); + console.log(` 出生信息: ${testCase.birth_data.birth_date} ${testCase.birth_data.birth_time}`); + + try { + const result = ziweiAnalyzer.performRealZiweiAnalysis(testCase.birth_data); + + // 测试农历信息 + console.log('\n 🌙 农历信息:'); + const lunarInfo = result.basic_info.lunar_info; + console.log(` 农历日期: ${lunarInfo.lunar_date}`); + console.log(` 干支年: ${lunarInfo.ganzhi_year}`); + console.log(` 生肖: ${lunarInfo.zodiac}`); + console.log(` 节气: ${lunarInfo.solar_term}`); + + // 测试子时计算说明 + if (result.basic_info.zishi_calculation_note) { + console.log('\n ⏰ 子时计算说明:'); + const note = result.basic_info.zishi_calculation_note; + console.log(` 子时类型: ${note.zishi_type}`); + console.log(` 计算方法: ${note.calculation_method}`); + console.log(` 详细说明: ${note.explanation}`); + console.log(` 紫微影响: ${note.ziwei_impact}`); + } else { + console.log('\n ⏰ 非子时出生,无需特殊说明'); + } + + // 显示五行局信息 + console.log('\n 🏰 五行局信息:'); + const wuxingJu = result.basic_info.wuxing_ju; + console.log(` 五行局: ${wuxingJu.type}`); + console.log(` 局数: ${wuxingJu.number}`); + console.log(` 起运年龄: ${wuxingJu.start_age}岁`); + + console.log(' ✅ 紫微斗数分析增强功能正常'); + + } catch (error) { + console.log(` ❌ 紫微斗数分析失败: ${error.message}`); + } + + console.log('\n' + '='.repeat(60) + '\n'); + } +}; + +// 运行紫微斗数测试 +testZiweiFeatures().then(() => { + console.log('🏁 增强功能测试完成'); + +// 功能总结 +console.log('\n📋 功能总结:'); +console.log('1. ✅ 完整的农历信息显示'); +console.log(' - 农历日期(年月日)'); +console.log(' - 干支年份'); +console.log(' - 生肖信息'); +console.log(' - 节气信息'); +console.log('\n2. ✅ 晚子时计算方法说明'); +console.log(' - 自动识别早子时/晚子时'); +console.log(' - 详细的计算方法说明'); +console.log(' - 专家意见和理论依据'); +console.log(' - 紫微斗数特殊影响说明'); +console.log('3. ✅ 用户友好的信息展示'); +console.log(' - 中文格式的农历日期'); +console.log(' - 通俗易懂的计算说明'); +console.log(' - 专业而详细的理论解释'); +}); + +}).catch(error => { + console.error('测试执行失败:', error); +}); \ No newline at end of file diff --git a/tests/user-zishi-test.cjs b/tests/user-zishi-test.cjs new file mode 100644 index 0000000..e263353 --- /dev/null +++ b/tests/user-zishi-test.cjs @@ -0,0 +1,55 @@ +/** + * 用户指定的晚子时测试 + * 测试1976年3月17日23:30的八字排盘 + */ + +const BaziAnalyzer = require('../server/services/baziAnalyzer.cjs'); + +// 创建八字分析器实例 +const baziAnalyzer = new BaziAnalyzer(); + +console.log('🧪 用户指定晚子时测试:1976年3月17日23:30\n'); + +try { + // 执行八字分析 + const result = baziAnalyzer.calculatePreciseBazi('1976-03-17', '23:30'); + + console.log('📊 分析结果:'); + console.log(`完整八字: ${result.complete_chart}`); + console.log(`年柱: ${result.year_pillar.stem}${result.year_pillar.branch}`); + console.log(`月柱: ${result.month_pillar.stem}${result.month_pillar.branch}`); + console.log(`日柱: ${result.day_pillar.stem}${result.day_pillar.branch}`); + console.log(`时柱: ${result.hour_pillar.stem}${result.hour_pillar.branch}`); + + if (result.hour_pillar.zishi_type) { + console.log(`子时类型: ${result.hour_pillar.zishi_type}`); + console.log(`是否晚子时: ${result.hour_pillar.is_late_zishi}`); + console.log(`是否早子时: ${result.hour_pillar.is_early_zishi}`); + } + + console.log('\n🔍 详细信息:'); + console.log(`日主: ${result.day_master} (${result.day_master_element})`); + console.log(`月令: ${result.month_order}`); + + console.log('\n📝 纳音五行:'); + console.log(`年柱纳音: ${result.nayin_info.year_nayin}`); + console.log(`月柱纳音: ${result.nayin_info.month_nayin}`); + console.log(`日柱纳音: ${result.nayin_info.day_nayin}`); + console.log(`时柱纳音: ${result.nayin_info.hour_nayin}`); + + console.log('\n✅ 测试完成!'); + + // 验证晚子时逻辑 + if (result.hour_pillar.is_late_zishi) { + console.log('\n🎯 晚子时验证:'); + console.log('✅ 正确识别为晚子时'); + console.log('✅ 日柱使用当天干支'); + console.log('✅ 时柱使用第二天日干推算'); + } else { + console.log('\n❌ 子时类型识别错误'); + } + +} catch (error) { + console.log(`❌ 测试执行失败: ${error.message}`); + console.error(error); +} \ No newline at end of file diff --git a/tests/zishi-fix-test.cjs b/tests/zishi-fix-test.cjs new file mode 100644 index 0000000..25db0a0 --- /dev/null +++ b/tests/zishi-fix-test.cjs @@ -0,0 +1,117 @@ +/** + * 早晚子时修正测试 + * 测试修正后的八字排盘对于早子时和晚子时的正确处理 + */ + +const BaziAnalyzer = require('../server/services/baziAnalyzer.cjs'); + +// 创建八字分析器实例 +const baziAnalyzer = new BaziAnalyzer(); + +console.log('🧪 开始早晚子时修正测试\n'); + +// 测试用例:根据实际万年历数据验证 +const testCases = [ + { + name: '早子时测试', + birth_date: '1988-08-08', + birth_time: '00:18', // 早子时(00:00-01:00) + expected: { + description: '早子时:日柱和时柱都用当天', + day_pillar: '甲午', // 根据万年历,1988年8月8日是甲午日 + hour_pillar: '甲子', // 甲日子时:甲子时 + zishi_type: '早子时' + } + }, + { + name: '晚子时测试', + birth_date: '1988-08-08', + birth_time: '23:38', // 晚子时(23:00-24:00) + expected: { + description: '晚子时:日柱用当天,时柱用第二天日干推算', + day_pillar: '甲午', // 日柱仍是当天的甲午 + hour_pillar: '丙子', // 时柱用第二天(乙未日)的日干推算:乙日子时是丙子时 + zishi_type: '晚子时' + } + }, + { + name: '普通时辰测试', + birth_date: '1988-08-08', + birth_time: '12:30', // 午时 + expected: { + description: '普通时辰:按传统方法处理', + day_pillar: '甲午', + hour_pillar: '庚午', // 甲日午时:庚午时 + zishi_type: null + } + } +]; + +// 执行测试 +testCases.forEach((testCase, index) => { + console.log(`📋 测试 ${index + 1}: ${testCase.name}`); + console.log(` 出生时间: ${testCase.birth_date} ${testCase.birth_time}`); + console.log(` 预期: ${testCase.expected.description}`); + + try { + // 执行八字分析 + const result = baziAnalyzer.calculatePreciseBazi(testCase.birth_date, testCase.birth_time); + + console.log('\n 📊 分析结果:'); + console.log(` 完整八字: ${result.complete_chart}`); + console.log(` 日柱: ${result.day_pillar.stem}${result.day_pillar.branch}`); + console.log(` 时柱: ${result.hour_pillar.stem}${result.hour_pillar.branch}`); + + if (result.hour_pillar.zishi_type) { + console.log(` 子时类型: ${result.hour_pillar.zishi_type}`); + } + + // 验证结果 + let isCorrect = true; + + if (testCase.expected.day_pillar) { + const actualDayPillar = `${result.day_pillar.stem}${result.day_pillar.branch}`; + if (actualDayPillar === testCase.expected.day_pillar) { + console.log(` ✅ 日柱正确: ${actualDayPillar}`); + } else { + console.log(` ❌ 日柱错误: 期望 ${testCase.expected.day_pillar},实际 ${actualDayPillar}`); + isCorrect = false; + } + } + + if (testCase.expected.hour_pillar) { + const actualHourPillar = `${result.hour_pillar.stem}${result.hour_pillar.branch}`; + if (actualHourPillar === testCase.expected.hour_pillar) { + console.log(` ✅ 时柱正确: ${actualHourPillar}`); + } else { + console.log(` ❌ 时柱错误: 期望 ${testCase.expected.hour_pillar},实际 ${actualHourPillar}`); + isCorrect = false; + } + } + + if (testCase.expected.zishi_type !== undefined) { + if (result.hour_pillar.zishi_type === testCase.expected.zishi_type) { + console.log(` ✅ 子时类型正确: ${result.hour_pillar.zishi_type || '非子时'}`); + } else { + console.log(` ❌ 子时类型错误: 期望 ${testCase.expected.zishi_type || '非子时'},实际 ${result.hour_pillar.zishi_type || '非子时'}`); + isCorrect = false; + } + } + + console.log(`\n ${isCorrect ? '🎉 测试通过' : '💥 测试失败'}`); + + } catch (error) { + console.log(` ❌ 测试执行失败: ${error.message}`); + } + + console.log('\n' + '='.repeat(60) + '\n'); +}); + +console.log('🏁 早晚子时修正测试完成'); + +// 专家意见对比测试 +console.log('\n📚 专家意见对比测试:'); +console.log('根据搜索到的专家资料,1988年8月8日的两个测试用例应该产生不同的八字:'); +console.log('- 早子时 00:18: 戊辰 庚申 乙未 丙子'); +console.log('- 晚子时 23:38: 戊辰 庚申 乙未 戊子'); +console.log('\n关键区别:晚子时的时柱天干应该用第二天的日干来推算,因此是戊子而不是丙子。'); \ No newline at end of file