Package Exports
- @aharris02/bazi-calculator-by-alvamind
- @aharris02/bazi-calculator-by-alvamind/package.json
Readme
Bazi Calculator (TypeScript Port)
⚠️ This is a fork of the original bazi-calculator-by-alvamind and incorporates work from bazica by tommitoan, published by @aharris02 for compatibility with modern TypeScript builds and deployment environments (e.g. Vercel).
A modern, accurate, and comprehensive Bazi (八字 / Four Pillars of Destiny) calculator and analyzer with robust timezone handling and advanced features.
📢 Disclaimer
This package is provided for educational and research purposes only. The calculations and interpretations should not be used as the sole basis for making important life decisions. Chinese Metaphysics and Bazi analysis require professional expertise and years of study.
✨ Key Features
Core Calculations
- Four Pillars (四柱) Calculation: Accurate Year, Month, Day, and Hour pillar determination
- Timezone-Aware Processing: Requires IANA timezone strings (e.g.,
America/New_York
,Asia/Shanghai
) - Unknown Birth Time Handling: Gracefully calculates when exact birth time is unknown
- Luck Pillars Calculation: Determines 10-year Luck Pillar sequence with direction and precise start age
- Gender Normalization: Accepts various gender inputs but normalizes to
'male'
or'female
, since Bazi is based on binary genders
Analysis Components
- Five Elements (五行) Analysis: Element distribution with relationship weighting
- Day Master (日主) Analysis: Stem, Element, Yin/Yang properties
- Eight Mansions (八宅) Feng Shui: Life Gua calculation with favorable/unfavorable directions
- Destiny Indicators: Nobleman (貴人), Intelligence Star (文昌), Sky Horse (天馬), Peach Blossom (桃花)
Technical Features
- 🔒 Type-safe with TypeScript
- 📦 ES Module Support
- 🌐 Timezone-correct calculations via date-fns-tz
- 📝 Comprehensive Type Definitions
- ⚡ Optimized Performance
🚀 Installation
# Using npm
npm install @aharris02/bazi-calculator-by-alvamind date-fns date-fns-tz
# Using yarn
yarn add @aharris02/bazi-calculator-by-alvamind date-fns date-fns-tz
# Using pnpm
pnpm add @aharris02/bazi-calculator-by-alvamind date-fns date-fns-tz
Note: This library requires
date-fns
anddate-fns-tz
as peer dependencies for robust date and timezone handling.
🎯 Quick Start
import { BaziCalculator } from '@aharris02/bazi-calculator-by-alvamind';
import { toDate } from 'date-fns-tz'; // Essential for timezone-aware Date creation
// Define Birth Details
const dateString = '1990-05-10T12:30:00';
const timezone = 'Asia/Shanghai';
const gender = 'male';
// Create a timezone-aware Date object (IMPORTANT!)
const birthDate = toDate(dateString, { timeZone: timezone });
// Initialize calculator with modern constructor
const calculator = new BaziCalculator(
birthDate, // Date object (timezone-aware)
gender, // Gender ('male' or any other string -> 'female')
timezone, // IANA Timezone string
true // Is birth time known? (default: true)
);
// Get complete analysis
const analysis = calculator.getCompleteAnalysis();
// Display Chinese characters
console.log(calculator.toString()); // 庚午年辛巳月乙酉日壬午時
📖 Detailed Documentation
Birth Time Known Example
import { BaziCalculator } from '@aharris02/bazi-calculator-by-alvamind';
import { toDate, formatInTimeZone } from 'date-fns-tz';
import { isValid } from 'date-fns';
// 1. Define Birth Details
const year = 1995;
const month = 6; // 1-12
const day = 8;
const hour = 22; // 0-23
const minute = 5;
const gender = 'male'; // or 'female', 'nonbinary', 'other', etc.
const timeZone = 'Asia/Ho_Chi_Minh'; // IANA Timezone String is crucial!
const isTimeKnown = true; // Explicitly state time is known
// 2. Create a Timezone-Aware Date Object
// IMPORTANT: Use date-fns-tz's toDate for correct initial parsing
const dateString = `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}T${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}:00`;
const birthDate = toDate(dateString, { timeZone });
if (!isValid(birthDate)) {
console.error("Invalid Date constructed. Check inputs and timezone.");
// Handle error appropriately
} else {
// 3. Instantiate the Calculator
// Gender normalizes internally: non-'male' inputs become 'female' for calculations
const calculator = new BaziCalculator(birthDate, gender, timeZone, isTimeKnown);
// 4. Get the Complete Analysis
const analysis = calculator.getCompleteAnalysis();
if (analysis) {
console.log("--- Four Pillars (Simple) ---");
console.log(analysis.mainPillars);
// Example: { year: {...}, month: {...}, day: {...}, time: {...} }
console.log("\n--- Luck Pillars Summary ---");
if (analysis.luckPillars) {
console.log(`Direction: ${analysis.luckPillars.incrementRule === 1 ? 'Forward' : 'Backward'}`);
console.log(`Timing Known: ${analysis.luckPillars.isTimingKnown}`);
console.log(`Start Age: ${analysis.luckPillars.startAgeYears}y ${analysis.luckPillars.startAgeMonths}m ${analysis.luckPillars.startAgeDays}d`);
}
console.log("\n--- Basic Analysis ---");
console.log(analysis.basicAnalysis);
console.log("\n--- Chart String ---");
console.log(calculator.toString()); // Output: 乙亥年 壬午月 庚午日 丁亥時
}
}
Unknown Birth Time Example
import { BaziCalculator } from '@aharris02/bazi-calculator-by-alvamind';
import { toDate } from 'date-fns-tz';
import { isValid } from 'date-fns';
const year = 1995;
const month = 6;
const day = 8;
const hour = 12; // Placeholder Hour (e.g., noon)
const minute = 0; // Placeholder Minute
const gender = 'male';
const timeZone = 'Asia/Ho_Chi_Minh';
const isTimeKnown = false; // <<< Indicate time is unknown
const dateString = `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}T${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}:00`;
const birthDate = toDate(dateString, { timeZone });
if (isValid(birthDate)) {
const calculator = new BaziCalculator(birthDate, gender, timeZone, isTimeKnown);
const analysis = calculator.getCompleteAnalysis();
if (analysis) {
console.log("--- Analysis (Unknown Time) ---");
console.log("Pillars:", analysis.mainPillars);
// Output will have time: null
console.log("Pillars String:", calculator.toString());
// Output: 乙亥年 壬午月 庚午日 ??時
console.log("Luck Pillars Timing Known:", analysis.luckPillars?.isTimingKnown);
// Output: false
console.log("Luck Pillars Start Age:", analysis.luckPillars?.startAgeYears);
// Output: null
console.log("Five Factors:", analysis.basicAnalysis?.fiveFactors);
// Output: May be less accurate or null if calculation requires hour
}
}
API Reference
BaziCalculator Class
class BaziCalculator {
constructor(
birthDateTime: Date, // Timezone-aware Date object
genderInput?: string, // 'male', 'female', or any other (defaults to 'male')
timezoneInput?: string, // IANA timezone string (defaults to 'UTC')
isTimeKnownInput?: boolean // Whether the exact hour/minute are known (defaults to true)
)
// Main methods
calculatePillars(): Pillars | null
calculateLuckPillars(): LuckPillarsResult | null
calculateBasicAnalysis(): BasicAnalysis | null
getCompleteAnalysis(): CompleteAnalysis | null
toString(): string
}
Data Files
This library relies on internal JSON data for calculations:
lunar-new-year.json
: Used for determining the Lunar Year for the Year Pillar.solar-term.json
: Used for determining the Month Branch and Luck Pillar timing.
These files are bundled with the library.
📝 Important Notes
Calculation Methods
- Timezone-aware calculations using IANA timezone strings
- Traditional Chinese time system (12 two-hour periods)
- Standard Stem-Branch (干支) system
- Eight Mansions Feng Shui principles
- Support for unknown birth time calculations
Limitations
- Luck Pillar Start Time precision depends on solar term data
- Currently does not include 10 Gods (十神), advanced Symbolic Stars, or Pillar interaction analysis
- Calculations use standard timezone time, not Real Solar Time adjusted for longitude
- For professional consultations, please consult a qualified Bazi practitioner
🤝 Contributing
We welcome contributions! See our Contributing Guidelines for details.
📄 License
MIT License - see the LICENSE file for details.
Based on the original work by Alvamind