Open-source BaZi (Four Pillars of Destiny, 八字) calculation engine in pure TypeScript. Zero dependencies.
This is the exact engine running in production at Stillness Dao 靜為道 — try it live: free Bazi calculator · 免費八字排盤 · Bazi compatibility.
Most open Bazi code gets the pillars roughly right and everything else wrong. This engine treats the chart as an astronomy problem first:
- True solar time — longitude correction + equation of time, computed from birth coordinates, not just a time zone. A birth in Ürümqi (87.6°E, clock UTC+8) is corrected by −143 minutes, which changes the hour pillar — see the example below.
- Astronomical solar terms — month and year pillars follow apparent solar longitude (節氣), not calendar months. Births near 立春 or any Jie boundary are handled by real boundary timestamps, not lookup-table approximations.
- Honest uncertainty — unknown birth hours produce a
nullhour pillar and a lowered confidence score instead of a silently guessed midnight.
- Four Pillars with Heavenly Stems & Earthly Branches (year / month / day / hour)
- True solar time context: correction minutes, method, standard meridian
- Hidden stems (藏干), Ten Gods (十神), Nayin (納音), void branches (空亡), fetal origin (胎元), twelve growth phases (十二長生)
- Shen Sha (神煞) star detection
- Day Master strength & useful-god candidates (用神候選)
- Ten-year luck pillars (大運) with computed start age & direction
- Annual flow (流年) and monthly flow (流月, solar-term based)
- Late Zi hour rule option (
lateZiRule: "next-day" | "same-day", 晚子時換日/不換日) - Two-chart compatibility scoring (合婚)
- Confidence score + warnings describing exactly what lowered chart certainty
# not yet on npm — use directly from source
git clone https://github.com/David88666/bazi-engine.git
cd bazi-engine && npm run buildimport { calculateBaziChart } from "@stillnessdao/bazi-engine";
const chart = await calculateBaziChart({
birthDate: "1990-02-04",
birthTime: "23:30",
birthPlaceText: "Ürümqi, China",
timezone: "Asia/Shanghai",
gender: "female",
latitude: 43.83,
longitude: 87.62,
lateZiRule: "next-day"
});
console.log(chart.fourPillars);
// year 庚午 · month 戊寅 · day 庚子 · hour 丁亥
// clock said 子時 (23:30) — true solar time says 亥時 (21:06),
// because Ürümqi sits 32° west of the UTC+8 meridian.
console.log(chart.timeContext.totalCorrectionMinutes); // -143.6
console.log(chart.timeContext.method); // "true_solar_time"Run the bundled example:
npm run example| Export | What it does |
|---|---|
calculateBaziChart(input) |
Full chart: pillars, hidden stems, Ten Gods, Shen Sha, luck pillars, annual + monthly flow, confidence |
scoreBaziCompatibility(a, b) |
Two-chart relationship scoring (Day Master interaction, branch clashes/combines, element balance) |
buildBaziMonthlyFlow(...) |
Solar-term-based monthly Gan-Zhi flow for any year |
BAZI_CALCULATION_VERSION |
Engine version string recorded into every result |
All input/output types are exported (BaziInput, BaziResult, Pillar, …) — the result object is fully typed and serializable.
- Month/year boundaries use apparent solar longitude with minute-level boundary timestamps.
- Time zone handling uses the IANA database (via
Intl), so historical DST is respected. - With no coordinates, the engine falls back to civil time and says so (
method: "civil_time_fallback", confidence penalty) — it never pretends. - Interpretation is intentionally out of scope: this library computes the chart; what it means is your product's job. If you want to see one opinionated interpretation layer, that's what Stillness Dao builds on top — question-first readings in English, Traditional and Simplified Chinese, without doom-selling.
An MCP (Model Context Protocol) wrapper lives in mcp/ — one calculate_bazi tool so AI agents (Claude Code, Claude Desktop, any MCP client) can generate accurate charts locally, no API key. See mcp/README.md.
- npm publish
- Zi Wei Dou Shu (紫微斗數) engine extraction
MIT © Stillness Dao — free for commercial use. If this engine saves you a week of solar-term debugging, a star ⭐ or a link back to stillnessdao.com is appreciated.