Star placement

Where a group of stars lands given birth data, plus the low-level building blocks of the charting pipeline.

Use this layer when you do not want a whole chart and only need "which palace does Lucun land in?" or "how are the adjective stars distributed on this chart?".

The module has two layers:

LayerTakesPurpose
star::queryBirth dataThe outward placement entry points, the subject of this page
star::location / decorative / major / minor / adjectivePrecomputed indicesBuilding blocks of the charting pipeline, reusable in a pipeline of your own

Every index is a palace index: 0 is the Yin palace, 11 the Chou palace.

The examples on this page all chart with Language::EnUS, so the star names in the output are iztro's en-US vocabulary — emperor for Ziwei, general for Wuqu, and so on. The indices themselves are language-independent.

StarParam

Every entry point in star::query shares this one parameter struct.

pub struct StarParam<'a> {
    pub solar_date: &'a str,
    pub time_index: u8,
    pub gender: Gender,
    pub fix_leap: bool,
    pub from: Option<(HeavenlyStem, EarthlyBranch)>,
    pub language: Language,
    pub config: &'a Config,
}
FieldTypeDescription
solar_date&strSolar date in YYYY-M-D
time_indexu8Hour index 0–12
genderGenderGender, which sets the direction of the Changsheng and Boshi gods
fix_leapboolWhether to correct for leap months
fromOption<(HeavenlyStem, EarthlyBranch)>The pillar anchoring the five elements class; None uses the Soul palace's
languageLanguageOutput language for star names
config&ConfigCharting configuration
use x_iztro::star::query::StarParam;

let cfg = Config::default();
let param = StarParam {
    solar_date: "2000-8-16",
    time_index: 2,
    gender: Gender::Female,
    fix_leap: true,
    from: None,
    language: Language::EnUS,
    config: &cfg,
};

from only affects the five elements class

Once from is given, the class is derived from that pillar instead, which in turn moves Ziwei and Tianfu and the Changsheng gods. How the other star groups are placed is unaffected. Use it to obtain the placements of the Zhongzhou school's earth and human charts.


get_start_index

Purpose Find the starting palaces of Ziwei and Tianfu.

Zi Wei meaning Ziwei is the anchor of the whole chart, located from the five elements class and the lunar day by the Ziwei placement rule; the other thirteen major stars then spread out from Ziwei and Tianfu. Tianfu's position mirrors Ziwei's.

Signature

pub fn get_start_index(param: &StarParam) -> Result<StartIndex, IztroError>

Return value StartIndex { ziwei: usize, tianfu: usize }.

Example

let s = star::query::get_start_index(&param)?;
println!("Ziwei {} Tianfu {}", s.ziwei, s.tianfu);

Output

Ziwei 4 Tianfu 8

Edge cases and pitfalls

A different pillar in from changes the result — which is exactly where the Zhongzhou school's three charts differ.


Landing indices per group

The following six entry points share a shape: they take a &StarParam and return a struct whose fields are all palace indices.

FunctionReturn typeFieldsPlacement rule
get_lu_yang_tuo_ma_indexLuYangTuoMalu yang tuo maThe year stem places Lucun, with Qingyang ahead and Tuoluo behind; Tianma from the year branch
get_kui_yue_indexKuiYuekui yueYear stem
get_chang_qu_indexChangQuchang quHour branch
get_kong_jie_indexKongJiekong jieHour branch
get_timely_star_indexTimelyStarstaifu fenggaoHour branch
get_luan_xi_indexLuanXihongluan tianxiYear branch

Example

use x_iztro::star::query as sq;

let l = sq::get_lu_yang_tuo_ma_index(&param)?;
println!("Lucun {} Qingyang {} Tuoluo {} Tianma {}", l.lu, l.yang, l.tuo, l.ma);

let c = sq::get_chang_qu_index(&param)?;
println!("Wenchang {} Wenqu {}", c.chang, c.qu);

let lx = sq::get_luan_xi_index(&param)?;
println!("Hongluan {} Tianxi {}", lx.hongluan, lx.tianxi);

Output

Lucun 6 Qingyang 7 Tuoluo 5 Tianma 0
Wenchang 6 Wenqu 4
Hongluan 9 Tianxi 3

Qingyang sits one palace ahead of Lucun and Tuoluo one behind — the direct expression of the mnemonic "Qingyang before Lucun, Tuoluo after".


get_daily_star_index / get_monthly_star_index / get_yearly_star_index

Purpose Get the landing palaces of the adjective stars placed by day, month and year.

Zi Wei meaning Adjective stars are grouped by how they are placed: day-based stars count forward from a minor star's position, starting at day one, to the birth day; month-based stars are located from the lunar month; year-based stars are the largest group and start from the year stem or year branch.

Signature

pub fn get_daily_star_index(param: &StarParam) -> Result<DailyStar, IztroError>
pub fn get_monthly_star_index(param: &StarParam) -> Result<MonthlyStar, IztroError>
pub fn get_yearly_star_index(param: &StarParam) -> Result<YearlyStars, IztroError>

Return value

TypeFields
DailyStarsantai bazuo enguang tiangui
MonthlyStarjieshen tianyao tianxing yinsha tianyue tianwu
YearlyStars29 fields: tiancai tianshou tianchu posui feilian longchi fengge tianku tianxu tianguan tianfu tiande yuede tiankong jielu kongwang xunkong jiekong tianshang tianshi huagai xianchi guchen guasu jiesha nianjie dahao hongluan tianxi

Example

let d = sq::get_daily_star_index(&param)?;
println!("Santai {} Bazuo {} Enguang {} Tiangui {}", d.santai, d.bazuo, d.enguang, d.tiangui);

let m = sq::get_monthly_star_index(&param)?;
println!("Jieshen {} Tianyao {} Tianxing {}", m.jieshen, m.tianyao, m.tianxing);

let y = sq::get_yearly_star_index(&param)?;
println!("Xianchi {} Huagai {} Tianshang {} Tianshi {}", y.xianchi, y.huagai, y.tianshang, y.tianshi);

Output

Santai 0 Bazuo 10 Enguang 9 Tiangui 7
Jieshen 0 Tianyao 5 Tianxing 1
Xianchi 7 Huagai 2 Tianshang 9 Tianshi 11

Edge cases and pitfalls


get_major_stars / get_minor_stars / get_adjective_stars

Purpose Get the complete distribution of major, minor and adjective stars across the twelve palaces.

Signature

pub fn get_major_stars(param: &StarParam) -> Result<[Vec<Star>; 12], IztroError>
pub fn get_minor_stars(param: &StarParam) -> Result<[Vec<Star>; 12], IztroError>
pub fn get_adjective_stars(param: &StarParam) -> Result<[Vec<Star>; 12], IztroError>

Return value A fixed array of twelve, indexed by palace index. Each item is that palace's star list, possibly empty.

Rust names these three in the plural; the Python and Go bindings name their equivalents in the singular (get_major_star, GetMajorStar, …). Do not confuse them with get_major_star_by_solar_date, which returns only the Soul palace's major stars as a string.

Example

let major = sq::get_major_stars(&param)?;
for (i, stars) in major.iter().take(5).enumerate() {
    println!("[{i}] {:?}", stars.iter().map(|s| s.name.as_str()).collect::<Vec<_>>());
}

Output

[0] ["general", "minister"]
[1] ["sun", "sage"]
[2] ["marshal"]
[3] ["advisor"]
[4] ["emperor"]

Edge cases and pitfalls

The returned Stars carry brightness and natal mutagen marks and are identical to those from a full chart — they go through the same code. If you want the whole chart, by_solar is simpler.


get_changsheng12 / get_boshi12 / get_yearly12

Purpose Get how the four groups of twelve gods are arranged across the twelve palaces.

Zi Wei meaning Each group is twelve marks filling the twelve palaces, exactly one per palace: the Changsheng gods start from the five elements class with direction from gender and year-branch polarity; the Boshi gods start from Lucun with the same direction rule; the Sui-qian gods run forward from the year branch, and the Jiang-qian gods start from the trine group of the year branch.

Signature

pub fn get_changsheng12(param: &StarParam) -> Result<[StarKey; 12], IztroError>
pub fn get_boshi12(param: &StarParam) -> Result<[StarKey; 12], IztroError>
pub fn get_yearly12(param: &StarParam) -> Result<([StarKey; 12], [StarKey; 12]), IztroError>

Return value A fixed array of twelve, indexed by palace index. get_yearly12 returns two groups at once, in the order (Sui-qian gods, Jiang-qian gods).

Example

let cs = sq::get_changsheng12(&param)?;
println!("{:?}", cs.iter().take(4).map(|s| translate_star(*s, Language::EnUS)).collect::<Vec<_>>());

let (suiqian, jiangqian) = sq::get_yearly12(&param)?;
println!("{:?}", suiqian.iter().take(4).map(|s| translate_star(*s, Language::EnUS)).collect::<Vec<_>>());
println!("{:?}", jiangqian.iter().take(4).map(|s| translate_star(*s, Language::EnUS)).collect::<Vec<_>>());

Output

["dissipated", "buried", "dead", "sick"]
["sorrowing", "illness", "initial", "unlucky"]
["varied", "listless", "religious", "robbed"]

get_changsheng12_start_index / get_jiangqian12_start_index

Purpose Get just the starting palace of two of the god groups, without laying out the whole cycle.

Zi Wei meaning The Changsheng starting point is set by the five elements class: water 2nd starts at Shen, wood 3rd at Hai, metal 4th at Si, earth 5th at Shen, fire 6th at Yin. The Jiangxing starting point is set by the trine group of the year branch: yin/woo/xu years at Woo, shen/zi/chen years at Zi, si/you/chou years at You, hai/mao/wei years at Mao.

Signature

pub fn get_changsheng12_start_index(five_elements_class: FiveElementsClass) -> usize
pub fn get_jiangqian12_start_index(yearly_branch: EarthlyBranch) -> usize

Return value usize, 0–11. Neither function needs birth data, and neither can fail.

Example

use x_iztro::star::decorative::{get_changsheng12_start_index, get_jiangqian12_start_index};

println!("{} {}",
    get_changsheng12_start_index(FiveElementsClass::Water2nd),
    get_changsheng12_start_index(FiveElementsClass::Fire6th));
println!("{} {}",
    get_jiangqian12_start_index(EarthlyBranch::Zi),
    get_jiangqian12_start_index(EarthlyBranch::Wu));

Output

6 0
10 4

Water 2nd puts Changsheng in Shen (index 6), fire 6th in Yin (index 0).


get_horoscope_stars

Purpose Get the scope-star distribution of a horoscope layer.

Zi Wei meaning Scope stars are the ten stars a horoscope produces: Tiankui, Tianyue, Wenchang, Wenqu, Lucun, Qingyang, Tuoluo, Tianma, Hongluan and Tianxi. Where they land is fixed by that layer's stem and branch, and their names change with the layer. The yearly layer carries one extra star, Nianjie.

Signature

pub fn get_horoscope_stars(
    stem: HeavenlyStem,
    branch: EarthlyBranch,
    scope: Scope,
    lang: Language,
) -> [Vec<Star>; 12]

Parameters

ParameterTypeRequiredDefaultDescription
stemHeavenlyStemYesStem of that layer
branchEarthlyBranchYesBranch of that layer
scopeScopeYesThe horoscope layer, which fixes the star names
langLanguageYesOutput language

Return value A fixed array of twelve, indexed by palace index. It cannot fail — the parameters are enums with no invalid values.

Star names per layer

NatalDecadalYearlyMonthlyDailyHourly
TiankuiYunkuiLiukuiYuekuiRikuiShikui
TianyueYunyueLiuyueYueyueRiyueShiyue
WenchangYunchangLiuchangYuechangRichangShichang
WenquYunquLiuquYuequRiquShiqu
LucunYunluLiuluYueluRiluShilu
QingyangYunyangLiuyangYueyangRiyangShiyang
TuoluoYuntuoLiutuoYuetuoRituoShituo
TianmaYunmaLiumaYuemaRimaShima
HongluanYunluanLiuluanYueluanRiluanShiluan
TianxiYunxiLiuxiYuexiRixiShixi

Those are the StarKey names. In the en-US vocabulary a scope star displays as its base name plus a layer marker — money(D) for Yunlu at the decadal layer, (Y) (M) (d) (H) for the yearly, monthly, daily and hourly layers, and no marker at the natal layer.

Example

use x_iztro::astro::horoscope::get_horoscope_stars;

let decadal = get_horoscope_stars(HeavenlyStem::Jia, EarthlyBranch::Zi, Scope::Decadal, Language::EnUS);
println!("{:?}", decadal.iter().take(4)
    .map(|g| g.iter().map(|s| s.name.as_str()).collect::<Vec<_>>()).collect::<Vec<_>>());

let origin = get_horoscope_stars(HeavenlyStem::Jia, EarthlyBranch::Zi, Scope::Origin, Language::EnUS);
println!("{:?}", origin.iter().take(2)
    .map(|g| g.iter().map(|s| s.name.as_str()).collect::<Vec<_>>()).collect::<Vec<_>>());

Output

[["money(D)", "horse(D)"], ["driven(D)", "attractive(D)"], [], ["scholar(D)"]]
[["money", "horse"], ["driven", "attractive"]]

Edge cases and pitfalls

The yearly layer has one extra star

The result for Scope::Yearly additionally contains Nianjie, located from the yearly branch and placed ahead of the ten scope stars. No other layer has it.


The low-level building blocks

The functions under star::location and star::decorative take precomputed indices rather than birth data. The charting pipeline uses them internally, and they are reusable in a pipeline of your own.

star::location

FunctionTakesReturns
get_start_indexlunar_day, time_index, month_day_count, five_elements_valueStartIndex { ziwei, tianfu }
get_lu_yang_tuo_ma_indexstem, branchLuYangTuoMa { lu, yang, tuo, ma }
get_kui_yue_indexstemKuiYue { kui, yue }
get_zuo_you_indexlunar_monthZuoYou { zuo, you }
get_chang_qu_indextime_indexChangQu { chang, qu }
get_chang_qu_index_by_stemstemChangQu { chang, qu } (for horoscope layers)
get_daily_star_indexlunar_day, time_index, zuo_index, you_index, chang_index, qu_indexDailyStar { santai, bazuo, enguang, tiangui }
get_timely_star_indextime_indexTimelyStars { taifu, fenggao }
get_kong_jie_indextime_indexKongJie { kong, jie }
get_huo_ling_indexbranch, time_indexHuoLing { huo, ling }
get_luan_xi_indexbranchLuanXi { hongluan, tianxi }
get_huagai_xianchi_indexbranchHuagaiXianchi { huagai, xianchi }
get_gu_gua_indexbranchGuGua { guchen, guasu }
get_jiesha_adj_indexbranchusize
get_dahao_indexbranchusize
get_nianjie_indexbranchusize
get_tianshang_tianshi_indexgender, yearly_branch, soul_index, algorithm(usize, usize), Tianshang then Tianshi
get_tiancai_indexyearly_branch, soul_indexusize
get_monthly_star_indexmonth_indexMonthlyStar { jieshen, tianyao, tianxing, yinsha, tianyue, tianwu }
get_yearly_star_indexsoul_index, body_index, yearly_stem, yearly_branch, gender, algorithmYearlyStars (the 29 fields above)

Every field of these structs is a usize palace index (0 being the Yin palace); get_tianshang_tianshi_index returns a bare tuple rather than a named struct.

star::decorative

FunctionTakesReturns
get_changsheng12_start_indexfive_elements_classusize
get_jiangqian12_start_indexyearly_branchusize
get_changsheng12the class, gender, year branch and so on[StarKey; 12]
get_boshi12lu_index, gender, yearly_branch[StarKey; 12]
get_yearly12the year branch and so on([StarKey; 12], [StarKey; 12]), Sui-qian then Jiang-qian

star::major / minor / adjective

get_major_stars, get_minor_stars and get_adjective_stars — same names as the functions under star::query, different parameters: this layer takes precomputed indices, that one takes birth data.

Names collide with those under star::query

The two layers share several function names (two get_start_index, for instance), distinguished by module path: star::query::get_start_index takes a &StarParam, while star::location::get_start_index takes the lunar day, the hour, the number of days in that month and the five elements class number. Use qualified paths when both modules are in scope.

The derivation from birth data to the intermediates these blocks need lives in astro::context::derive; in a pipeline of your own, call it first to get the context and feed that to the blocks, without re-deriving the year pillar and Soul palace yourself.

On this page