Files
zhimingge/lib/calc/bazi.ts
T
dekun fff77dac3f Implement three divination modes, learn pages, and PM2 deploy on port 3130.
Add liuyao/bazi/combined flows with shared calc and AI infrastructure, 64-gua learn routes, and update Ubuntu PM2 deployment docs for port 3130.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-10 20:19:49 +08:00

177 lines
5.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { Solar } from "lunar-javascript";
import {
adjustToTrueSolarTime,
formatDateTime,
parseDateTime,
} from "@/lib/calc/time";
export interface BaziInput {
date: string;
time: string;
gender: "male" | "female";
longitude: number;
unknownHour?: boolean;
}
export interface PillarInfo {
ganZhi: string;
shiShenGan: string;
shiShenZhi: string[];
hideGan: string[];
naYin: string;
}
export interface DaYunInfo {
ganZhi: string;
startAge: number;
}
export interface BaziChart {
birthTime: string;
trueSolarTime: string;
unknownHour: boolean;
lunarDate: string;
pillars: {
year: PillarInfo;
month: PillarInfo;
day: PillarInfo;
time: PillarInfo;
};
daYun: {
startYear: number;
startMonth: number;
startDay: number;
items: DaYunInfo[];
};
liuNian: { year: number; ganZhi: string }[];
shenSha: {
ji: string[];
xiong: string[];
};
}
function buildPillar(
ganZhi: string,
shiShenGan: string,
shiShenZhi: string[],
hideGan: string[],
naYin: string,
): PillarInfo {
return { ganZhi, shiShenGan, shiShenZhi, hideGan, naYin };
}
export function calculateBazi(input: BaziInput): BaziChart {
const localTime = parseDateTime(input.date, input.time);
const trueSolar = adjustToTrueSolarTime(localTime, input.longitude);
const solar = Solar.fromYmdHms(
trueSolar.getFullYear(),
trueSolar.getMonth() + 1,
trueSolar.getDate(),
input.unknownHour ? 12 : trueSolar.getHours(),
input.unknownHour ? 0 : trueSolar.getMinutes(),
0,
);
const lunar = solar.getLunar();
const ec = lunar.getEightChar();
const genderCode = input.gender === "male" ? 1 : 0;
const yun = ec.getYun(genderCode);
const currentYear = new Date().getFullYear();
const liuNian: { year: number; ganZhi: string }[] = [];
for (let year = currentYear - 2; year <= currentYear + 3; year++) {
const yearSolar = Solar.fromYmdHms(year, 6, 1, 12, 0, 0);
liuNian.push({
year,
ganZhi: yearSolar.getLunar().getYearInGanZhi(),
});
}
const daYunList = yun.getDaYun();
const daYunItems: DaYunInfo[] = [];
let age = yun.getStartYear();
for (const dy of daYunList) {
const gz = dy.getGanZhi();
if (!gz) {
continue;
}
daYunItems.push({ ganZhi: gz, startAge: age });
age += 10;
if (daYunItems.length >= 8) {
break;
}
}
return {
birthTime: formatDateTime(localTime),
trueSolarTime: formatDateTime(trueSolar),
unknownHour: !!input.unknownHour,
lunarDate: lunar.toString(),
pillars: {
year: buildPillar(
ec.getYear(),
ec.getYearShiShenGan(),
ec.getYearShiShenZhi(),
ec.getYearHideGan(),
ec.getYearNaYin(),
),
month: buildPillar(
ec.getMonth(),
ec.getMonthShiShenGan(),
ec.getMonthShiShenZhi(),
ec.getMonthHideGan(),
ec.getMonthNaYin(),
),
day: buildPillar(
ec.getDay(),
ec.getDayShiShenGan(),
ec.getDayShiShenZhi(),
ec.getDayHideGan(),
ec.getDayNaYin(),
),
time: buildPillar(
input.unknownHour ? "不详" : ec.getTime(),
input.unknownHour ? "—" : ec.getTimeShiShenGan(),
input.unknownHour ? [] : ec.getTimeShiShenZhi(),
input.unknownHour ? [] : ec.getTimeHideGan(),
input.unknownHour ? "—" : ec.getTimeNaYin(),
),
},
daYun: {
startYear: yun.getStartYear(),
startMonth: yun.getStartMonth(),
startDay: yun.getStartDay(),
items: daYunItems,
},
liuNian,
shenSha: {
ji: lunar.getDayJiShen(),
xiong: lunar.getDayXiongSha(),
},
};
}
export function formatBaziForPrompt(chart: BaziChart): string {
const p = chart.pillars;
const lines = [
`出生时间:${chart.birthTime}`,
`真太阳时:${chart.trueSolarTime}${chart.unknownHour ? "(时辰不详,按中午排盘)" : ""}`,
`农历:${chart.lunarDate}`,
"",
"【四柱】",
`年柱:${p.year.ganZhi}(天干十神:${p.year.shiShenGan},地支十神:${p.year.shiShenZhi.join("、")},藏干:${p.year.hideGan.join("、")},纳音:${p.year.naYin}`,
`月柱:${p.month.ganZhi}(天干十神:${p.month.shiShenGan},地支十神:${p.month.shiShenZhi.join("、")},藏干:${p.month.hideGan.join("、")},纳音:${p.month.naYin}`,
`日柱:${p.day.ganZhi}(天干十神:${p.day.shiShenGan},地支十神:${p.day.shiShenZhi.join("、")},藏干:${p.day.hideGan.join("、")},纳音:${p.day.naYin}`,
`时柱:${p.time.ganZhi}(天干十神:${p.time.shiShenGan},地支十神:${p.time.shiShenZhi.join("、") || "—"},藏干:${p.time.hideGan.join("、") || "—"},纳音:${p.time.naYin}`,
"",
`【大运】起运 ${chart.daYun.startYear}${chart.daYun.startMonth}${chart.daYun.startDay}`,
chart.daYun.items.map((d) => `${d.startAge}岁起 ${d.ganZhi}`).join(" → "),
"",
`【流年】${chart.liuNian.map((l) => `${l.year}(${l.ganZhi})`).join("、")}`,
"",
`【神煞】吉神:${chart.shenSha.ji.join("、") || "无"};凶煞:${chart.shenSha.xiong.join("、") || "无"}`,
];
return lines.join("\n");
}