About

Migrating from iztro: API mapping

Where each public iztro API lands in the three x-iztro bindings, the few that changed shape and why, and the ones not provided.

For: developers, especially anyone migrating from JS iztro

x-iztro is a port of iztro v2.5.8. Every public iztro API has an equivalent in all three bindings — Rust, Python and Go — with identical capability and a form that suits each language.

This page is for people coming from iztro: when a name does not line up, look it up here. For how to use each API, see that language's API reference.

Names that map directly

iztroRustPythonGo
astro.bySolarby_solarastro.by_solarBySolar
astro.byLunarby_lunarastro.by_lunarByLunar
chart.horoscopechart.horoscopechart.horoscopeHoroscope
chart.palacechart.palacechart.palacePalace / PalaceByIndex
chart.surroundedPalaceschart.surrounded_palaceschart.surrounded_palacesSurroundedPalaces
palace.fliesToflies_toflies_toFliesTo
util.fixIndexutils::fix_indexutils.fix_indexFixIndex
star.getMajorStarstar::query::get_major_starsstar.get_major_starGetMajorStar
i18n.ttranslate_keyi18n.translateTranslate
i18n.kotkey_ofi18n.key_ofKeyOf

The rest follow the same pattern: JS camelCase becomes snake_case in Rust and Python, and PascalCase in Go.

The ones that changed shape

These few are not transcribed, because transcribing them would have carried JS's limitations across too.

Charting perspective (heaven / earth / human plate)

iztro puts astroType on the options object of astro.withOptions, because its astro.config() is a global singleton that cannot hold a value varying per chart.

x-iztro's configuration is passed per call in the first place, so astroType goes straight into Config and works from both charting entry points, with no extra entry point to remember:

from x_iztro import Astro, ChartConfig

chart = Astro().by_solar("2000-8-16", 2, "female",
                         config=ChartConfig(astro_type="earth"))

Charting from an arbitrary stem and branch corresponds to rearrangeAstrolable, and is an astrolabe method rearranged(stem, branch) in all three bindings.

No global config and no global language

iztro's astro.config() and i18n.setLanguage() mutate module-level singletons, which is why astro.getConfig() also has to exist to read the value back.

x-iztro has no global state: both the config and the language are passed on every call and held by the caller. So getConfig and setLanguage are not provided — to read the value back, read your own copy.

Decadals and age fortune

getHoroscope(param) in astro/palace takes an AstrolabeParam. x-iztro's get_decadals_and_ages takes a Soul palace index and a Five Elements class directly, so you do not have to assemble a full set of birth data first; its capability is a superset of iztro's.

The leap-month arguments of the lunar entry point

byLunar(lunarDateStr, timeIndex, gender, isLeapMonth?, fixLeap?, language?) describes the leap month with two adjacent booleans: swap them and nothing complains while the chart silently shifts by a month — and fixLeap only means anything when the input is a leap month in the first place. x-iztro folds the pair into one three-way value: Rust LeapMonth::{NotLeap, Leap, LeapFixed}, Go NotLeapMonth / LeapMonthKeep / LeapMonthFixed; Python keeps the two booleans but makes them keyword-only (is_leap_month=, fix_leap=). The JSON wire protocol of the bindings still carries the isLeapMonth/fixLeap keys, as in iztro. The solar entry point's fixLeap is a single boolean with nothing to swap against, so it stays as it is.

Likewise, Go makes gender and language the named string types Gender / Language (GenderFemale, LanguageZhCN): literals still work, but a stray string variable in the wrong position is rejected at compile time.

Plugins

iztro's loadPlugin / use(plugin) attaches functions to the astrolabe object at run time — a product of JS having no other extension mechanism. All three bindings implement the same capability using the answer their own language gives, at compile time or load time, without sacrificing type checking:

Approach
RustExtension trait
Pythonload_plugin / load_plugins from x_iztro.plugin, attaching methods to the Astrolabe class
GoEmbedding *Astrolabe (Go does not allow adding methods to another package's type; embedding is the language's answer)

For the syntax, see Extending the astrolabe.

Disambiguating a reverse lookup

The second parameter of kot(value, k) is a separate entry point in each binding: key_of_in (Rust), key_of(text, key_filter) (Python), KeyOfIn (Go). The values match iztro case for case, including which key homographic names such as horse, dragon and 유시 (Korean for the You hour) resolve to.

A miss returns empty, not the input

iztro's kot echoes the argument back on a miss; x-iztro returns None (Rust and Python) or an empty string (Go). If you were relying on "treat a miss as the original value and carry on", that has to change when migrating.

The ones not provided

iztroWhy not
astro.astrolabeBySolarDate / astrolabeByLunarDateAliases deprecated since iztro v2.0.5, with the same parameters and behaviour as bySolar / byLunar
star.initStarsIn JS it is a factory returning 12 empty arrays; all three type systems already give a fixed-length array of 12
util.fixEarthlyBranchIndexSynonymous with earthlyBranchIndexToPalaceIndex
palace.setAstrolabe / star.setPalace / star.setAstrolabeWiring references between objects is internal behaviour, done automatically after parsing in all three bindings
The astro/analyzer moduleIts 11 functions are free-function versions of palace and surrounded-palace methods (hasStars is palace.has); the capability is already covered by the object methods
The calendar moduleDead code in iztro v2.5.8: every live code path goes through the lunar-lite dependency instead, and the module is not in the package's root exports
The i18next instance in i18n's default exportThird-party library instances are not passed through; translation and reverse lookup are covered by translate / key_of
Astrolabe.copyrightiztro's own copyright notice string

Behavioural points worth noting

Custom mutagen and brightness tables take keys only

The mutagens / brightness override tables on Config accept language-independent keys only: "ziweiMaj" works, "emperor" and "紫微" do not — taking translated names would tie a config to one chart language.

Override table lengths are validated strictly

A mutagen entry must have all 4 items (Lu, Quan, Ke, Ji) and a brightness entry all 12 (the first is the Yin palace). One too many or too few raises invalid_argument outright; nothing is padded and nothing is truncated. See Config in depth.

Override tables are not echoed in the output config

The config echoed on the astrolabe holds only the six switches. The override tables are charting input, and putting them into the DTO would break the field contract with iztro, so they read back empty — keep your own copy if you need a record.

What x-iztro adds

Pattern judgement (no iztro equivalent)

iztro has no pattern API at all. On top of chart casting, x-iztro adds a pattern engine: 64 patterns, one rule set shared by natal charts and horoscope views, each hit carrying the palace it formed in, the reading that matched (variant), a "spoiled" flag (broken), and the evidencing stars. The entries, example charts and classical quotations come from the 格局 (Patterns) page of iztro-docs (MIT License, by Sylar Long); the judgement implementation, the pattern names in six languages, and the choices between competing readings are x-iztro's own work.

The entry points on each side: Astrolabe::patterns / HoroscopeRef::patterns in Rust, Astrolabe.patterns / Horoscope.patterns in Python, Astrolabe.Patterns / Horoscope.Patterns in Go, plus the language-independent pattern keys (PatternKey in Rust and Python, the PatternXxx constants in Go). The concepts and the full table of 64 are on Patterns.

Since iztro has nothing to compare against, this area has no golden data; its correctness is held by four layers of tests: a unit test per rule, a reproduction of the source page's 32 example charts on real charts, a bulk invariant sweep over the 1,560 tier-1 charts, and output snapshots that all three bindings read back from the same files.

Knowledge packs (no iztro equivalent)

iztro ships facts only; the reading texts for stars and patterns live on its documentation site, not in the library. x-iztro turns interpretation into data behind a protocol: a knowledge pack is JSON mapping "language-independent key → text and attributes", and one default pack ships inside the library (107 stars, 64 patterns, 12 palaces, 4 transformations, 49 glossary entries, taken from the 学习 (Learn) pages of iztro-docs, MIT License, by Sylar Long). Disagree with it and you write an overlay pack that merges field by field.

The entry points: Rust's KnowledgePack::builtin / merged, Python's KnowledgePack.builtin / merged, Go's BuiltinKnowledgePack / Merged, with the merge implemented once in the Rust core. A star's yin-yang, five elements, dipper and chemistry are attributes that live in the pack rather than the core tables — the core StarInfo stays value-for-value identical to iztro's, while those attributes are a school's reading. See Knowledge packs.

Reverse lookup (no iztro equivalent)

iztro goes one way only: birth moment → chart. x-iztro adds the reverse direction: solar_dates_by_bazi recovers solar birth dates from four BaZi pillars — interpreted under the boundary readings of the Config you pass, the same semantics as raw_dates.chinese_date — and reverse_chart recovers birth candidates from chart features (soul/body palace branches, five elements class, star placements, birth-year mutagens). Both are pruned enumeration followed by full re-charting, so results have zero divergence from forward charting. A set of pillars recurs roughly every 60 years, so multiple solutions are inherent; chart any candidate to reproduce the target.

The entry points: solar_dates_by_bazi / reverse_chart in Rust and Python, SolarDatesByBazi / ReverseChart in Go (each with a Context variant). See Reverse lookup.

Everything else

  • Language-independent keys: every field on the astrolabe carries a *key / *Key alongside its translated name, valued with iztro's i18n keys. Predicate logic is therefore unaffected by the chart language and never has to reverse-look-up a translation. See The key contract.
  • The semantic text projection (to_text): project an astrolabe, a horoscope, a palace or the surrounded palaces into natural-language text, for a language model or a person. See Semantic text.
  • Up-front validation at the entry points: invalid dates, out-of-range hours and the like return an error rather than panicking, with a machine-readable category code. See Error handling.
  • Custom mutagen and brightness tables: replace the built-in data wholesale, by key. See Config in depth.
  • all_keys: fetch all 260 translatable keys at once.

Numeric consistency

Beyond API parity, chart output has zero field-level divergence from iztro, held by 716,314 golden cases. The coverage matrix and how it is verified are on Accuracy.

On this page