This document is the unified reference for celestial-core.
Language-specific guides: python.md · javascript.md · php.md
[dependencies]
celestial-core = { path = "../core" }All symbols are available at the crate root (backward-compatible) and via their domain module (preferred):
// Preferred — explicit, IDE-friendly
use celestial_core::position::{calc_ut, CalcOptions};
use celestial_core::motion::{RiseTransOptions, SearchOptions};
use celestial_core::chart::{AspectOrbs, full_dignity, firdaria};
use celestial_core::moon::{moon_phase, sabbats_for_year};
use celestial_core::calendar::{jewish_holidays, easter_gregorian};
use celestial_core::body::{Body, CalcFlags, HouseSystem};
// Convenience — import everything at once
use celestial_core::prelude::*;
// Still works — crate root re-exports all domain modules
use celestial_core::calc_ut;The public API is a single flat namespace:
use celestial_core::*;/// #[non_exhaustive] — match arms must include `_` wildcard.
pub enum Error {
// Structured variants (carry typed fields for programmatic inspection)
BodyNotImplemented { body: i32 },
StarNotFound { name: String },
PhaseNotFound { phase: String, from_jd: f64 },
NoEclipseFound { from_jd: f64 },
CircumpolarBody { body: i32, lat: f64 },
HouseSystemFailed { system: u8, lat: f64 },
// Legacy string variants (kept for backward compatibility)
Calc(String),
Houses(String),
Eclipse(String),
RiseTrans(String),
Date(String),
}All variants implement Display with a human-readable message, so e.to_string() always works regardless of which variant is returned.
The following structs derive serde::Serialize and serde::Deserialize and can be used directly with serde_json::to_value() or any serde format:
| Struct | Fields |
|---|---|
ChartAspect |
body1, body2, aspect, orb, applying |
Stations |
retrograde, direct |
ArabicPart |
name, formula, degree |
DashaLevel |
body, start, end, years |
| Function | Signature | Description |
|---|---|---|
julday |
(y, m, d, h, cal) → f64 |
Calendar date → Julian day number |
revjul |
(jd, cal) → CalDate |
Julian day → calendar date |
utc_to_jd |
(date, cal) → JdPair |
UTC → (jd_et, jd_ut) |
deltat |
(jd) → f64 |
ΔT = TT − UT1 in days |
sidtime |
(jd_ut) → f64 |
Greenwich Apparent Sidereal Time (hours) |
mean_sidtime |
(jd) → f64 |
Mean sidereal time (degrees) |
day_of_week |
(jd) → u8 |
0 = Sunday … 6 = Saturday |
jdnow |
() → f64 |
Current Julian day (UTC) |
CalDate fields: year month day hour cal
| Function | Signature | Description |
|---|---|---|
calc_ut |
(jd, body, flags) → Result<PlanetPos> |
Geocentric position (UT input) |
calc |
(jd, body, flags) → Result<PlanetPos> |
Geocentric position (TT/ET input) |
calc_many |
(jd, &[body], flags) → Result<Vec<PlanetPos>> |
Parallel multi-body (TT) |
calc_ut_many |
(jd, &[body], flags) → Result<Vec<PlanetPos>> |
Parallel multi-body (UT) |
calc_pctr |
(jd, body, center, flags) → Result<PlanetPos> |
Position relative to center |
fixstar_ut |
(name, jd, flags) → Result<FixStarPos> |
Fixed star (UT) |
fixstar_mag |
(name) → Result<f64> |
Fixed star visual magnitude |
nutation |
(jde) → (dpsi, deps) |
IAU 2000B nutation in longitude + obliquity (degrees) |
nod_aps |
(jd, body, flags, method) → Result<NodAps> |
Nodes and apsides |
PlanetPos fields:
| Field | Type | Description |
|---|---|---|
lon |
f64 |
Ecliptic longitude (degrees) |
lat |
f64 |
Ecliptic latitude (degrees) |
dist |
f64 |
Distance (AU for planets, light-years for stars) |
speed_lon |
f64 |
Daily speed in longitude (°/day) |
speed_lat |
f64 |
Daily speed in latitude |
speed_dist |
f64 |
Daily change in distance |
ret_flags |
i32 |
Return flags from the calculation |
Body constants:
| Constant | Value | Body |
|---|---|---|
SUN |
0 | Sun |
MOON |
1 | Moon |
MERCURY |
2 | Mercury |
VENUS |
3 | Venus |
MARS |
4 | Mars |
JUPITER |
5 | Jupiter |
SATURN |
6 | Saturn |
URANUS |
7 | Uranus |
NEPTUNE |
8 | Neptune |
PLUTO |
9 | Pluto |
MEAN_NODE |
10 | Mean Lunar Node |
TRUE_NODE |
11 | True Lunar Node |
CHIRON |
15 | Chiron |
Calculation flags:
| Flag | Description |
|---|---|
FLG_BUILTIN |
Use built-in ephemeris (required) |
FLG_SPEED |
Include daily speed in result |
FLG_SIDEREAL |
Sidereal positions (requires set_sid_mode first) |
FLG_EQUATORIAL |
Equatorial coordinates (RA/Dec) |
FLG_HELCTR |
Heliocentric positions |
FLG_TOPOCTR |
Topocentric (requires set_topo first) |
FLG_NONUT |
Suppress nutation correction |
FLG_XYZ |
Cartesian (x, y, z) output |
| Function | Signature | Description |
|---|---|---|
set_sid_mode |
(mode, t0, ayan_t0) |
Activate a sidereal ayanamsa |
set_topo |
(lon, lat, alt_m) |
Set topocentric observer position |
ayanamsa_ut |
(jd_ut) → f64 |
Ayanamsa for the active mode |
ayanamsa |
(jd_et) → f64 |
Ayanamsa (TT input) |
ayanamsa_name |
(mode) → &str |
Name of a sidereal mode |
planet_name |
(body) → &str |
Body number → display name |
Sidereal modes:
| Constant | Value | Mode |
|---|---|---|
SIDM_FAGAN_BRADLEY |
0 | Fagan-Bradley |
SIDM_LAHIRI |
1 | Lahiri (official Indian) |
SIDM_DELUCE |
2 | DeLuce |
SIDM_RAMAN |
3 | B.V. Raman |
SIDM_KRISHNAMURTI |
5 | Krishnamurti |
SIDM_SASSANIAN |
11 | Sassanian |
SIDM_USER |
255 | User-defined |
| Function | Signature | Description |
|---|---|---|
houses |
(jd, lat, lon, sys) → Result<HouseResult> |
House cusps + angles |
houses_ex |
(jd, flags, lat, lon, sys) → Result<HouseResult> |
With sidereal/topocentric flags |
house_pos |
(armc, lat, eps, sys, pos) → Result<f64> |
House position of a body |
house_name |
(sys) → &str |
System byte → name |
HouseResult fields:
| Field | Description |
|---|---|
cusps[12] |
House cusps; index 0 unused, 1–12 are the twelve house cusps |
ascmc[0] |
Ascendant (ASC) |
ascmc[1] |
Midheaven (MC) |
ascmc[2] |
ARMC (sidereal time × 15) |
ascmc[3] |
Vertex |
ascmc[4] |
Equatorial ASC |
ascmc[7] |
Polar ASC |
House systems:
| Byte | Name |
|---|---|
b'P' |
Placidus |
b'K' |
Koch |
b'E' |
Equal (from ASC) |
b'W' |
Whole-Sign |
b'O' |
Porphyry |
b'R' |
Regiomontanus |
b'C' |
Campanus |
b'M' |
Morinus |
b'B' |
Alcabitus |
b'X' |
Axial Rotation |
b'H' |
Azimuthal / Horizontal |
| Function | Signature | Description |
|---|---|---|
moon_phase |
(jd) → MoonPhase |
Named phase (8 variants) |
moon_illumination |
(jd) → f64 |
Fraction illuminated 0.0–1.0 |
moon_elongation |
(jd) → f64 |
Moon–Sun elongation 0°–360° |
next_new_moon |
(jd) → f64 |
JD of next new moon |
next_first_quarter |
(jd) → f64 |
JD of next first quarter |
next_full_moon_phase |
(jd) → f64 |
JD of next full moon |
next_last_quarter |
(jd) → f64 |
JD of next last quarter |
moon_phases_for_month |
(year, month) → Vec<PhaseEvent> |
All phases in a month |
moon_phase_info |
(jd) → MoonPhaseInfo |
Rich phase info with prev/next |
MoonPhase variants: NewMoon · WaxingCrescent · FirstQuarter · WaxingGibbous · FullMoon · WaningGibbous · LastQuarter · WaningCrescent
MoonPhaseInfo fields: phase · phase_name · elongation · illumination · age_days · prev_phase_jd · prev_phase_name · next_phase_jd · next_phase_name
SYNODIC_MONTH = 29.530_588_853 days is exported as a constant.
| Function | Description |
|---|---|
sabbat_jd(year, kind) |
Exact JD of a specific sabbat |
sabbats_for_year(year) |
All 8 sabbats sorted chronologically |
next_sabbat(jd) |
Next sabbat at or after jd |
esbats_for_year(year) |
All named full moons |
next_esbat(jd) |
Next named full moon |
SabbatKind: Yule(270°) · Imbolc(315°) · Ostara(0°) · Beltane(45°) · Litha(90°) · Lughnasadh(135°) · Mabon(180°) · Samhain(225°)
| Function | Description |
|---|---|
jewish_holidays(hebrew_year) |
All major holidays |
jewish_holiday_jd(year, name) |
JD of a specific holiday |
jd_to_hebrew_date(jd) |
JD → (year, month, day) |
omer_from_jd(jd) |
Tonight's Omer day |
omer_days(hebrew_year) |
Full 49-day schedule |
omer_day_jd(year, day) |
JD of a specific Omer day |
omer_declaration(day) |
Traditional Omer declaration text |
| Function | Description |
|---|---|
easter_gregorian(year) |
Western Easter → (y, m, d) |
easter_orthodox(year) |
Orthodox Easter → (y, m, d) |
christian_feasts(year) |
All moveable feasts |
christian_fixed_feasts(year) |
Fixed feasts (Christmas, Epiphany…) |
| Function | Description |
|---|---|
hijri_from_jd(jd) |
JD → (year, month, day) |
hijri_month_name(month) |
Month number → Arabic name |
islamic_observances(hijri_year) |
Major observances |
gregorian_to_hijri_years(year) |
Overlapping Hijri years |
| Function | Description |
|---|---|
panchanga(jd) |
Full Panchānga for a JD |
hindu_festivals(year) |
Major festivals for a Gregorian year |
PanchangaResult fields: tithi_name · paksha · vara_name · nakshatra_name · nakshatra_pada · yoga_name · karana_name
| Function | Description |
|---|---|
vesak_jd(year) |
Vesak (Buddha Day) JD |
uposatha_days(year) |
All four Uposatha phases |
| Function | Description |
|---|---|
nowruz_jd(year) |
Exact Nowruz JD (vernal equinox) |
gregorian_to_solar_hijri(year) |
Gregorian → Solar Hijri year |
naw_ruz_jd(bahai_year) |
Bahá'í Naw-Rúz JD |
jd_to_bahai(jd) |
JD → BahaiDate |
bahai_holy_days(bahai_year) |
11 Bahá'í holy days |
BahaiDate: year (BE) · month (1–19, 0=Ayyám-i-Há) · day · month_name
Replaces calc_ut, calc, calc_many, calc_ut_many with a single discoverable API.
use celestial_core::{CalcOptions, CalcStrategy, Body, CalcFlags};
// Single body (UT)
let pos = CalcOptions::ut(jd, CalcFlags::BUILTIN | CalcFlags::SPEED)
.body(Body::SUN)
.get()?;
// Multiple bodies — Auto strategy (sequential ≤2, parallel >2)
let results = CalcOptions::ut(jd, CalcFlags::BUILTIN)
.bodies(&[Body::SUN, Body::MOON, Body::MERCURY])
.get_many();
// Force sequential
let results = CalcOptions::ut(jd, CalcFlags::BUILTIN)
.strategy(CalcStrategy::Sequential)
.bodies(&[Body::SUN, Body::MOON])
.get_many();CalcStrategy variants: Sequential · Parallel · Auto (default)
use celestial_core::{RiseTransOptions, Body, CalcFlags};
let result = RiseTransOptions::new(jd, Body::MOON, [lon, lat, alt_m])
.event(1) // 1=rise, 2=set, 4=upper transit
.atmosphere(1013.25, 15.0) // pressure mb, temperature °C
.flags(CalcFlags::BUILTIN)
.search()?;
println!("Rises at JD {}", result.tret);use celestial_core::{SearchOptions, Body, CalcFlags, HouseSystem};
// Aspect to house cusp
let hit = SearchOptions::new(Body::SATURN, jd_start)
.aspect(90.0)
.cusp(10, lat, lon, HouseSystem::PLACIDUS)
.search_cusp();
// Natal angle transits
let jd = SearchOptions::new(Body::SATURN, jd_start)
.natal_chart(jd_natal, lat, lon, HouseSystem::PLACIDUS)
.search_mc_transit()?;
// Also: .search_ic_transit() · .search_asc_transit() · .search_dsc_transit()use celestial_core::AspectOrbs;
let m = AspectOrbs::new(2.0, 1.5) // applying_orb, separating_orb
.def_orb(2.0)
.check(pos0, speed0, pos1, speed1, 120.0); // trine
assert!(m.matched);
println!("Orb: {:.2}° Applying: {}", m.diff.abs(), m.diff < 0.0);11-year sunspot cycle context. Useful for natal-chart annotation, long-term correlations, and any heliophysical work that needs "where is the Sun in its activity cycle right now." Data anchored to SIDC/SILSO observed minima and maxima for cycles 1..=25 (1755 → ~2030). Asymmetric phase classification follows the Waldmeier effect (rise ~4y, decline ~7y).
| Function | Signature | Description |
|---|---|---|
solar_cycle |
(jd) → Option<SolarCycleInfo> |
Full per-JD info or None outside cycles 1–25 |
grand_solar_epoch |
(jd) → Option<GrandSolarEpoch> |
Long-term envelope (Maunder, Dalton, …) for any JD |
cycle_nickname |
(u8) → Option<&'static str> |
Informal cycle names (e.g. cycle 19 = "the Great Cycle") |
SolarCycleInfo fields:
| Field | Type | Description |
|---|---|---|
cycle_num |
u8 |
Wolf/Schwabe cycle number (1..=25) |
phase |
f64 |
Time-fractional position 0.0 → 1.0 |
phase_name |
SolarCyclePhase |
Minimum · Rising · Maximum · Declining |
min_jd / max_jd / next_min_jd |
f64 |
Anchored cycle boundaries |
years_since_min |
f64 |
Years elapsed since the cycle's solar minimum |
nickname |
Option<&'static str> |
e.g. "the Great Cycle" for cycle 19 |
grand_epoch |
Option<GrandSolarEpoch> |
Long-term envelope if applicable |
GrandSolarEpoch variants: SporerMinimum (1450-1550) · MaunderMinimum (1645-1715) · DaltonMinimum (1790-1830) · ModernMaximum (1950-2000).
In the chart renderer, ctx["solar_cycle"] always exists; the object contains
the full breakdown for in-range dates, only grand_epoch for dates inside a
named long-term envelope but outside the numbered cycles, and is empty
otherwise. The built-in natal SVG renders a compact "Solar Cycle" table
beside the Arabic Parts block.
| Function | Description |
|---|---|
solcross_ut(lon, jd, flags) |
Next solar ecliptic longitude crossing |
mooncross_ut(lon, jd, flags) |
Next lunar ecliptic longitude crossing |
helio_cross_ut(body, lon, jd, flags, dir) |
Heliocentric crossing |
mooncross_node(jd, flags) |
Next Moon/node crossing |
rise_trans(jd, body, star, flags, rsmi, geo, press, temp) |
Rise / transit / set |
sol_eclipse_when_glob(jd, flags, type, back) |
Next solar eclipse |
lun_eclipse_when(jd, flags, type, back) |
Next lunar eclipse |
use celestial_core::*;
fn main() -> Result<()> {
let jd = julday(1985, 7, 14, 12.0, GREG_CAL);
let lat = 48.85;
let lon = 2.35;
// Positions
let bodies = [SUN, MOON, MERCURY, VENUS, MARS, JUPITER, SATURN,
URANUS, NEPTUNE, PLUTO, MEAN_NODE, CHIRON];
let positions = calc_many(jd, &bodies, FLG_BUILTIN | FLG_SPEED)?;
// Aspects
let pos_pairs: Vec<(i32, f64, f64)> = positions.iter().zip(bodies.iter())
.map(|(p, &b)| (b, p.lon, p.speed_lon)).collect();
let aspects = calc_chart_aspects(&pos_pairs, MAJOR_ASPECTS, 8.0);
for a in &aspects {
println!("{} {} {} orb={:.2}°",
planet_name(a.body1), a.aspect, planet_name(a.body2), a.orb);
}
// Solar return
let jd_sr = solar_return_jd(jd, 2025, FLG_BUILTIN)?;
let d = revjul(jd_sr, GREG_CAL);
println!("Solar return 2025: {:04}-{:02}-{:02}", d.year, d.month, d.day);
// Secondary progressions (35 years)
let (prog, _) = secondary_progressions(jd, 35.0, &bodies, lat, lon, b'P', FLG_BUILTIN)?;
let prog_sun = prog[0].1.lon;
let prog_moon = prog[1].1.lon;
println!("Prog Sun={:.2}° Prog Moon={:.2}°", prog_sun, prog_moon);
// Midpoint
let mid = midpoint_deg(prog_sun, prog_moon);
println!("Sun-Moon midpoint: {:.2}°", mid);
// Vedic — Vimshottari dasha
set_sid_mode(SIDM_LAHIRI, 0.0, 0.0);
let moon_sid = calc_ut(jd, MOON, FLG_BUILTIN | FLG_SIDEREAL)?;
let dashas = vimshottari_dasha(jd, moon_sid.lon, 120.0);
for d in dashas.iter().take(3) {
println!("{} dasha: {:.1} years", planet_name(d.planet), d.years);
}
// Hellenistic — dignity
let h = houses(jd, lat, lon, b'P')?;
let sun = positions[0];
let is_day = is_day_chart(sun.lon, &h.cusps);
let (dig, score) = full_dignity(SUN, sun.lon, is_day)?;
println!("Sun dignity: {dig:?} (score {score})");
// Ba Zi
let pillars = four_pillars(jd, 12.0, sun.lon);
for (i, p) in pillars.iter().enumerate() {
let label = ["Year", "Month", "Day", "Hour"][i];
println!("{label}: {} {}", p.stem_name, p.branch_name);
}
// Tonalpohualli
let (trecena, _, name, _) = tonalpohualli(jd);
println!("Aztec day: {trecena} {name}");
// Medicine Wheel
let (animal, element, clan, season) = medicine_wheel_totem(sun.lon);
println!("Totem: {animal} ({element}, {clan}, {season})");
// Hellenistic dignities
let (dig, score) = full_dignity(Body::SUN, sun.lon, is_day_chart(sun.lon, &h.cusps))?;
println!("Sun dignity: {dig:?} (score {score})");
let periods = firdaria(jd_natal, is_day_chart(sun.lon, &h.cusps), 75.0);
println!("First firdaria lord: {}", planet_name(periods[0].major_lord));
let (house, _) = annual_profection(&h.cusps, 35);
println!("Age 35 profection: house {house}");
Ok(())
}| Function | Description |
|---|---|
calc_chart_aspects(positions, aspects, orb) |
All aspects in a chart |
calc_chart_aspects_auto(positions, orbs) |
Aspects with per-planet orb table |
match_aspect(p0, s0, p1, s1, aspect, orb) |
Test if aspect is within orb |
next_retro(body, jd, back, days, flags) |
Next retrograde station |
next_aspect(body, aspect, fixed, jd, …) |
Aspect to a fixed point |
next_aspect_with(body, aspect, other, jd, …) |
Aspect between two bodies |
next_aspect_cusp(body, aspect, cusp, jd, …) |
Aspect to a house cusp |
sign_ingress_ut(body, jd, flags, back) |
Next sign ingress |
retrograde_station_ut(body, jd, flags) |
Retrograde and direct station JDs |
| Function | Description |
|---|---|
long_to_rasi(lon) |
Ecliptic longitude → rasi (sign) 0–11 |
long_to_navamsa(lon) |
Longitude → navamsa sign 0–11 |
long_to_nakshatra(lon) |
Longitude → (nakshatra 0–26, pada 0–3) |
nakshatra_name(n) |
Nakshatra number → name string |
raman_houses(asc, mc, sandhi) |
12 Raman house cusps |
vimshottari_dasha(jd, moon_lon, span) |
Dasha period list |
ochchabala(graha, lon) |
Exaltation strength 0–60 |
tatkalika_relation(g1, g2) |
Temporary relationship −1/0/1 |
naisargika_relation(g1, g2) |
Natural relationship −1/0/1 |
residential_strength(lon, cusps) |
Bhava bala |
| Function | Signature | Description |
|---|---|---|
egyptian_terms_ruler |
(lon) → Body |
Egyptian bounds (Ptolemy/Tetrabiblos) |
decan_ruler |
(lon) → Body |
Chaldean decan (face) ruler |
triplicity_rulers |
(lon) → (Body, Body, Body) |
Day / night / participating |
full_dignity |
(body, lon, is_day) → (Dignity, i8) |
Dignity name + score |
almuten |
(lon, is_day) → (Body, i8) |
Highest-scoring planet |
is_day_chart |
(sun_lon, cusps) → bool |
Sun above horizon |
same_sect |
(body, is_day) → bool |
Sect membership |
firdaria |
(jd, is_day, span) → Vec<FirdariaPeriod> |
75-year period list |
annual_profection |
(cusps, age) → (u8, f64) |
House number + lon |
monthly_profection |
(cusps, age_years, months) → (u8, f64) |
Sub-annual |
Dignity variants: Domicile · Exaltation · Triplicity · Term · Decan · Peregrine · Detriment · Fall
FirdariaPeriod fields: major_lord · minor_lord · start · end · years (JD start/end, span in years)
| Function | Signature | Description |
|---|---|---|
four_pillars |
(jd, hour_ut, sun_lon) → [BaZiPillar; 4] |
Year/Month/Day/Hour pillars |
solar_term_position |
(sun_lon) → (usize, f64, usize, f64) |
Current/next solar term |
sexagenary_name |
(idx) → (String, String) |
Stem + animal names |
BaZiPillar fields: stem_name · branch_name · animal · stem_element · branch_element · yang
Constants: SOLAR_TERMS[24] · HEAVENLY_STEMS[10] · EARTHLY_BRANCHES[12]
| Function | Signature | Description |
|---|---|---|
tonalpohualli |
(jd) → (u8, usize, &'static str, &'static str) |
Aztec 260-day: trecena, sign_idx, nahuatl, english |
xiuhpohualli |
(jd) → (usize, u8, &'static str, &'static str) |
Aztec 365-day: month_idx, day, name, english |
tzolkin |
(jd) → (u8, usize, &'static str, &'static str) |
Maya 260-day: trecena, sign_idx, mayan, english |
haab |
(jd) → (usize, u8, &'static str) |
Maya 365-day: month_idx, day, name |
calendar_round |
(jd) → (u8, &'static str, u8, &'static str) |
Tzolkin + Haab combined position |
Constants: GMT_CORRELATION = 584_283i64 · TONALPOHUALLI_SIGNS[20] · TZOLKIN_SIGNS[20] · XIUHPOHUALLI_MONTHS[18]
| Function | Signature | Description |
|---|---|---|
medicine_wheel_totem |
(sun_lon) → (&'static str, &'static str, &'static str, &'static str) |
Animal, element, clan, season |
egyptian_decan |
(lon) → (usize, &'static str, &'static str) |
Index 0–35, decan name, rising star |
All types are passed via celestial render --chart-type <n>. The 27
registered types and their aliases are derived from CHART_REGISTRY in
cli/src/cmd/render/mod.rs; unknown
types print the full alias list at runtime.
| Type | Aliases | Tradition |
|---|---|---|
natal |
(default — empty --chart-type also matches) |
Western |
cosmogram |
— | Western |
solar-return |
solar_return |
Western |
lunar-return |
lunar_return |
Western |
progressed |
secondary |
Western |
solar-arc |
solar_arc |
Western |
biwheel |
bi-wheel, synastry, transit |
Western |
composite |
— | Western |
triwheel |
tri-wheel |
Western |
dial |
90dial, midpoint-dial |
Western (Uranian) |
ephemeris |
graphic-ephemeris |
Western |
local-space |
localspace |
Western |
rasi |
vedic, south-indian |
Vedic |
navamsa |
d9 |
Vedic |
dasha |
vimshottari |
Vedic |
north-indian |
north_indian |
Vedic |
ashtakavarga |
ashtak |
Vedic |
shadbala |
strength |
Vedic |
hellenistic |
greek |
Hellenistic |
firdaria |
persian |
Persian |
profection |
— | Hellenistic |
bazi |
four-pillars, chinese |
Chinese |
mesoamerican |
aztec, maya |
Mesoamerican |
medicine-wheel |
indigenous, egyptian-decans |
Indigenous |
wheel-of-year |
sabbats, celtic |
Celtic |
omer-grid |
omer, sefirat-haomer |
Jewish |
calendar |
— | Multi-tradition |
These thin wrappers exist for SwissEph API compatibility and are available in Python, JavaScript, and PHP.
| Alias | Canonical | Notes |
|---|---|---|
degnorm(d) |
norm_deg(d) |
Normalise degrees to [0°, 360°) |
difdeg2n(p1, p2) |
diff_deg_signed(p1, p2) |
Signed diff in (−180°, +180°] |
next_sabbat_name(jd) |
next_sabbat(jd) |
Returns name string only |
next_full_moon(jd) |
next_full_moon_after(jd) |
Short name variant |
Returns the Julian Day (UT) when the Sun next crosses ecliptic longitude
x2cross degrees. Use this to find equinoxes, solstices, or any solar
degree transit.
# Python — vernal equinox (Sun crosses 0° Aries)
jd = julday(2025, 1, 1, 0.0, GREG_CAL)
equinox_jd = solcross_ut(0.0, jd, FLG_BUILTIN)// PHP
$equinox_jd = solcross_ut(0.0, $jd, FLG_BUILTIN);| Function | Returns | Notes |
|---|---|---|
iso_week(jd) |
(iso_year, week) |
ISO year may differ from calendar year near Jan 1 / Dec 31 |
day_of_year(year, month, day) |
1..366 |
— |
weeks_in_iso_year(year) |
52 | 53 |
53 iff Jan 1 or Dec 31 is a Thursday |
Uses GMT correlation (JD 584 283 = Maya Day 0).
| Function | Returns |
|---|---|
maya_long_count(jd) |
(baktun, katun, tun, uinal, kin) |
maya_long_count_str(jd) |
"13.0.0.0.0" style |
| Function | Returns |
|---|---|
yallop_q(arcv_deg, arcl_deg, sd_arcmin) |
(q, 'A'..'F') class |
best_time_method(jd_sunset, jd_moonset) |
f64 — best evaluation epoch |
Classes: A easily visible → F not visible.
| Function | Returns |
|---|---|
coptic_to_jd(y, m, d) / jd_to_coptic(jd) |
JD ↔ (year, month, day) |
ethiopic_to_jd(y, m, d) / jd_to_ethiopic(jd) |
JD ↔ (year, month, day) |
is_coptic_leap_year(year) |
bool (year mod 4 == 3) |
coptic_month_days(year, month) |
0..=30 (month 13 is epagomenal) |
13 months: 12 × 30 days + 5 or 6 epagomenal days. Same structure for both calendars, different epochs.
Reformed 1906; New Year locked to astronomical vernal equinox.
| Function | Returns |
|---|---|
fasli_nowruz_jd(year) |
Option<f64> — JD of Nowruz |
jd_to_fasli(jd) |
Option<(year, month_index, day)> |
Month index 13 = five Gatha days, plus a sixth intercalary day when successive equinox dates span 366 days.
losar_jd is an astronomical approximation, not a complete Phugpa calendar.
It omits intercalation and true-date rules and can differ from published Losar
dates by a day or month.
| Function | Returns |
|---|---|
losar_jd(year) |
Option<f64> — approximate 2nd new moon after winter solstice |
tibetan_year_name(year) |
(rabjung_cycle, year_in_cycle, element, gender, animal) |
Structurally similar to Chinese calendar but uses UTC+7 for month boundaries (since 1967).
| Function | Returns |
|---|---|
vietnamese_month_start_jd(jd_ut) |
Option<f64> — start of Hanoi civil day with starting new moon |
vietnamese_chinese_boundary_differs(jd_ut) |
bool — true if UTC+7 and UTC+8 give different civil days |
The workspace provides cargo xtask commands for binding maintenance:
cargo xtask parity # Check Python / JS / PHP export identical function sets (194/194/194)
cargo xtask codegen # Preview stubs for functions missing from bindings
cargo xtask codegen --apply # Write generated stubs into the binding sources
cargo xtask stubs # Regenerate bindings/php/phpstan-stubs.php (~400 symbols)
cargo xtask test-stubs # Validate phpstan-stubs.php for PHP 8.0 syntax
cargo xtask pyi # Regenerate bindings/python/.../celestial_py.pyi (~200 stubs)
cargo xtask pyi --check # Verify .pyi is in sync (CI gate)
cargo xtask dts # Regenerate bindings/js/index.d.ts (~275 declarations — struct interfaces, constants, functions)
cargo xtask dts --check # Verify .d.ts is in sync (CI gate)
cargo xtask golden # Regenerate native binding numeric fixtures from core
cargo xtask golden --check # Verify native fixtures are in sync (CI gate)The --check variants exit non-zero if the generated file is out of sync,
so CI catches stale stubs before merge.
The render subcommand accepts a separate --time argument for convenience:
# Equivalent — time embedded in date string:
celestial render --chart-type natal --date "1990-05-15 14:30" --timezone UTC --lat 48.85 --lon 2.35
# Or separated — easier for scripts:
celestial render --chart-type natal --date 1990-05-15 --time 14:30 --timezone UTC --lat 48.85 --lon 2.35
# Seconds accepted; display truncates to HH:MM:
celestial render --date 1990-05-15 --time 14:30:45 --timezone UTC--time is ignored when --date already contains a time, is "now", or is a
raw Julian Day.