🌛Solar date to BaZi
// Some code
private readonly TIAN_GAN = ['甲', '乙', '丙', '丁', '戊', '己', '庚', '辛', '壬', '癸'];
private readonly DI_ZHI = ['子', '丑', '寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥'];
// 年干支
private calcYearGZ(year: number): string {
const baseYear = 1984;
const offset = year - baseYear;
const ganIndex = (offset % 10 + 10) % 10;
const zhiIndex = (offset % 12 + 12) % 12;
return this.TIAN_GAN[ganIndex] + this.DI_ZHI[zhiIndex];
}
// 月干支(节气+五虎遁)
private calcMonthGZ(year: number, month: number, day: number): string {
const zhi = this.getMonthZhiByJieQi(month, day);
const yearGan = this.calcYearGZ(year)[0];
let firstMonthGan: string;
if (yearGan === '甲' || yearGan === '己') firstMonthGan = '丙';
else if (yearGan === '乙' || yearGan === '庚') firstMonthGan = '戊';
else if (yearGan === '丙' || yearGan === '辛') firstMonthGan = '庚';
else if (yearGan === '丁' || yearGan === '壬') firstMonthGan = '壬';
else firstMonthGan = '甲';
const startIndex = this.TIAN_GAN.indexOf(firstMonthGan);
const yueIndex = this.DI_ZHI.indexOf(zhi) - this.DI_ZHI.indexOf('寅');
const ganIndex = (startIndex + yueIndex + 10) % 10;
return this.TIAN_GAN[ganIndex] + zhi;
}
private getMonthZhiByJieQi(month: number, day: number): string {
if ((month === 2 && day >= 4) || (month === 3 && day < 6)) return '寅';
if ((month === 3 && day >= 6) || (month === 4 && day < 5)) return '卯';
if ((month === 4 && day >= 5) || (month === 5 && day < 6)) return '辰';
if ((month === 5 && day >= 6) || (month === 6 && day < 6)) return '巳';
if ((month === 6 && day >= 6) || (month === 7 && day < 7)) return '午';
if ((month === 7 && day >= 7) || (month === 8 && day < 8)) return '未';
if ((month === 8 && day >= 8) || (month === 9 && day < 8)) return '申';
if ((month === 9 && day >= 8) || (month === 10 && day < 8)) return '酉';
if ((month === 10 && day >= 8) || (month === 11 && day < 7)) return '戌';
if ((month === 11 && day >= 7) || (month === 12 && day < 7)) return '亥';
if ((month === 12 && day >= 7) || (month === 1 && day < 5)) return '子';
return '丑';
}
// ==========================
// ✅ 日干支:使用本地时间(北京时间)计算
// 基准:1900-01-01 = 癸巳日(位置10)
// ==========================
private calcDayGanZhi(y: number, m: number, d: number): string {
const MS_PER_DAY = 86400000;
const TZ_OFFSET = 8 * 60 * 60 * 1000; // 北京时间
const baseUTC = Date.UTC(1900, 0, 1);
const targetUTC = Date.UTC(y, m - 1, d);
const days = Math.floor((targetUTC + TZ_OFFSET - baseUTC - TZ_OFFSET) / MS_PER_DAY);
const idx = ((10 + days) % 60 + 60) % 60;
const gan = this.TIAN_GAN[idx % 10];
const zhi = this.DI_ZHI[idx % 12];
return gan + zhi;
}
// ==========================
// ✅ 时柱五鼠遁
// ==========================
private calcHourGanZhi(dayGan: string, hour: number): string {
const h = Math.floor((hour + 1) / 2) % 12;
const dayGanIdx = this.TIAN_GAN.indexOf(dayGan.charAt(0));
// 五鼠遁起点
const startMap = [0, 2, 4, 6, 8, 0, 2, 4, 6, 8];
const ganIdx = (startMap[dayGanIdx] + h) % 10;
return this.TIAN_GAN[ganIdx] + this.DI_ZHI[h];
}
Last updated