Astrolabe object

The fields of Astrolabe, its lookup methods, and the surrounded-palace predicates.

Astrolabe is what charting produces and the entry point for every query. It holds all the data of the twelve palaces along with chart-level information such as the four pillars, the soul and body stars and the five elements class.

let chart = by_solar("2000-8-16", 2, Gender::Female, true, Language::EnUS, Config::default())?;

The examples on this page all chart with Language::EnUS, so the display values in the output are iztro's en-US vocabulary — emperor for Ziwei, soul for the Soul palace, and so on. Charting in another language changes those strings only; the *_key fields and every predicate stay the same.

Fields


palace

Purpose Fetch a palace by index, by name, or as the body or original palace.

Zi Wei meaning The twelve palaces are the skeleton of a chart. Once the Soul palace is fixed the other eleven follow counterclockwise in a fixed order. The "body palace" is whichever of the twelve also carries that flag, marking where acquired effort concentrates; the "original palace" is the one whose stem matches the birth-year stem, marking where matters originate.

Signature

pub fn palace(&self, target: impl Into<PalaceTarget>) -> Option<PalaceRef<'_>>

Parameters

ParameterTypeRequiredDefaultDescription
targetimpl Into<PalaceTarget>YesFour spellings, see the table below

All four variants of PalaceTarget have From implementations, so you write the value directly:

SpellingExampleMeaning
Indexchart.palace(0)Palace index 0–11, where 0 is the Yin palace
Namechart.palace(Palace::Soul)One of the twelve palace names
Body palacechart.palace(PalaceTarget::Body)Whichever palace carries the body-palace flag
Original palacechart.palace(PalaceTarget::Original)The palace whose stem matches the birth-year stem

Return value Option<PalaceRef<'_>>. An out-of-range index returns None; the name, body-palace and original-palace spellings resolve on any chart and are never None.

Example

let en = Language::EnUS;

let soul = chart.palace(Palace::Soul).unwrap();
println!("{} {} {}", translate_palace(soul.name, en),
    translate_heavenly_stem(soul.heavenly_stem, en),
    translate_earthly_branch(soul.earthly_branch, en));

let body = chart.palace(PalaceTarget::Body).unwrap();
println!("body palace falls in {}", translate_palace(body.name, en));

let original = chart.palace(PalaceTarget::Original).unwrap();
println!("original palace is {}", translate_palace(original.name, en));

println!("the Yin palace is {}", translate_palace(chart.palace(0).unwrap().name, en));

PalaceData::name has the type Palace, an enum rather than a string, so it cannot be printed with {} directly — the enum is a language-independent key, and display goes through translate_palace to get text in the current language. The same holds for heavenly_stem, earthly_branch, five_elements_class and the other enum fields.

Output

soul ren woo
body palace falls in career
original palace is spouse
the Yin palace is wealth

Edge cases and pitfalls


star

Purpose Find a star by key and get a view that can trace back to its palace.

Signature

pub fn star(&self, key: StarKey) -> Option<StarRef<'_>>

Parameters

ParameterTypeRequiredDefaultDescription
keyStarKeyYesStar key, e.g. StarKey::ZiweiMaj

Return value Option<StarRef<'_>>. None when the star is not on this chart.

Example

let en = Language::EnUS;
let ziwei = chart.star(StarKey::ZiweiMaj).unwrap();

println!("{} sits in {}", ziwei.name, translate_palace(ziwei.palace().name, en));
println!("its opposite palace is {}", translate_palace(ziwei.opposite_palace().name, en));
println!("brightness {:?} mutagen {:?}", ziwei.brightness, ziwei.mutagen);

Star::name is a String (already translated into the charting language) and prints directly; PalaceData::name is an enum and goes through translate_palace.

Output

emperor sits in soul
its opposite palace is surface
brightness Some(Miao) mutagen None

Edge cases and pitfalls

The search covers only the three groups of major, minor and adjective stars. The Changsheng, Boshi, Sui-qian and Jiang-qian gods are one-per-palace marks rather than star lists — read them from fields like palace.changsheng12.


surrounded_palaces

Purpose Fetch the surrounded palaces of a target palace.

Zi Wei meaning The surrounded set is the most commonly used reading scope in Zi Wei Dou Shu: the palace itself, its opposite (index +6), the career position (+4) and the wealth position (+8). The four are read together rather than the palace alone, because the stars of the opposite and trine palaces bear on the palace's affairs just as much.

Signature

pub fn surrounded_palaces(&self, target: impl Into<PalaceTarget>) -> Option<SurroundedPalaces<'_>>

Parameters Same as palace; all four spellings are supported.

Return value Option<SurroundedPalaces<'_>>, holding the four &PalaceData values target / opposite / wealth / career (not PalaceRefs: their fields read directly, but they carry none of the methods that need the astrolabe for context, such as the opposite palace or flying stars). Its predicates are on Surrounded palaces.

Example

let en = Language::EnUS;
let sp = chart.surrounded_palaces(Palace::Soul).unwrap();

println!("{} / {} / {} / {}",
    translate_palace(sp.target.name, en), translate_palace(sp.opposite.name, en),
    translate_palace(sp.wealth.name, en), translate_palace(sp.career.name, en));
println!("Ziwei in the surrounded set: {}", sp.have(&[StarKey::ZiweiMaj]));

Output

soul / surface / wealth / career
Ziwei in the surrounded set: true

is_surrounded / is_surrounded_one_of / not_surrounded

Purpose Test the surrounded palaces of a palace straight from the astrolabe, skipping the step of fetching the set first.

Signature

pub fn is_surrounded(&self, target: impl Into<PalaceTarget>, stars: &[StarKey]) -> bool
pub fn is_surrounded_one_of(&self, target: impl Into<PalaceTarget>, stars: &[StarKey]) -> bool
pub fn not_surrounded(&self, target: impl Into<PalaceTarget>, stars: &[StarKey]) -> bool

Parameters

ParameterTypeRequiredDefaultDescription
targetimpl Into<PalaceTarget>YesLocated the same way as in palace
stars&[StarKey]YesA list of star keys

Return value

MethodMeaning
is_surroundedEvery star in the list is in the surrounded set
is_surrounded_one_ofAt least one star in the list is in the surrounded set
not_surroundedNone of the stars in the list is in the surrounded set

Example

use x_iztro::StarKey::*;

println!("{}", chart.is_surrounded(Palace::Soul, &[ZiweiMaj, TianxiangMaj]));
println!("{}", chart.is_surrounded_one_of(Palace::Soul, &[QishaMaj, PojunMaj]));
println!("{}", chart.not_surrounded(Palace::Soul, &[HuoxingMin]));

Output

true
false
true

The Soul palace holds only Ziwei, while Tianxiang sits in the Wealth palace, one of the trine — hence true on the first line. Neither Qisha nor Pojun is in any of the four, hence false on the second.

Edge cases and pitfalls

What an empty list returns

With an empty stars slice, is_surrounded and not_surrounded return true ("all elements satisfy" and "no element fails" both hold vacuously) while is_surrounded_one_of returns false. Make sure the list is non-empty before calling.


horoscope / horoscope_now

Purpose Compute the horoscope for a target date, starting from this chart.

Signature

pub fn horoscope(&self, target_date: &str, target_time_index: u8) -> Result<HoroscopeRef<'_>, IztroError>
pub fn horoscope_now(&self) -> Result<HoroscopeRef<'_>, IztroError>

Parameters

ParameterTypeRequiredDefaultDescription
target_date&strYesTarget solar date in YYYY-M-D
target_time_indexu8YesTarget hour index 0–12, which fixes the hourly scope

horoscope_now takes the current date and hour from the local clock and has no parameters.

Return value HoroscopeRef<'_> — a horoscope view holding this chart, so palace lookups across the six scopes need not be passed the astrolabe again. Details on the horoscope object.

Example

let en = Language::EnUS;
let h = chart.horoscope("2025-6-1", 0)?;

println!("decadal {} {}",
    translate_heavenly_stem(h.decadal.heavenly_stem, en),
    translate_earthly_branch(h.decadal.earthly_branch, en));
println!("yearly  {} {}",
    translate_heavenly_stem(h.yearly.heavenly_stem, en),
    translate_earthly_branch(h.yearly.earthly_branch, en));

decadal / monthly / daily / hourly are HoroscopeItems whose pillars read directly, while yearly and age each carry one extra datum of their own (the shared fields sit under base), but both implement Deref, so h.yearly.heavenly_stem reads directly as well.

Output

decadal geng chen
yearly  yi si

to_text

Purpose The chart's semantic text: a complete description for language models and people.

Signature

pub fn to_text(&self) -> String

Emits in the charting language; for an explicit language use the free function text::astrolabe_to_text(astrolabe, lang)lang may differ from the charting language, with every field re-translated by key into the target language. For single palaces and surrounded palaces see PalaceRef::to_text() / SurroundedPalaces::to_text(lang). The full format is on Semantic text.

Example

println!("{}", chart.to_text().chars().take(77).collect::<String>());

Output

=== Basic Info ===
Gender: female
Solar Date: 2000-8-16
Lunar Date: 二〇〇〇年七月十七

to_dto

Purpose Convert the chart into the serialization structure that matches the JS iztro field contract.

Signature

pub fn to_dto(&self) -> AstrolabeDto

Return value x_iztro::dto::AstrolabeDto — camelCase keys with values translated into the charting language, plus the language-independent *Key fields and the charting context (genderKey / timeIndex / fixLeap / language / config). The field list is on the data model.

Example

let dto = chart.to_dto();
let json = serde_json::to_string(&dto)?;
let v: serde_json::Value = serde_json::from_str(&json)?;

println!("{} {}", v["solarDate"], v["palaces"][4]["nameKey"]);
println!("{}", v["config"]["yearDivide"]);

Output

"2000-8-16" "soulPalace"
"normal"

Edge cases and pitfalls

The DTO is for the language bindings and for frontends. For analysis on the Rust side use Astrolabe itself — it has every query method, while the DTO is only data. To get a JSON string in one step, use by_solar_json.

The overrides of Config (the custom mutagen and brightness tables) do not go into the DTO: they are charting input rather than result, and echoing them back would break the field contract with JS iztro.

On this page