运限对象
六个运限层级的数据结构、整层取回的三个列表,以及不必再传星盘的宫位查询方法。
运限把本命盘投影到某个时间点上。同一张盘,不同年份看到的宫位分布不同—— 这正是「大限走到哪一宫」的意思。
let h = chart.horoscope("2025-6-1", 0)?;HoroscopeRef 持有发起它的那张本命盘,因此所有查询方法都不必再把星盘传进去。
本页示例统一用 Language::ZhCN 的本命盘,因此输出里的展示值都是中文。
HoroscopeData
HoroscopeRef 经 Deref 得到 HoroscopeData,它有八个字段:两个日期串与六个层级。
| 字段 | 类型 | 说明 |
|---|---|---|
solar_date | String | 目标公历日期,与入参一致 |
lunar_date | String | 目标日期的农历中文写法 |
decadal | HoroscopeItem | 大限 |
age | AgeItem | 小限 |
yearly | YearlyItem | 流年 |
monthly | HoroscopeItem | 流月 |
daily | HoroscopeItem | 流日 |
hourly | HoroscopeItem | 流时 |
solar_date 是目标日期不是出生日期;出生日期在本命盘上,用 h.astrolabe().solar_date 取。
六个层级
| 字段 | 类型 | 跨度 | 说明 |
|---|---|---|---|
decadal | HoroscopeItem | 十年 | 大限。未起运的幼年期为童限 |
age | AgeItem | 一年 | 小限。按虚岁逐年走一宫 |
yearly | YearlyItem | 一年 | 流年。按流年干支定宫 |
monthly | HoroscopeItem | 一月 | 流月 |
daily | HoroscopeItem | 一日 | 流日 |
hourly | HoroscopeItem | 一时辰 | 流时 |
小限与流年的区别
两者都是一年一走,但起法不同:小限从生年地支起、按虚岁顺推, 流年直接看那一年的干支落在哪一宫。两条线互相独立,斗数里通常并看。
HoroscopeItem
| 字段 | 类型 | 说明 |
|---|---|---|
index | usize | 该层级落在哪一宫(宫位索引) |
name | String | 层级显示名,按输出语言翻译 |
name_key | HoroscopeName | 层级标识;大限层未起运时为 Childhood(童限),与 Decadal 是不同的解盘语义,判断层级用它、不要比对译文 |
heavenly_stem | HeavenlyStem | 该层级的天干,决定它飞出的四化 |
earthly_branch | EarthlyBranch | 该层级的地支 |
palace_names | Vec<Palace> | 以该层级所在宫为命宫重推的十二宫名,按宫位索引排列 |
mutagen | Vec<StarKey> | 该层级天干引发的四化星,顺序为禄权科忌 |
stars | Option<Vec<Vec<Star>>> | 该层级的流耀分布;无流耀的层级为 None |
age 与 yearly 不是 HoroscopeItem 本身,而是各自多带一项数据的包装:
pub struct AgeItem {
pub base: HoroscopeItem,
pub nominal_age: u32, // 该日期对应的虚岁
}
pub struct YearlyItem {
pub base: HoroscopeItem,
pub yearly_dec_star: YearlyDecStar,
}
pub struct YearlyDecStar {
pub jiangqian12: Vec<StarKey>, // 流年将前十二神,按宫位索引排列
pub suiqian12: Vec<StarKey>, // 流年岁前十二神,按宫位索引排列
}AgeItem 与 YearlyItem 都实现 Deref<Target = HoroscopeItem>,通用字段直接读:
h.yearly.heavenly_stem、h.age.index;需要整个 HoroscopeItem 时取 .base。
四个类型都在 crate 根重导出。
示例
let h = chart.horoscope("2025-6-1", 0)?;
for item in [&h.decadal, &h.monthly, &h.daily, &h.hourly] {
println!("{} 落在宫位 {} 干支 {}{}", item.name, item.index,
translate_heavenly_stem(item.heavenly_stem, Language::ZhCN),
translate_earthly_branch(item.earthly_branch, Language::ZhCN));
}
println!("小限虚岁 {}", h.age.nominal_age);输出
大限 落在宫位 2 干支 庚辰
流月 落在宫位 3 干支 壬午
流日 落在宫位 8 干支 辛丑
流时 落在宫位 8 干支 戊子
小限虚岁 26三个列表
decadal_list / yearly_list / monthly_list 是 Astrolabe 上的方法,不在运限对象上:
它们一次取回整层的运限项,省去按日期逐个调 horoscope 再自己拼。
每项都在通用的 HoroscopeItem 之外多带该层的时间坐标:
pub struct DecadalHoroscope {
pub base: HoroscopeItem,
pub palace_name: Palace, // 该大限所在的本命宫名
pub age_range: (u32, u32), // 起止虚岁,含两端
pub year_range: (i64, i64), // 起止农历年份,含两端
}
pub struct YearlyHoroscope {
pub base: HoroscopeItem,
pub age: u32, // 该流年对应的虚岁
pub year: i64, // 农历年份
}
pub struct MonthlyHoroscope {
pub base: HoroscopeItem,
pub age: u32, // 该流月对应的虚岁
pub year: i64, // 农历年份
pub month: u32, // 农历月份,正月为 1;闰月与同号常规月的 month 相同
pub is_leap_month: bool, // 该项是否闰月
pub part: MonthPart, // Normal 整月 / First 闰月前半 / Second 闰月后半
pub day_range: (u32, u32), // 该段覆盖的农历日,含两端
}三者都实现 Deref<Target = HoroscopeItem>,通用字段直接读(d.heavenly_stem、d.palace_names),
需要整个 HoroscopeItem 时取 .base。四个类型与 MonthPart 都在 crate 根重导出。
列表里的运限按时柱地支起
三个列表的每一项都以时柱地支对应的时辰计算,而不是排盘时传入的 time_index。
两者只在晚子时不同:入参 12 的盘,时柱地支是子,列表按时辰 0 起运限。
decadal_list
用途 一次取回本盘十二个大限,按起运先后排列。
斗数含义 大限十年一步,从命宫或其他起限宫顺逆行走十二宫。 把整条线摊平看,才知道某一段人生落在哪一宫、对应哪十年。
签名
pub fn decadal_list(&self) -> Vec<DecadalHoroscope>返回值 定长 12 项,第 0 项是第一个大限。顺序按起运虚岁排, 与宫位索引顺序无关(大限顺行逆行取决于阴阳男女)。
示例
let zh = Language::ZhCN;
for d in chart.decadal_list().iter().take(3) {
println!("{} {}{} {}-{} {}-{}",
translate_palace(d.palace_name, zh),
translate_heavenly_stem(d.heavenly_stem, zh),
translate_earthly_branch(d.earthly_branch, zh),
d.age_range.0, d.age_range.1, d.year_range.0, d.year_range.1);
}
println!("{}", chart.decadal_list().len());输出
命宫 壬午 3-12 2002-2011
兄弟 辛巳 13-22 2012-2021
夫妻 庚辰 23-32 2022-2031
12这张盘三岁起运,第一个大限落在命宫。
边界与陷阱
列表里没有童限
起运之前的那几年是童限,只有按具体日期查 horoscope 才会出现(name_key 为 Childhood)。
decadal_list 列的是十二个大限本身,每项的 name_key 恒为 Decadal。
yearly_list
用途 取一个大限内的全部流年。
斗数含义 定了大限再逐年细看,是斗数常规的推运顺序。 一个大限十年,对应的就是这十个流年。
签名
pub fn yearly_list(&self, target: impl Into<DecadalTarget>) -> Result<Vec<YearlyHoroscope>, IztroError>参数
| 参数 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
target | impl Into<DecadalTarget> | 是 | — | 大限序号(usize,0 为第一个大限)或该限所在的本命宫名(Palace) |
pub enum DecadalTarget {
Ordinal(usize), // 起运先后序号
Name(Palace), // 该大限所在的本命宫名
}两种写法定位到同一个大限时结果完全相同,选哪个取决于手上已有什么。
返回值 Result<Vec<YearlyHoroscope>, IztroError>,10 项,按虚岁先后排列。
序号越界或宫名定位不到时返回 Err。
示例
let zh = Language::ZhCN;
let list = chart.yearly_list(2usize)?;
for y in list.iter().take(3) {
println!("{} {} {}{} -> {}", y.age, y.year,
translate_heavenly_stem(y.heavenly_stem, zh),
translate_earthly_branch(y.earthly_branch, zh), y.index);
}
println!("{} {}", list.len(), chart.yearly_list(Palace::Spouse)?.len());输出
23 2022 壬寅 -> 0
24 2023 癸卯 -> 1
25 2024 甲辰 -> 2
10 10第 2 个大限落在夫妻宫,因此 yearly_list(2) 与 yearly_list(Palace::Spouse) 是同一个大限。
边界与陷阱
没有默认大限
两种定位必须给一个,没有「不传就取当前大限」的行为——静默取一个默认值会把漏传 变成看起来成功的错答案。
monthly_list
用途 取一个农历年的全部流月。
斗数含义 流月是流年之下的一层,逐月推移。闰月怎么算是一个流派分歧点, 因此拆不拆由调用方定。
签名
pub fn monthly_list(&self, year: i64, fix_leap: bool) -> Result<Vec<MonthlyHoroscope>, IztroError>参数
| 参数 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
year | i64 | 是 | — | 农历年份 |
fix_leap | bool | 是 | — | 闰月是否拆成前后半月两项 |
返回值 Result<Vec<MonthlyHoroscope>, IztroError>,长度取决于该年有无闰月与 fix_leap:
| 该农历年 | fix_leap | 项数 | 闰月怎么排 |
|---|---|---|---|
| 无闰月 | 任意 | 12 | — |
| 有闰月 | true | 14 | 闰月拆成 First(初一至十五)与 Second(十六至月末)两项 |
| 有闰月 | false | 13 | 闰月整月一项,part 为 Normal |
闰月排在同月号的常规月之后。每项按该段首日算出(后半段取十六)。
示例
let zh = Language::ZhCN;
let list = chart.monthly_list(2020, true)?;
println!("{}", list.len());
for m in list.iter().skip(3).take(4) {
println!("{} {} {} {}-{} {}{}", m.month, m.is_leap_month, m.part.as_key(),
m.day_range.0, m.day_range.1,
translate_heavenly_stem(m.heavenly_stem, zh),
translate_earthly_branch(m.earthly_branch, zh));
}
println!("{} {}", chart.monthly_list(2020, false)?.len(), chart.monthly_list(2021, true)?.len());输出
14
4 false normal 1-30 辛巳
4 true first 1-15 辛巳
4 true second 16-29 壬午
5 false normal 1-30 壬午
13 12农历 2020 年有闰四月。拆开之后,闰四月前半与四月同干支(辛巳),后半跟五月同干支(壬午) ——这正是「闰月下半月算下一个月」的意思。农历 2021 年无闰月,恒为 12 项。
边界与陷阱
这个 fix_leap 与排盘的 fix_leap 无关
排盘入口那个 fix_leap 决定闰月出生的人下半月按下个月安星,改的是本命盘布局;
这里这个只决定本列表拆不拆闰月。两者可以取不同的值,互不影响。
闰月与常规月的 month 相同
闰四月的 month 也是 4,靠 is_leap_month 区分。按 month 去重会把闰月弄丢。
age_palace
用途 取小限当年所在的宫。
斗数含义 小限是逐年推移的一条线,落在哪一宫就以那宫为该年重点。
签名
pub fn age_palace(&self) -> PalaceRef<'a>返回值 PalaceRef——本命盘上的宫位,必然存在。
示例
let h = chart.horoscope("2025-6-1", 0)?;
println!("{}", translate_palace(h.age_palace().name, Language::ZhCN));输出
田宅palace
用途 取某个运限层级下、按该层级重推的十二宫中的某一宫。
斗数含义 大限走到某宫后,以那一宫为「大限命宫」重排十二宫。 「大限的夫妻宫」问的就是这套重排后的宫位,与本命夫妻宫通常不是同一宫。
签名
pub fn palace(&self, name: Palace, scope: Scope) -> Option<PalaceRef<'a>>参数
| 参数 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
name | Palace | 是 | — | 要取的宫名 |
scope | Scope | 是 | — | 在哪个层级的十二宫里找 |
返回值 Option<PalaceRef<'a>>——本命盘上的宫位(同一格宫位在不同层级有不同宫名)。
层级为 Origin 时即本命十二宫。
示例
let zh = Language::ZhCN;
let h = chart.horoscope("2025-6-1", 0)?;
println!("大限命宫落在本命的 {}",
translate_palace(h.palace(Palace::Soul, Scope::Decadal).unwrap().name, zh));
println!("本命命宫是 {}",
translate_palace(h.palace(Palace::Soul, Scope::Origin).unwrap().name, zh));输出
大限命宫落在本命的 夫妻
本命命宫是 命宫边界与陷阱
返回的是本命盘上的那一格
palace(Soul, Decadal) 返回的宫位对象上,name 仍是本命宫名(例中的夫妻),
因为它就是本命盘上的那一格。要看该格在大限层级叫什么,查 h.decadal.palace_names[index]。
surround_palaces
用途 取某个运限层级下某宫的三方四正。
签名
pub fn surround_palaces(&self, name: Palace, scope: Scope) -> Option<SurroundedPalaces<'a>>参数 同 palace。
返回值 Option<SurroundedPalaces<'a>>,判断方法见三方四正。
示例
let h = chart.horoscope("2025-6-1", 0)?;
let sp = h.surround_palaces(Palace::Wealth, Scope::Yearly).unwrap();
println!("流年财帛的三方四正以本命 {} 为本宫", translate_palace(sp.target.name, Language::ZhCN));输出
流年财帛的三方四正以本命 疾厄 为本宫has_horoscope_stars / has_one_of_horoscope_stars / not_have_horoscope_stars
用途 判断某层级某宫里有没有指定的流耀。
斗数含义 流耀是随运限层级产生的一组星:魁钺昌曲禄羊陀马鸾喜。 它们在不同层级有不同名字——大限层级叫运魁、运钺,流年层级叫流魁、流钺, 含义相同但作用于各自的时间跨度。
签名
pub fn has_horoscope_stars(&self, name: Palace, scope: Scope, stars: &[StarKey]) -> bool
pub fn has_one_of_horoscope_stars(&self, name: Palace, scope: Scope, stars: &[StarKey]) -> bool
pub fn not_have_horoscope_stars(&self, name: Palace, scope: Scope, stars: &[StarKey]) -> bool参数
| 参数 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
name | Palace | 是 | — | 该层级下的宫名 |
scope | Scope | 是 | — | 运限层级 |
stars | &[StarKey] | 是 | — | 流耀标识,须用该层级的名字 |
返回值
| 方法 | 语义 |
|---|---|
has_horoscope_stars | 每一颗都在 |
has_one_of_horoscope_stars | 至少一颗在 |
not_have_horoscope_stars | 一颗都不在 |
示例
use x_iztro::StarKey::*;
let h = chart.horoscope("2025-6-1", 0)?;
println!("{}", h.has_horoscope_stars(Palace::Soul, Scope::Decadal, &[Yunlu]));
println!("{}", h.has_one_of_horoscope_stars(Palace::Soul, Scope::Decadal, &[Yunlu, Yunyang]));
println!("{}", h.not_have_horoscope_stars(Palace::Soul, Scope::Decadal, &[Yuntuo]));输出
false
false
true边界与陷阱
has_horoscope_mutagen
用途 判断某层级某宫里有没有该层级天干引发的四化。
斗数含义 每个运限层级有自己的天干,会像生年干一样化出四颗星。 「大限化禄落在大限财帛」这类判断问的就是这个。
签名
pub fn has_horoscope_mutagen(&self, name: Palace, scope: Scope, mutagen: Mutagen) -> bool参数
| 参数 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
name | Palace | 是 | — | 该层级下的宫名 |
scope | Scope | 是 | — | 运限层级 |
mutagen | Mutagen | 是 | — | 四化之一 |
返回值 bool。检查该层级天干化出的那颗星是否落在目标宫的主星或辅星里(不看杂耀)。
示例
let h = chart.horoscope("2025-6-1", 0)?;
println!("{}", h.has_horoscope_mutagen(Palace::Soul, Scope::Decadal, Mutagen::Lu));
// 该层级化出的四颗星本身可直接读
println!("{:?}", h.decadal.mutagen.iter()
.map(|s| translate_star(*s, Language::ZhCN)).collect::<Vec<_>>());输出
false
["太阳", "武曲", "太阴", "天同"]大限干为庚,庚干四化为太阳化禄、武曲化权、太阴化科、天同化忌。
边界与陷阱
scope 为 Origin 时恒为 false
本命层级没有「层级天干」这回事——生年四化已经打在星耀自身的 mutagen 字段上。
has_horoscope_mutagen(name, Scope::Origin, m) 因此直接返回 false,
不代表本命盘上没有这个四化。要查本命四化,用宫位的
has_mutagen。
astrolabe / data / into_data
用途 回到本命盘,或取出运限的纯数据。
签名
pub fn astrolabe(&self) -> &'a Astrolabe
pub fn data(&self) -> &HoroscopeData
pub fn into_data(self) -> HoroscopeData返回值
| 方法 | 用途 |
|---|---|
astrolabe | 回到发起这次运限的本命盘 |
data | 借用底层数据;视图已实现 Deref,通常直接写 h.decadal 即可 |
into_data | 取走数据、丢掉对星盘的借用,用于需要 'static 生命周期的场合 |
示例
let h = chart.horoscope("2025-6-1", 0)?;
println!("{}", h.astrolabe().solar_date);
let data: HoroscopeData = h.into_data(); // 不再借用 chart
println!("{}", data.solar_date);输出
2000-8-16
2025-6-1to_text
用途 运限的语义化文本:面向语言模型与人的完整描述,Markdown 子集。
签名
pub fn to_text(&self) -> String定义在 HoroscopeRef 上,按星盘排盘语言输出;要指定语言用自由函数
text::horoscope_to_text(astrolabe, horoscope, lang)。
返回值 String——大限(未起运为童限)、小限、流年、流月、流日、流时各一节,
各层带四化、该层视角的格局与流耀,大限与流年展开十二宫表。
完整格式见语义化文本。
示例
let h = chart.horoscope("2025-1-1", 0)?;
for line in h.to_text().lines().take(5) {
println!("{line}");
}输出
# 运限 2025-1-1 (二〇二四年腊月初二)
## 大限 · 命宫: 本命夫妻 (庚辰)
- 四化: 太阳化禄→本命子女, 武曲化权→本命财帛, 太阴化科→本命仆役, 天同化忌→本命疾厄
- 格局: 杀破狼 (命宫), 风云际会 (命宫)to_text_with
用途 to_text 的同一份文本,按 TextOptions 附释义:
每层的表或事实之后紧跟该层流耀的释义与该层视角命中格局的释义,跨层去重。
本命星耀的释义不在这里重复,在本命盘的 to_text_with 里。
签名
pub fn to_text_with(&self, opts: &TextOptions) -> String参数
| 参数 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
opts | &TextOptions | 是 | — | 输出选项;TextOptions::new().knowledge(pack) 带释义,TextOptions::default() 与 to_text 等价 |
定义在 HoroscopeRef 上,按星盘排盘语言输出;要指定语言用自由函数
text::horoscope_to_text_with(astrolabe, horoscope, opts, lang)。
插入位置见带释义的文本。
示例
let pack = KnowledgePack::builtin(Language::ZhCN).unwrap();
let h = chart.horoscope("2025-1-1", 0)?;
let text = h.to_text_with(&TextOptions::new().knowledge(pack));
println!("{} {}", h.to_text().chars().count(), text.chars().count());
for line in text.lines().filter(|l| l.starts_with("## ")) {
println!("{line}");
}输出
2457 8458
## 大限 · 命宫: 本命夫妻 (庚辰)
## 小限 · 命宫: 本命官禄 · 虚岁 25
## 流年 · 命宫: 本命夫妻 (甲辰)
## 流月 · 命宫: 本命仆役 (丁丑)
## 流日 · 命宫: 本命迁移 (庚午)
## 流时 · 命宫: 本命迁移 (丙子)to_dto
用途 把运限数据转成与 JS iztro 字段契约一致的序列化结构。
签名
pub fn to_dto(&self, lang: Language) -> HoroscopeDto参数
| 参数 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
lang | Language | 是 | — | 译名字段用哪种语言 |
定义在 HoroscopeData 上(不是 HoroscopeRef)。运限数据本身不记语言,
因此这里要显式传——通常传 chart.language 与本命盘保持一致。
返回值 x_iztro::dto::HoroscopeDto,camelCase 键 + *Key 标识。
示例
let h = chart.horoscope("2025-6-1", 0)?;
let json = serde_json::to_string(&h.to_dto(chart.language))?;
let v: serde_json::Value = serde_json::from_str(&json)?;
println!("{} {}", v["solarDate"], v["decadal"]["heavenlyStem"]);
println!("{}", v["age"]["nominalAge"]);输出
"2025-6-1" "庚"
26