Skip to main content

x-iztro

crates.io PyPI Go Reference License: MIT

中文文档:README.zh-CN.md

Give it a birth date and hour; get back a complete Zi Wei Dou Shu (紫微斗数, Purple Star Astrology) chart — twelve palaces, every star with its brightness and transformation, decadal and annual horoscopes — as typed objects in Rust, Python, or Go, plus a single call that renders the whole chart as text you can hand straight to an LLM.

What the LLM-ready output looks like

from x_iztro import Astro

astro = Astro()
chart = astro.by_solar("2000-8-16", 2, "female")
print(astro.astrolabe_to_prompt(chart))
=== 基本信息 ===
性别: 女
阳历: 2000-8-16
农历: 二〇〇〇年七月十七
干支: 庚辰 甲申 丙午 庚寅
时辰: 寅时 (03:00~05:00)
星座: 狮子座
生肖: 龙
命宫地支: 午
身宫地支: 戌
命主: 破军
身主: 文昌
五行局: 木三局
生年四化: 太阳禄, 武曲权, 太阴科, 天同忌

=== 十二宫 ===

--- 财帛 ---
天干地支: 戊寅
大限: 43-52
小限虚岁: 9, 21, 33, 45, 57, 69, 81, 93, 105, 117
十二神: 绝, 飞廉, 吊客, 岁驿
主星: 武曲(得)[权], 天相(庙)
辅星: 天马
杂耀: 解神, 三台, 天寿, 天巫, 天厨, 阴煞, 天哭

--- 夫妻 [来因] ---
天干地支: 庚辰
大限: 23-32
小限虚岁: 7, 19, 31, 43, 55, 67, 79, 91, 103, 115
十二神: 死, 将军, 岁建, 华盖
主星: 七杀(庙)
辅星: 右弼, 火星(陷)
杂耀: 封诰, 华盖

... (all twelve palaces)

The same text is available in six languages. Pass language="en-US" and the same chart renders as:

=== Basic Info ===
Gender: female
Solar Date: 2000-8-16
Time: Tiger hour (03:00~05:00)
Soul Star: rebel
Five Elements Class: wood 3rd
Birth-Year Mutagen: sunA, generalB, moonC, fortunateD

--- wealth ---
Decadal: 43-52
Twelve Gods: dissipated, gossip, sorrowing, varied
Major Stars: general([+1])[B], minister([+3])
Minor Stars: horse
...

horoscope_to_prompt does the same for a horoscope at a given date.

Why not just ask the LLM to cast the chart?

Casting a chart is arithmetic, not interpretation: lunar/solar conversion, leap month handling, sexagenary cycle, the placement rules for ~100 stars, and the 四化 transformation table. A language model gets some of it right and quietly gets the rest wrong, and you cannot tell which from the output. This library does the arithmetic deterministically and verifiably, then hands the LLM the part it is actually good at — reading the chart.

Install

Rust

[dependencies]
x-iztro = "0.2"

Python — requires 3.10+, ships as an abi3 wheel with zero runtime dependencies.

pip install x-iztro

Go — the core library is embedded as WebAssembly and driven by the pure-Go wazero runtime: no cgo, no Rust toolchain, cross-compilation works as usual.

go get github.com/x-haose/x-iztro/go/iztro

Quick start

Rust

use x_iztro::{by_solar, IztroError};
use x_iztro::data::types::*;

fn main() -> Result<(), IztroError> {
    let chart = by_solar(
        "2000-8-16",        // solar birth date
        2,                  // hour index: 0 = early Rat hour … 12 = late Rat hour
        Gender::Female,
        true,               // fix_leap: split leap months at the midpoint
        Language::ZhCN,
        Config::default(),  // boundaries and school; defaults match JS iztro
    )?;

    // Translated strings; `soul` and `five_elements_class` are language-independent
    // keys (`StarKey::PojunMaj`, `FiveElementsClass::Wood3rd`).
    println!("{} / {}", chart.lunar_date, chart.chinese_date);
    println!("{:?} {:?}", chart.soul, chart.five_elements_class);

    // `horoscope` derefs to the data, so the six levels are plain fields.
    let horoscope = chart.horoscope("2024-1-1", 0)?;
    println!("{:?}", horoscope.yearly.base.mutagen);

    // Bad input is an error, never a panic.
    assert!(by_solar("2000-13-1", 2, Gender::Male, true, Language::ZhCN, Config::default()).is_err());
    Ok(())
}

Python

from x_iztro import Astro, IztroError
from x_iztro.enums import MajorStar, Mutagen, PalaceName

chart = Astro().by_solar("2000-8-16", 2, "female")
print(chart.chinese_date, chart.soul, chart.five_elements_class)

# Enums are language-independent keys, so these checks give the same answer
# no matter which language the chart was rendered in.
soul = chart.palace(PalaceName.SOUL)
print(soul.has([MajorStar.ZIWEI]), soul.has_mutagen(Mutagen.LU))

horoscope = chart.horoscope("2024-1-1", 0)
print(horoscope.yearly.heavenly_stem, horoscope.yearly.earthly_branch)

# IztroError subclasses ValueError; .code is a machine-readable category.
try:
    Astro().by_solar("2000-13-1", 2, "male")
except IztroError as e:
    print(e.code)  # invalid_date

Go

package main

import (
    "errors"
    "fmt"
    "log"

    "github.com/x-haose/x-iztro/go/iztro"
)

func main() {
    chart, err := iztro.BySolar("2000-8-16", 2, iztro.GenderFemale, true, iztro.LanguageZhCN, nil)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(chart.ChineseDate, chart.Soul, chart.FiveElementsClass)

    soul := chart.Palace(iztro.PalaceSoul)
    fmt.Println(soul.Has(iztro.StarZiweiMaj), soul.HasMutagen(iztro.MutagenLu))

    horoscope, err := chart.Horoscope("2024-1-1", 0)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(horoscope.Yearly.HeavenlyStem, horoscope.Yearly.EarthlyBranch)

    // Errors carry a category you can match with errors.Is.
    _, err = iztro.BySolar("2000-13-1", 2, iztro.GenderMale, true, iztro.LanguageZhCN, nil)
    fmt.Println(errors.Is(err, iztro.ErrInvalidDate)) // true
}

Features

  • Full chart — twelve palaces, body palace, soul/body stars, five elements class, major/minor/adjective stars with brightness and 四化 transformations.
  • Six horoscope levels — decadal, yearly, monthly, daily, hourly and the childhood limit, each with its own palaces and transformations.
  • Chart queries — locate a palace by name, branch or index; test stars, transformations and empty palaces; the 三方四正 surrounded-palace group; and the flying-star (飞星) family.
  • Pattern judgement — 64 named star arrangements (格局), one rule set shared by natal charts and horoscope views, each hit carrying the palace it formed in, the reading that matched, and the evidencing stars. iztro has no such API.
  • Knowledge packs — reading texts and school-specific star attributes live in a swappable JSON pack, not in the core. A default pack ships inside (107 stars, 64 patterns, 12 palaces, 4 transformations, 49 glossary entries, zh-CN, from iztro-docs by Sylar Long, MIT); write an overlay to replace any entry.
  • Reverse lookup — solar_dates_by_bazi recovers solar birth dates from four BaZi pillars (interpreted under the chart Config), and reverse_chart recovers them from chart features — soul/body palace branches, five elements class, star placements, birth-year mutagens. Pruned enumeration verified by full re-charting: zero divergence from forward casting. iztro has no such API.
  • Two schools — the default school and 中州派 (Zhongzhou), selected per chart.
  • Six languages — zh-CN, zh-TW, en-US, ja-JP, ko-KR, vi-VN, with language-independent key constants so your logic never depends on the display language.
  • LLM output — astrolabe_to_prompt / horoscope_to_prompt render a whole chart as structured text.
  • Validated input — date format and existence, solar years 1583–9999, hour index 0–12. Invalid input returns Err(IztroError) in Rust, raises x_iztro.IztroError (a ValueError) in Python, returns an error matchable with errors.Is in Go, and yields {"error":"..."} JSON over the C FFI. Every failure carries a machine-readable category. Nothing panics.

Pattern judgement

chart = astro.by_solar("1985-5-3", 9, "male", language="en-US")

for hit in chart.patterns():
    print(hit.name, hit.palace_name, hit.broken)
General and Wolf Together surface False
Empress and Minister Facing the Palace soul False
Marshal, Rebel and Wolf surface False
Money and Horse Galloping Together soul False
Officer and Helper Flanking Life soul False
Literary Nobility and Brilliance surface False
Literary Stars Facing Life soul True
Literary Stars in Hidden Support soul False
Literary Stars in Hidden Support soul False

The judging principles and the full table of 64 patterns are on the documentation site.

Knowledge packs

The default pack is Chinese, so pair it with a hit's language-independent key rather than its translated name:

from x_iztro import KnowledgePack

pack = KnowledgePack.builtin()
chart = astro.by_solar("2000-8-16", 2, "female", language="en-US")

for hit in chart.patterns():
    print(hit.name, "|", pack.pattern(hit.key).quotes[0])
Empress and Minister Facing the Palace | 府相朝垣命必荣

The pack format, the merge rules and how to write an overlay are on the documentation site.

Reverse lookup

from x_iztro import solar_dates_by_bazi

# every solar birth moment in 1900-2100 with the pillars 庚辰 甲申 丙午 庚寅
for c in solar_dates_by_bazi(
    ("gengHeavenly", "chenEarthly"), ("jiaHeavenly", "shenEarthly"),
    ("bingHeavenly", "wuEarthly"), ("gengHeavenly", "yinEarthly"),
):
    print(c.solar_date, c.time_index)
1940-8-31 2
2000-8-16 2
2060-8-1 2

Chart-feature lookup, how the pillars follow the Config boundaries, and the truncation semantics are on the documentation site.

Accuracy

Every number is checked field-by-field against the JavaScript iztro v2.5.8 (version-pinned), with zero tolerance for differences. Roughly 710,000 golden cases in eight layers:

Layer Cases Coverage
Tier 1 1,560 60 years × 13 hours × both genders, every field compared individually
Tier 2 37,440 60 years × the 1st and 15th of each month × 13 hours × both genders
Tier 3 586,430 every day of 60 years × 13 hours × both genders × fix_leap, hashed
Edge years 46,228 the far ends of the supported range, where leap months and tables strain
Horoscope 5,760 360 charts × 16 target dates, all six horoscope levels, every field
Variants 14,268 lunar-date charts across leap months, Zhongzhou school, all six languages
Config 9,696 each boundary switch at its non-default value
Astro type 12,488 the heaven / earth / human chart perspectives

On top of that: the serialization contract is compared key-by-key against JS JSON.stringify, and the three bindings are cross-checked so that the same birth data yields the same answers in Rust, Python and Go.

cargo test                                               # regular layers, ~15s
cargo test --release --test golden_tier3 -- --ignored    # Tier 3 in full, ~20s

Configuration

Six switches, passed explicitly per chart — there is no global state.

Switch Values Default Effect
year_divide normal / exact normal Year boundary: lunar new year, or 立春
horoscope_divide normal / exact normal Horoscope boundary: 1st of the month, or solar term
age_divide normal / birthday normal Nominal age: increments at new year, or on the birthday
day_divide forward / current forward Late Rat hour belongs to the next day, or the current one
algorithm default / zhongzhou default School of placement rules
astro_type heaven / earth / human heaven Chart perspective (Zhongzhou)

Custom 四化 and brightness tables can be supplied alongside them.

Documentation

https://ziwei.x-hoase.com — the documentation site, in Chinese and English: a guide that starts from zero, the Zi Wei concepts behind the data model, and per-language API references where every function, type and method has its own entry with real output and edge-case notes. LLM-friendly endpoints: /llms.txt, /llms-full.txt, and any page with .md appended.

The site lives in docs/ (cd docs && npm ci && npm run dev to run it locally). Rust API docs are also published at docs.rs/x-iztro. Runnable projects for all three languages are under examples/.

Building from source

Only needed when changing the Rust core.

cargo build --release

# Python bindings
PYO3_USE_ABI3_FORWARD_COMPATIBILITY=1 maturin develop --features python

# Go bindings: rebuild and refresh the embedded wasm
cargo build --release --target wasm32-wasip1
cp target/wasm32-wasip1/release/x_iztro.wasm go/iztro/

Golden test data is generated from the JS iztro package:

cd tests/golden && npm install && node generate_tier1.mjs   # …and the other generators

Credits

Ported from iztro by SylarLong. New to Zi Wei Dou Shu? Its author maintains an introduction at iztro.com.

License

MIT

Metadata

Release files for x-iztro 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for x-iztro 0.3.0
File Size Uploaded
x_iztro-0.3.0.tar.gz 327.7 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for x-iztro 0.3.0
File
x_iztro-0.3.0-cp310-abi3-win_amd64.whl CPython 3.10 abi3 Windows x86-64 Details
x_iztro-0.3.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.10 abi3 Linux glibc 2.17+ x86-64 Details
x_iztro-0.3.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.10 abi3 Linux glibc 2.17+ ARM64 Details
x_iztro-0.3.0-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl CPython 3.10 abi3 macOS 10.12+ universal2 (ARM64, x86-64), macOS 10.12+ x86-64, macOS 11.0+ ARM64 Details

Total release size: 5.1 MB

Release files / x_iztro-0.3.0.tar.gz

Download URL x_iztro-0.3.0.tar.gz
Size 327.7 kB
Tags Source
SHA-256 checksum
How to use checksums
4af458b2998197fba98f32f5eadeaeba3d613f21c8186861b8d73335aa090f22
BLAKE2b-256 checksum
How to use checksums
1f00bb5ab77ab6a1bfb1aaeb67e89720f0005849327926a143816c6fda22c223
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 20, 2026.

Transparency log

Release files / x_iztro-0.3.0-cp310-abi3-win_amd64.whl

Download URL x_iztro-0.3.0-cp310-abi3-win_amd64.whl
Size 847.5 kB
Tags CPython 3.10 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
a04e97ab39dcb0e616a92cd682cc00d63cee0980430239c1348efcb97fd43c6e
BLAKE2b-256 checksum
How to use checksums
49c9ef5023f35c9edc2f38170a3bc4c76a2af314c4502594b144b40057faac72
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 20, 2026.

Transparency log

Release files / x_iztro-0.3.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL x_iztro-0.3.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 1.1 MB
Tags CPython 3.10 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
e12ba6f1491f0614088dec8b1545649d0e40288e184f8ee9398552ac89ae0d42
BLAKE2b-256 checksum
How to use checksums
1cce6da155e162da393749b3212a30757e1f5d5e733a0b2e36f78f5b12d9cfc1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 20, 2026.

Transparency log

Release files / x_iztro-0.3.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL x_iztro-0.3.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 1.0 MB
Tags CPython 3.10 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
14253b55ee28c4c60816f3a9c05fb9853b289a717a7ed5ca8575c45ea316638b
BLAKE2b-256 checksum
How to use checksums
1d21c09174c95467400a999fdca87921a78c44176513410109509214e56e8889
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 20, 2026.

Transparency log

Release files / x_iztro-0.3.0-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl

Download URL x_iztro-0.3.0-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Size 1.8 MB
Tags CPython 3.10 abi3 macOS 10.12+ universal2 (ARM64, x86-64) macOS 10.12+ x86-64 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
aa1941b7f2ae8baca4668c66bb86461a3ab02f4a22f2884cf280fd99b68f1505
BLAKE2b-256 checksum
How to use checksums
62a0242d40ff8dfe18a70b9860e2b456582e0c5d3515e45c00b77580faa614f2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 20, 2026.

Transparency log

Release history Release notifications | RSS feed

0.6.1

5 release files

0.6.0

5 release files

0.5.0

5 release files

0.4.0

5 release files

This release

0.3.0 This release

5 release files

0.2.0

5 release files

0.1.1

5 release files

0.1.0

5 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page