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.
| 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 |
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.
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');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;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.
Teach traditional metaphysics with accurate, verifiable data. All outputs are explainable — solarTimeInfo shows exactly how True Solar Time was calculated.
npm install @openfate/bazi-engineimport { 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'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 calculatingcalculateBaziChart({
// ...
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)
});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.
Detect interactions in a natal chart, optionally against an annual branch (太岁).
Low-level pillar generator — use when you've already handled time correction yourself.
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 testBirth 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
@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.
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
MIT — Free to use, modify, and distribute commercially.