Charting entries

BySolar, ByLunar, Rearranged and the semantic text projection.

Charting is where everything starts: give a birth date, hour and gender, get an *Astrolabe.

Every entry point returns an error. Date format and existence, the solar year range, the hour index, gender, language and configuration are all validated up front in the core. See Error handling.


BySolar

Purpose Chart a natal chart from a solar date.

Zi Wei meaning Zi Wei Dou Shu computes on the lunar calendar, but most people only remember their solar birthday. This function converts solar to lunar first (including the year, month, day and hour pillars) and places the stars from there. When the year turns over is governed by YearDivide — for someone born between lunar New Year and the Beginning of Spring, the two settings give different year pillars, which in turn affects the mutagens, the soul and body stars, and every year-based star.

Signature

func BySolar(
    solarDate string,
    timeIndex uint8,
    gender Gender,
    fixLeap bool,
    language Language,
    config *Config,
) (*Astrolabe, error)

Parameters

ParameterTypeRequiredDefaultDescription
solarDatestringYesSolar date in YYYY-M-D; month and day need no zero padding. Years 1583–9999
timeIndexuint8YesHour index 0–12. 0 is the early Zi hour (00:00–01:00), 12 the late Zi hour (23:00–24:00)
genderGenderYesGenderMale or GenderFemale (the literals "male"/"female" also work). Sets the direction of the decadal scope and of the Changsheng and Boshi gods
fixLeapboolYesWhether to correct for lunar leap months. When true, the sixteenth of a leap month onward counts as the next month (the late Zi hour excepted, see below)
languageLanguageYesChart language (LanguageZhCN and friends); affects every translated field. The *Key fields are unaffected
config*ConfigYesCharting configuration; pass nil for the defaults

Return value *Astrolabe — a complete chart with the twelve palaces, the four pillars, the soul and body stars and the five elements class.

Example

chart, err := iztro.BySolar("2000-8-16", 2, iztro.GenderFemale, true, iztro.LanguageEnUS, nil)
if err != nil {
    log.Fatal(err)
}

fmt.Println(chart.SolarDate, "|", chart.LunarDate, "|", chart.ChineseDate)
fmt.Println(chart.Sign, chart.Zodiac, chart.FiveElementsClass)
fmt.Println("soul", chart.Soul, "body", chart.Body)

Output

2000-8-16 | 二〇〇〇年七月十七 | geng chen - jia shen - bing woo - geng yin
leo dragon wood 3rd
soul rebel body scholar

LunarDate is a lunar date in Chinese numerals and stays Chinese under every language; 二〇〇〇年七月十七 is the 17th day of the 7th lunar month of 2000.

Edge cases and pitfalls


ByLunar

Purpose Chart a natal chart from a lunar date.

Zi Wei meaning The lunar date is Zi Wei Dou Shu's native input, and this skips the solar conversion. Anyone who knows their lunar birthday can use it directly; the result is identical to calling BySolar with the corresponding solar date.

Signature

func ByLunar(
    lunarDate string,
    timeIndex uint8,
    gender Gender,
    leap LeapMonth,
    language Language,
    config *Config,
) (*Astrolabe, error)

Parameters Identical to BySolar apart from the following two; BySolar's fixLeap is folded into leap here.

ParameterTypeRequiredDefaultDescription
lunarDatestringYesLunar date in YYYY-M-D; write the month as a positive number (leap months are flagged by the next parameter)
leapLeapMonthYesNotLeapMonth — not a leap month; LeapMonthKeep — leap month, charted as itself; LeapMonthFixed — leap month, and days after the 15th are treated as the next month (iztro fixLeap). Flagging a leap month that does not exist in that year falls back to the ordinary month; any other value returns ErrInvalidArgument

Return value Same as BySolar.

Example

a, _ := iztro.ByLunar("2000-7-17", 2, iztro.GenderFemale, iztro.NotLeapMonth, iztro.LanguageEnUS, nil)
b, _ := iztro.BySolar("2000-8-16", 2, iztro.GenderFemale, true, iztro.LanguageEnUS, nil)

fmt.Println(a.SolarDate, a.SolarDate == b.SolarDate)

Output

2000-8-16 true

Edge cases and pitfalls

The silent fallback for a wrongly flagged leap month

Flag leap as a leap month when that month is not one and the chart is cast for the ordinary month without an error (as in iztro). If you need strict validation, confirm the leap month exists for that year and month before calling.


Config

The charting configuration. Every field may be omitted, and omitting it takes the default.

type Config struct {
    YearDivide      string
    HoroscopeDivide string
    AgeDivide       string
    DayDivide       string
    Algorithm       string
    AstroType       string
    Mutagens        map[string][]string
    Brightness      map[string][]string
}
FieldValuesDefaultDescription
YearDivide"normal" / "exact""normal"Whether the year pillar turns over at lunar New Year or the Beginning of Spring
HoroscopeDivide"normal" / "exact""normal"Which boundary the yearly spirits take their year branch from
AgeDivide"normal" / "birthday""normal"Whether the nominal age increments with the lunar year or with the birthday
DayDivide"forward" / "current""forward"Whether the late Zi hour belongs to the next day or the current one
Algorithm"default" / "zhongzhou""default"The algorithm school
AstroType"heaven" / "earth" / "human""heaven"The charting perspective
MutagensStem key → four star keysA custom mutagen table, replacing the whole table for a stem
BrightnessStar key → twelve brightness keysA custom brightness table, replacing the whole table for a star

Example

cfg := &iztro.Config{
    Algorithm:  iztro.AlgorithmZhongzhou,
    YearDivide: iztro.YearDivideExact,
}
chart, _ := iztro.BySolar("2000-8-16", 2, iztro.GenderFemale, true, iztro.LanguageEnUS, cfg)

fmt.Println(chart.FiveElementsClass)

Output

wood 3rd

Every value set has matching constants, so you need not write the strings by hand: YearDivideNormal / YearDivideExact, HoroscopeDivideNormal / HoroscopeDivideExact, AgeDivideNormal / AgeDivideBirthday, DayDivideForward / DayDivideCurrent, AlgorithmDefault / AlgorithmZhongzhou, AstroHeaven / AstroEarth / AstroHuman.

Edge cases and pitfalls


Rearranged

Purpose Re-anchor the chart on a given stem and branch as the Soul palace and return a new chart; the original is untouched.

Zi Wei meaning The Zhongzhou school reads one set of birth data as three charts: the heaven chart anchors the five elements class on the Soul palace's pillar, the earth chart on the Body palace's, the human chart on the Spirit palace's. Change the anchoring pillar and the class changes, and with it the placement of Ziwei and Tianfu, the twelve palace names, the Changsheng gods and the decadal and age scopes are all recomputed. This method opens that capability up to any stem and branch.

Signature

func (a *Astrolabe) Rearranged(fromStemKey string, fromBranchKey string) (*Astrolabe, error)

Parameters

ParameterTypeRequiredDefaultDescription
fromStemKeystringYesStem key of the new Soul palace
fromBranchKeystringYesBranch key of the new Soul palace

Return value A new *Astrolabe. Recomputed: the Soul and Body palaces, the five elements class, the fourteen major stars, the twelve palace names, the Changsheng gods, the decadal and age scopes, the soul star, plus Tianshang, Tianshi and Tiancai, which follow the Soul palace. Carried over from the original chart: minor stars, the remaining adjective stars, the Boshi gods, the Sui-qian and Jiang-qian gods, and the body star.

On the rearranged chart, Patterns, horoscope queries and the ToText projection all compute from the rearranged layout — the five elements class, soul palace and decadal ranges follow the new starting stem-branch; the birth data (dates and four pillars) stays unchanged.

Example

chart, _ := iztro.BySolar("2000-8-16", 2, iztro.GenderFemale, true, iztro.LanguageEnUS, nil)

// anchor on the original chart's Body palace pillar — equivalent to the earth chart
var body *iztro.Palace
for i := range chart.Palaces {
    if chart.Palaces[i].IsBodyPalace {
        body = &chart.Palaces[i]
    }
}
earth, _ := chart.Rearranged(body.HeavenlyStemKey, body.EarthlyBranchKey)

fmt.Println("heaven", chart.FiveElementsClass, "→ earth", earth.FiveElementsClass)

Output

heaven wood 3rd → earth earth 5th

Edge cases and pitfalls

The three standard charts do not need this method

For the heaven, earth and human charts just chart with &Config{AstroType: iztro.AstroEarth}; both charting entry points support it. Rearranged exists for anchoring on an arbitrary stem and branch.


Semantic text (ToText)

Purpose Project a chart or a horoscope into semantic text — the chart's facts in natural-language form, for a language model or a person. Alongside the JSON DTO (machine structure) and the translated fields (display), it is the third projection of the same object.

Signature

func (a *Astrolabe) ToText() (string, error)
func (h *Horoscope) ToText() (string, error)
func (a *Astrolabe) PalaceToText(target PalaceTarget) (string, error)
func (a *Astrolabe) SurroundedPalacesToText(target PalaceTarget) (string, error)

Each has a Context variant (ToTextContext etc.); the ctx cancels waiting for the wasm instance. Pattern text is PatternsToText — see Patterns.

Parameters

ParameterTypeRequiredDefaultDescription
targetPalaceTargetYesPalace addressing: with a non-empty Key the palace is located by name key (PalaceSoul etc.; PalaceBody / PalaceOriginal are also accepted), otherwise by Index (0–11)

Return value string — sectioned plain text in the chart's own charting language; the natal text closes with a patterns section, and each horoscope scope carries a patterns line and flowing-star lines from its own perspective.

Example

chart, _ := iztro.BySolar("2000-8-16", 2, iztro.GenderFemale, true, iztro.LanguageEnUS, nil)
text, _ := chart.ToText()

fmt.Println(string([]rune(text)[:68]))

Output

=== Basic Info ===
Gender: female
Solar Date: 2000-8-16
Lunar Date: 

Edge cases and pitfalls

The output language follows the chart's charting language and is not set separately. For an English text, chart in English.

On this page