@openfate/bazi-engine
v1.1.0
Published
Accurate Four Pillars (八字) chart engine with True Solar Time correction, Da Yun cycles, and interaction detection. Extracted from the OpenFate.ai core engine.
Maintainers
Readme
@openfate/bazi-engine
A deterministic, production-oriented Four Pillars (八字) engine for JavaScript and TypeScript. Powered by OpenFate.ai — the AI-native metaphysical analysis platform.
Getting the Four Pillars right is hard. Solar Term boundaries (节气), True Solar Time correction (真太阳时), day-change boundaries, and lunar conversion all require explicit, testable policy. This package exposes those calculations and the metadata needed to audit them.
Why use this?
| Problem | Without this package | With @openfate/bazi-engine |
|---|---|---|
| True Solar Time | Complex astronomy, most ignore it | Built-in via @openfate/true-solar-time |
| Solar Term boundaries | Easy to get LiChun wrong | Handles all 24 节气 precisely |
| Zi Hour boundary (23:00) | Confusing, often skipped | Configurable dayBoundaryMode |
| Lunar Calendar conversion | Requires separate library | Built-in, one function call |
| Interaction detection | Implement 7 types yourself | All 7 types detected, zero effort |
Use Cases
1. 🔮 Bazi Consulting Software / CRM
Professional Fengshui consultants manage hundreds of clients. Build a dashboard that generates accurate charts on-demand:
const chart = calculateBaziChart({ year: 1985, month: 3, day: 12, hour: 9,
gender: 'male', longitude: 121.47, timezone: 8 });
// Render chart.pillars in your UI, show chart.daYun timelineNo more relying on unreliable online tools or expensive licensed software — own your calculation stack.
2. 💌 Matchmaking & Dating Apps
Check compatibility by comparing two users' charts:
const userA = calculateBaziChart({ ... });
const userB = calculateBaziChart({ ... });
// Do their Day Masters combine? (六合)
const combined = detectInteractions(
{ year: userA.pillars.year.branch, month: userA.pillars.month.branch,
day: userA.pillars.day.branch, hour: userA.pillars.hour?.branch ?? '' },
userB.pillars.day.branch // Check against UserB's Day Branch
);
const compatible = combined.some(i => i.type === 'COMBINATION_2');3. 📅 Daily Horoscope / Almanac Push Notifications
Calculate today's pillar and send personalized notifications:
const today = new Date();
const todayChart = calculateBaziChart({
year: today.getFullYear(), month: today.getMonth()+1, day: today.getDate(),
hour: 12, gender: 'male'
});
// If today's Day Branch clashes with user's Day Branch → alert!
const todayBranch = todayChart.pillars.day.branch;4. 🤖 AI Metaphysics Agents / Discord Bots
Feed the structured JSON into your own AI agent:
const chart = calculateBaziChart({ ... });
// Pass to OpenAI / Claude with your own prompts
const prompt = `Analyze this Bazi chart: ${JSON.stringify(chart.pillars)}
Major cycles: ${chart.daYun.cycles.map(c => c.ganZhi).join(', ')}
Key interactions: ${chart.interactions.map(i => i.description).join(', ')}`;You get the data layer right with this package, then apply your own interpretation model on top.
5. 🏫 Education & Research
Teach traditional metaphysics with accurate, verifiable data. All outputs are explainable — solarTimeInfo shows exactly how True Solar Time was calculated.
Installation
npm install @openfate/bazi-engineQuick Start
import { calculateBaziChart } from '@openfate/bazi-engine';
const chart = calculateBaziChart({
year: 1998, month: 12, day: 13,
hour: 12, minute: 0,
gender: 'female',
// Location — enables True Solar Time correction
longitude: 116.39, // Beijing
timezone: 8, // UTC+8
});
// Four Pillars
console.log(chart.pillars.year.stem + chart.pillars.year.branch); // 戊寅
console.log(chart.pillars.month.stem + chart.pillars.month.branch); // 甲子
console.log(chart.pillars.day.stem + chart.pillars.day.branch); // 甲午
console.log(chart.pillars.hour!.stem + chart.pillars.hour!.branch); // 庚午
// Day Master
console.log(chart.dayMaster.pinyin); // 'jia'
console.log(chart.dayMaster.element); // 'wood'
// Major Luck Cycles (大运)
chart.daYun.cycles.forEach(cycle => {
console.log(`Age ${cycle.startAge}: ${cycle.ganZhi}`);
});
// Branch Interactions
chart.interactions.forEach(i => {
console.log(`${i.type}: ${i.description}`);
});
// True Solar Time details
console.log(chart.solarTimeInfo?.trueSolarTime); // '12:09'Lunar Calendar Input
const chart = calculateBaziChart({
year: 1998, month: 10, day: 25, // Lunar date
calendarType: 'lunar',
hour: 12, gender: 'male', longitude: 116.39, timezone: 8,
});
// Automatically converts to Solar 1998-12-13 before calculatingConfiguration
calculateBaziChart({
// ...
enableTrueSolarTime: true, // default: true (requires longitude)
dayBoundaryMode: 'MIDNIGHT_00', // 'MIDNIGHT_00' (default) or 'ZI_HOUR_23' (traditional)
calendarType: 'solar', // 'solar' (default) or 'lunar'
dstOffset: 1, // For historical/DST dates (e.g. China pre-1992)
});API Reference
calculateBaziChart(input: BaziInput): BaziChart
Main entry point. Returns a BaziChart with:
pillars— Four Pillars (year, month, day, hour)dayMaster— Day Master stem with element, polarity, pinyindaYun— 9 Major Luck Cycles with start year/ageinteractions— All detected branch interactions (7 types)solarTimeInfo— True Solar Time details (or null if disabled)calendar— Civil solar input, calculation solar time, converted lunar date, and zodiacmetadata— Applied True Solar Time, timezone, DST, and day-boundary policy
Each pillar preserves the simple stem, branch, and element fields and also includes Ten Gods, hidden stems, Na Yin, Xun, void branches, and growth stage.
detectInteractions(natal, annualBranch?): BranchInteraction[]
Detect interactions in a natal chart, optionally against an annual branch (太岁).
generatePillarsFromSolar(...): PillarResult
Low-level pillar generator — use when you've already handled time correction yourself.
🛡️ Testing & Reliability
Bazi calculations are notoriously prone to edge-case bugs. We maintain a regression suite of 100+ calendrical cases plus focused public-contract tests:
- 24 Solar Terms: Minute-level precision for Li Chun, Jing Zhe, etc.
- Early/Late Zi Hour: Handles the 23:00 day-rollover across month/year boundaries.
- Global Distortion: Extreme longitudes (e.g., Xinjiang, Iceland) and fractional timezones (e.g., India UTC+5.5).
- Historical DST: Explicit
dstOffsetinput or IANA timezone rules; the engine does not guess historical policy. - Century Boundaries: Regression coverage for dates across 1800, 1900, 2000, and 2100.
- Da Yun: Exact start date, elapsed-age convention, direction, and cycle boundaries.
- Factual Enrichment: Ten Gods, hidden stems, Na Yin, Xun, void branches, and growth stages.
Run the tests yourself:
npm testHow It Works
Birth input (civil time)
↓
[@openfate/true-solar-time] ← Longitude correction + Meeus Equation of Time
↓
True Solar Time
↓
[lunar-javascript] ← Solar Term boundary detection + Ganzhi calculation
↓
Four Pillars → Da Yun → Interactions🔗 Try the Full Engine
@openfate/bazi-engine gives you the data. OpenFate.ai gives you the complete AI-powered interpretation — relationship analysis, career forecasting, and interactive AI chat with your chart.
GitHub Pages Site
This repository now includes a static GitHub Pages microsite in docs/index.html.
To publish it:
- Push the repository to GitHub on the
mainbranch. - In the repository settings, open
Pages. - Under
Build and deployment, selectGitHub Actions. - Push a new commit or manually run the
Deploy GitHub Pagesworkflow.
If the workflow fails with Get Pages site failed:
- The repository does not have GitHub Pages enabled yet.
- The fastest fix is to open
Settings->Pagesand setSourcetoGitHub Actions, then rerun the workflow. - Optional: create a repository secret named
PAGES_TOKENwith a token that can administer Pages. The workflow will then try to enable Pages automatically on the first run.
Once enabled, the site will publish at:
https://openfate-ai.github.io/bazi-engine/for the current repository name- or
https://<owner>.github.io/<repo>/for forks and renamed repositories
License
MIT — Free to use, modify, and distribute commercially.
