Astrology9 MIN READ17 / 31

Panchang Engine — High-Level Design

Status: Draft for review · Part of: Astro Composer · Updated: 2026-10-24

The panchang engine turns one local day into five limbs — tithi (lunar day), vara (weekday), nakshatra (lunar mansion), yoga and karana (half-tithi) — each with exact start and end instants anchored to sunrise. It is pure arithmetic on binder positions and rise/set answers: no provider call, interpolation, timezone database or clock.

1. Purpose

Panchang is what users check against a printed almanac, so a convention error shows immediately. Four conventions matter:

  • The day’s tithi is the one running at sunrise, not at midnight.
  • Vara (the weekday) changes at sunrise.
  • A tithi can be skipped (kshaya) or repeat (adhika).
  • People expect an end time (“Panchami ends at 14:32”), not just a name.

The engine exists so that:

  1. one sunrise definition anchors the day, tithi and vara;
  2. every limb is an interval with exact boundary instants, not a sampled guess;
  3. kshaya and adhika tithis are never deduplicated;
  4. tithi and karana ignore ayanamsa while nakshatra and yoga inherit it;
  5. every response names its profile, rulebook and binder provenance.

2. Where it sits

binder rise-set + positions ──┐
request · local date + offset ─┼──▶ panchang engine ──▶ five limbs + boundary instants
observer · profile · rulebook ┘
  • Upstream: the composition facade supplies the local date, UTC offset, observer, profile and one rulebook handle; the binder client supplies sunrise, next sunrise and Sun/Moon positions on request.
  • Downstream: the facade builds POST /v1/panchang; muhurta packs and calendar features reuse the same limb intervals.
  • Never: it does not call a provider, interpolate an ephemeris, read a clock, use a timezone database, or produce festival and muhurta rules.

Input contract

Input Source Used for
Local date Request The sunrise-to-sunrise day to describe
UTC offset Request Resolving the local day to an absolute search window; no tz database
Observer Request Latitude, longitude and elevation for the Hindu sunrise
Profile Request Sunrise definition (C6), day boundary (C7), zodiac and ayanamsa
Rulebook handle Registry Limb names, tithi names, karana cycle, boundary tolerance
Rise/set answer Binder POST /v1/rise-set Sunrise, next sunrise, optional sunset
Sun and Moon positions Binder POST /v1/positions Longitude, speed, sign and nakshatra id per probe
Boundary probes Facade through the binder client Additional instants requested by the solver

Output contract

Output Shape Read by
day Local date, offset, sunrise, next sunrise, optional sunset Response, muhurta packs
atSunrise Tithi, vara, nakshatra, yoga and karana at the sunrise instant Response, daily summary
limbs.tithi[] Index, name, paksha, start, end, kshaya, adhika Response, muhurta filters
limbs.nakshatra[] Index, name, start, end Response, muhurta filters
limbs.yoga[] Index, name, start, end Response, muhurta filters
limbs.karana[] Index, name, movable or fixed, start, end Response, muhurta filters
vara Canonical weekday id, weekday index, start, end Response, muhurta filters
boundaryPrecision Tolerance, probe count, convergence state Audit and fixtures
diagnostics No sunrise, missing next sunrise, unavailable sunset Facade degradation and errors

3. Responsibilities

Each area owns one decision and one deterministic rule.

Area Owns Deterministic rule
Day anchor Sunrise, next sunrise and the day interval Day is [sunrise, nextSunrise); vara changes at sunrise
Tithi 12° elongation intervals and names floor(elongation / 12) + 1, 1–30; half-open
Vara Weekday of the sunrise instant Derived from sunrise, never from civil midnight
Nakshatra Moon nakshatra intervals Binder id is authority; engine only finds change instants
Yoga 13°20′ of (sun + moon) mod 360 floor(((sun + moon) mod 360) / 13.3333…)
Karana 6° elongation intervals, 60 per lunation Rulebook cycle of seven movable and four fixed names
Boundary solve Crossing instant for each limb Bracketed root with a Newton step on binder speed, ≤ 1 s
Tithi flags Kshaya, adhika and at-sunrise state Derived from which sunrises the interval contains
Assembly Five limbs in a fixed order Canonical ids, UTC instants, one rounding point

4. Architecture

Panchang Engine — High-Level Design Five sunrise-anchored limbs with solved boundary instants, over binder positions and rise-set. Reference design, not deployed behaviour. Panchang Engine — High-Level Design Five sunrise-anchored limbs with solved boundary instants, over binder positions and rise-set. Request · local day civil date + UTC offset no timezone database Observer latitude · longitude elevationMeters Profile + rulebook sunrise = hindu (C6) limb names · karana cycle Panchang engine · pure arithmetic over a probe port Sunrise anchor hindu sunrise · next sunrise vara changes at sunrise Boundary solver tithi · nakshatra · yoga · karana Newton on speed · 1 s tolerance Tithi + karana 12° and 6° elongation intervals paksha · movable and fixed names Nakshatra + yoga binder nakshatra id is authority yoga from sun + moon longitude Vara + interval flags sunrise-to-sunrise weekday kshaya · adhika · at-sunrise Panchang assembler five limbs in fixed order half-open UTC intervals Probe port: the engine asks for an instant; the facade performs the binder read. No approximation: a boundary that misses one second fails the request. Astro Binder · existing deployable Rise-set · proposed hindu or astronomical sunrise · next sunrise Positions sun + moon longitude speed · nakshatra id Timeseries · proposed grid + speeds phase 3 probe reduction Probe requests are HTTPS JSON, facade-owned. The engine holds no client. Panchang layer · facade atSunrise + interval lists profile · rulebook · binder meta Muhurta packs consume panchang facts phase 3 · purpose-specific Derived cache complete response · HMAC key no birth data in keys date + offset observer conventions rise/set + values panchang layer facts cache write dependency pure module engine output boundary Reference design · not deployed behaviour.

Diagram: reference design, not deployed behaviour.

The engine is a pure module with one seam: a boundary probe port. The engine picks the next instant it needs; the facade runs the binder read. That keeps the solver deterministic and testable without a network client, cache or clock.

5. Rules

  1. Sunrise defines the day. Day tithi and vara are the ones at sunrise; midnight or noon boundaries are a different product and are not served.
  2. Five limbs, two quantities. Tithi and karana use Sun–Moon elongation, nakshatra the sidereal Moon, yoga the sidereal Sun-plus-Moon sum, vara the sunrise instant. No other body participates.
  3. The binder owns nakshatra. The engine reads its nakshatra id per probe and may use the in-segment remainder as a Newton step, never deriving an id from a longitude.
  4. Tithi and karana ignore ayanamsa. Both are longitude differences, so a profile change cannot move them. Sidereal nakshatra and yoga do move; the response names the profile.
  5. Boundaries are solved, not sampled. Every limb carries start and end instants; missing one second fails the request.
  6. No ephemeris interpolation. The probe port returns longitude and speed and the engine only does arithmetic; the facade owns every binder read.
  7. Half-open intervals. A limb beginning exactly at a boundary belongs to the new interval; one beginning at sunrise opens the day.
  8. Kshaya and adhika are reported. A tithi with no sunrise inside is kshaya; one holding both the day’s sunrise and the next is adhika. Neither is removed, merged or renumbered.
  9. Karana is a rulebook cycle. Seven movable names repeat eight times per lunation; the first half of Shukla Pratipada and the last three half-tithis are fixed. Names and positions come from the rulebook.
  10. Vara is sunrise to sunrise. The id is the Sanskrit weekday (somavara) plus an index; display names belong to the client.
  11. No timezone database, no clock. The caller supplies the local date and offset; the engine returns UTC instants and never resolves DST, reads the server clock or formats a date.
  12. No partial panchang. Missing sunrise, missing next sunrise or a non-converged boundary fails the request; allowPartial does not cover the five limbs. A missing sunset is null.
  13. The probe budget is a contract. Each boundary gets a bounded probe count; exhausting it is LIMIT_EXCEEDED, never an approximate boundary.
  14. Deterministic order. Limbs are emitted tithi, vara, nakshatra, yoga, karana, intervals ordered by start. Two identical requests give byte-identical output.

6. Edge cases

Bad input fails loudly; nothing is silently approximated.

Case Behaviour
Polar day: no sunrise on the local date 422 LAYER_UNSUPPORTED with reason: "no_sunrise"; no midnight fallback
Polar night: sunrise exists but no next sunrise Same failure; no fabricated 24-hour day
Tithi begins after sunrise and ends before next sunrise Included with kshaya: true; not removed from the day list
Same tithi at two consecutive sunrises adhika: true; one interval spans both sunrises
Tithi ends exactly at sunrise Half-open rule makes the new tithi the day’s tithi
Nakshatra changes exactly at sunrise Binder id at sunrise decides; boundary instant is sunrise
Two karana boundaries in one day Both intervals returned in order, never collapsed
Karana interval crosses the next sunrise Ends at the solved boundary; the next day owns the remainder
Elongation or Moon longitude at 359.9999° Wraps correctly; intervals are never negative or reordered
Ayanamsa changes at a nakshatra boundary Nakshatra and yoga move; tithi and karana do not
DST transition in the supplied offset Caller resolves the offset; engine uses the supplied offset and no tz database
Binder omits speed for a probe Solver falls back to bracketed bisection within the same probe budget
Boundary solver exhausts its probe budget LIMIT_EXCEEDED; no approximate boundary in a success response
Binder degraded to a lower-precision engine Panchang still returned; degraded propagates in binder metadata
Sunset unavailable but sunrise present Panchang returned; sunset: null; limbs unaffected
Local date skipped by a civil calendar change Caller’s offset defines the instant; the engine does not invent a date
Leap second near a boundary Instants remain UTC; the one-second tolerance absorbs the discontinuity
allowPartial requested Ignored for the five limbs; missing sunrise still fails
Very short or very long day at high latitude Sunrise and next sunrise still define the day; no minimum day length

7. Out of scope

  • Muhurta windows, Rahu kala, Yamaganda, Gulika, panchaka, Abhijit, hora and choghadiya (muhurta packs).
  • Festival names, samvat, regional month names and calendar conversion.
  • Sunrise, sunset and horizon astronomy (Astro Binder).
  • Eclipses, upagraha, planetary war, transits and dasha periods.
  • Alternative day boundaries at midnight or noon.
  • Timezone database and DST resolution (caller and facade).
  • Interpretation, remedies and almanac prose (product content).
  • Caching and provenance storage (facade, result cache and provenance store).
  • Matching, transits and natal chart assembly (chart core).

8. Planned code

Piece Responsibility
panchang/PanchangEngine Admission, probe planning and five-limb assembly
panchang/SunriseAnchor Hindu sunrise, next sunrise and vara boundary
panchang/BoundaryProbePort Instant probe contract executed by the facade
panchang/LimbBoundarySolver Bracketed root, Newton step, tolerance and budget
panchang/TithiResolver 12° intervals, paksha, names, kshaya and adhika flags
panchang/NakshatraYogaResolver Binder nakshatra changes and yoga intervals
panchang/KaranaCycle 60-karana rulebook cycle, names and movable/fixed state
panchang/VaraResolver Sunrise weekday id, index and interval
panchang/PanchangAssembler Ordered intervals, at-sunrise values and rounding