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
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
target | impl Into<PalaceTarget> | Yes | — | Four spellings, see the table below |
All four variants of PalaceTarget have From implementations, so you write the value directly:
| Spelling | Example | Meaning |
|---|---|---|
| Index | chart.palace(0) | Palace index 0–11, where 0 is the Yin palace |
| Name | chart.palace(Palace::Soul) | One of the twelve palace names |
| Body palace | chart.palace(PalaceTarget::Body) | Whichever palace carries the body-palace flag |
| Original palace | chart.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 wealthEdge 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
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
key | StarKey | Yes | — | Star 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 NoneEdge 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: trueis_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]) -> boolParameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
target | impl Into<PalaceTarget> | Yes | — | Located the same way as in palace |
stars | &[StarKey] | Yes | — | A list of star keys |
Return value
| Method | Meaning |
|---|---|
is_surrounded | Every star in the list is in the surrounded set |
is_surrounded_one_of | At least one star in the list is in the surrounded set |
not_surrounded | None 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
trueThe 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
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
target_date | &str | Yes | — | Target solar date in YYYY-M-D |
target_time_index | u8 | Yes | — | Target 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 sito_text
Purpose The chart's semantic text: a complete description for language models and people.
Signature
pub fn to_text(&self) -> StringEmits 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) -> AstrolabeDtoReturn 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.