npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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.

Readme

@openfate/bazi-engine

NPM Version License

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 timeline

No 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-engine

Quick 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 calculating

Configuration

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, pinyin
  • daYun — 9 Major Luck Cycles with start year/age
  • interactions — 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 zodiac
  • metadata — 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 dstOffset input 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 test

How 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:

  1. Push the repository to GitHub on the main branch.
  2. In the repository settings, open Pages.
  3. Under Build and deployment, select GitHub Actions.
  4. Push a new commit or manually run the Deploy GitHub Pages workflow.

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 -> Pages and set Source to GitHub Actions, then rerun the workflow.
  • Optional: create a repository secret named PAGES_TOKEN with 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.