panchang-ts 3.0.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,31 +2,10 @@
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/panchang-ts)](https://www.npmjs.com/package/panchang-ts)
4
4
 
5
- Pure TypeScript Hindu Panchang (almanac) calculations. Zero native dependencies.
6
- Works offline in React Native (Hermes), Node.js, and browsers.
5
+ Pure TypeScript Hindu Panchang (almanac), Jyotish, and Birth Chart calculations.
6
+ Zero native dependencies. Works offline in React Native (Hermes), Node.js, and browsers.
7
7
 
8
- **Fast** (~0.1 ms names-only, ~0.5 ms full) | **Typed** (full TypeScript types) | **Offline** (pure JS math, no network)
9
-
10
- ---
11
-
12
- ## Table of Contents
13
-
14
- - [Install](#install)
15
- - [Quick Start](#quick-start)
16
- - [Features](#features)
17
- - [API Reference](#api-reference)
18
- - [`getDailyPanchang`](#getdailypanchangdate-location-options)
19
- - [`getInstantPanchang`](#getinstantpanchangdate-location-options)
20
- - [When to use `getInstantPanchang` vs `getDailyPanchang`](#when-to-use-getinstantpanchang-vs-getdailypanchang)
21
- - [Options](#options)
22
- - [Low-level Utilities](#low-level-utilities)
23
- - [Birth Chart (Kundli) API](#birth-chart-kundli-api)
24
- - [Types](#types)
25
- - [React Native / Hermes](#react-native--hermes)
26
- - [Accuracy](#accuracy)
27
- - [Performance](#performance)
28
- - [Error Handling](#error-handling)
29
- - [Compatibility](#compatibility)
8
+ **Fast** (~0.1 ms names-only, ~0.5 ms full) | **Typed** (full TypeScript types) | **Offline** (pure JS math, no network) | **7,156 tests**
30
9
 
31
10
  ---
32
11
 
@@ -40,6 +19,45 @@ pnpm add panchang-ts
40
19
  yarn add panchang-ts
41
20
  ```
42
21
 
22
+ ---
23
+
24
+ ## Features at a Glance
25
+
26
+ Every category below is implemented end-to-end, cross-verified against reference panchang
27
+ sources, and exposed through the public API. Click a row to jump to its usage example.
28
+
29
+ | Category | Features | Jump to |
30
+ |----------|----------|---------|
31
+ | **Pancha Anga (5 limbs)** | Tithi, Nakshatra, Yoga, Karana, Vara — with all transitions through the day | [↓](#1-pancha-anga--the-five-limbs) |
32
+ | **Lunar Calendar** | Chandra Masa (Purnimanta + Amanta), Adhika (leap-month) detection, Vikram Samvat, Shaka Samvat | [↓](#2-lunar-calendar) |
33
+ | **Solar Calendar** | Saura Masa, Surya Nakshatra, Sankranti (transit-based) | [↓](#3-solar-calendar) |
34
+ | **Sun & Moon** | Sunrise, Sunset, Moonrise, Moonset, Chandra Rashi (Moon sign) | [↓](#4-sun--moon) |
35
+ | **Auspicious Muhurta** | Brahma, Abhijit, Vijaya, Godhuli, Nishita, Madhyahna, Pratah / Sayahna Sandhya, Amrit Kala | [↓](#5-auspicious-muhurta) |
36
+ | **Inauspicious Periods** | Rahu Kalam, Gulika Kalam, Yamaganda, Dur Muhurta, Varjyam, Ganda Mula, Bhadra Kala, Panchaka | [↓](#6-inauspicious-periods) |
37
+ | **Time-Slot Systems** | Choghadiya (16), Gowri Panchangam / Nalla Neram (16), Hora (24), Do Ghati (30), Panchaka Rahita | [↓](#7-time-slot-systems) |
38
+ | **Special Yogas** | Anandadi (28-name cycle), Amrit Siddhi, Sarvartha Siddhi, Ravi / Guru Pushya, Dwipushkar, Tripushkar, Jwalamukhi, Aadal, Vidaal, Ravi | [↓](#8-special-yogas) |
39
+ | **Festivals (80+)** | Ekadashi (Smarta + Vaishnava split), Pradosha, Sankranti variants, classical festivals (Diwali, Holi, Shivaratri…), regional festivals across 21 states + Nepal | [↓](#9-festivals) |
40
+ | **Eclipses (Grahan)** | Solar + lunar detection, subtype, magnitude, observer-horizon visibility, sutak window | [↓](#10-eclipses) |
41
+ | **Planetary Positions** | All 9 grahas (sidereal) with rashi, nakshatra, pada, retrograde — mean or true Rahu/Ketu | [↓](#11-planetary-positions) |
42
+ | **Vimshottari Dasha** | Maha → Antar → Pratyantar (3-level) breakdown from birth | [↓](#12-vimshottari-dasha) |
43
+ | **Personal Transits** | Chandra Balam, Tarabala (9-tara cycle), Sade Sati (Saturn arc) | [↓](#13-personal-transits) |
44
+ | **Birth Chart (Kundli)** | Lagna (sidereal), Bhava under 3 house systems, D1 / D2 / D3 / D7 / D9 / D10 / D12 / D30 charts, Planetary Dignity | [↓](#14-birth-chart-kundli) |
45
+ | **Compatibility & Doshas** | Ashtakoot Guna Milan (36-point), Mangal Dosha, Kaal Sarp Dosha (12 subtypes), Pitru Dosha | [↓](#15-compatibility--doshas) |
46
+ | **Aspects & Strength** | Drishti (graha aspects), Shadbala (six-fold strength) | [↓](#16-aspects--strength) |
47
+ | **Dasha Systems** | Vimshottari (Maha→Antar→Pratyantar), Ashtottari, Yogini, Chara (Jaimini) | [↓](#17-dasha-systems) |
48
+ | **Muhurta Engine** | Configurable scoring + 13 stock occasions (vivah, griha pravesh, namakarana, …) | [↓](#18-muhurta-engine) |
49
+ | **Calendar Conversion** | Gregorian↔Hindu, Kali Yuga year, Hindu New Year, yearly Ekadashi / Sankranti / festival listings | [↓](#19-calendar-conversion) |
50
+ | **Localization** | English + Hindi (Devanagari) on every returned name | [↓](#20-localization) |
51
+ | **Configuration** | 5 ayanamsas (Lahiri, Raman, KP, True Chitrapaksha, Thirukanitham), 2 masa systems, 3 house systems, 21 regional festival scopes | [↓](#21-configuration) |
52
+
53
+ ---
54
+
55
+ ## Used By
56
+
57
+ - [dharmagya.app](https://dharmagya.app) — Daily Panchang and Hindu calendar
58
+
59
+ ---
60
+
43
61
  ## Quick Start
44
62
 
45
63
  ```typescript
@@ -53,57 +71,17 @@ const result = getDailyPanchang(
53
71
  // result is `DailyPanchangResult | null` — null only at polar latitudes
54
72
  // where sunrise can't be computed. Anywhere else, narrow with `if (!result) return;`
55
73
 
56
- // Pancha Anga
57
74
  console.log(result.tithis[0].name); // "Krishna Chaturdashi"
58
75
  console.log(result.nakshatras[0].name); // "Mrigashira"
59
76
  console.log(result.vara.name); // "Mangalawara"
60
-
61
- // Lunar calendar (Purnimanta by default)
62
77
  console.log(result.chandramasa.name); // "Magha"
63
- console.log(result.chandramasa.amantaName); // "Pausha" (South Indian)
64
78
  console.log(result.samvat.vikramSamvat); // 2081
65
-
66
- // Zodiac
67
- console.log(result.chandraRashi.name); // "Mithuna" (Moon in Gemini)
68
- console.log(result.suryaNakshatra.name); // "Uttara Ashadha"
69
-
70
- // Astronomical events
71
- console.log(result.sunrise); // Date (read via getUTC*)
72
- console.log(result.moonrise); // Date | null
73
-
74
- // Muhurta & inauspicious periods
75
- console.log(result.brahmaMuhurta); // { start: Date, end: Date }
76
- console.log(result.madhyahna); // solar noon ±24 min
77
- console.log(result.rahuKalam); // { start: Date, end: Date }
78
- console.log(result.anandadiYoga.name); // "Ananda" (Vara × Nakshatra cycle)
79
- console.log(result.gandaMula.active); // false (or true with severity)
80
- console.log(result.varjyam); // { start, end } | null
81
-
82
- // Choghadiya — 8 daytime slots
83
- result.choghadiya.day.forEach(slot => {
84
- console.log(slot.name, slot.qualityName); // "Amrit", "Auspicious"
85
- });
86
-
87
- // Gowri Panchangam — 8 daytime slots
88
- result.gowriPanchangam.day.forEach(slot => {
89
- console.log(slot.name, slot.qualityName); // "Amrit", "Auspicious"
90
- });
91
-
92
- // Special Yogas active today
93
- result.specialYogas.forEach(yoga => {
94
- console.log(yoga.name, yoga.type); // "Guru Pushya Yoga", "guru_pushya"
95
- });
96
-
97
- // Festivals today
98
- result.festivals.forEach(f => {
99
- console.log(f.name, f.type); // "Makar Sankranti", "major"
100
- });
101
79
  ```
102
80
 
103
81
  ### Reading Output Times
104
82
 
105
- All `Date` objects in the result are **offset-adjusted** to the requested timezone.
106
- Always read time components via `getUTC*` methods:
83
+ All `Date` objects in the result are **offset-adjusted** to the requested timezone. Always
84
+ read time components via `getUTC*` methods — `.getHours()` would use your system zone:
107
85
 
108
86
  ```typescript
109
87
  const sunrise = result.sunrise;
@@ -111,7 +89,6 @@ const h = sunrise.getUTCHours(); // 7
111
89
  const m = sunrise.getUTCMinutes(); // 4
112
90
  // → Sunrise at 07:04 local time
113
91
 
114
- // Format helper:
115
92
  function fmt(d: Date) {
116
93
  const h = d.getUTCHours(), m = d.getUTCMinutes();
117
94
  return `${h}:${String(m).padStart(2, '0')}`;
@@ -119,477 +96,678 @@ function fmt(d: Date) {
119
96
  fmt(result.rahuKalam.start); // "09:04"
120
97
  ```
121
98
 
122
- Do **not** use `.getHours()` — it uses your system timezone, which may differ.
99
+ `moonrise` and `moonset` can be `null`the Moon occasionally does not rise or set on a
100
+ given calendar day, which is normal.
123
101
 
124
- `moonrise` and `moonset` can be `null` — the Moon occasionally does not rise or set
125
- on a given calendar day, which is normal.
102
+ ### `getDailyPanchang` vs `getInstantPanchang`
103
+
104
+ | Use case | Recommended | Why |
105
+ |----------|-------------|-----|
106
+ | "What Panchang elements are active right now?" | `getInstantPanchang` | Single-moment snapshot; no sunrise needed |
107
+ | Birth chart / muhurta picking at a specific instant | `getInstantPanchang` | Exact element at that UTC moment |
108
+ | Daily calendar / almanac row for a date | `getDailyPanchang` | Lists all element transitions for the day |
109
+ | Today's festivals & observances | `getDailyPanchang` | Full canonical-time festival refinement |
110
+ | Rahu Kalam / Choghadiya / Gowri / Hora / muhurtas | `getDailyPanchang` | Computed from sunrise, sunset, day length |
111
+ | Eclipse detection with sutak window | `getDailyPanchang` | Overlapping the day needs the day window |
112
+
113
+ `getInstantPanchang` does emit `festivals`, but evaluates rules against the elements at the
114
+ given instant only. It does not run canonical-time refinements (madhyahna / pradosha /
115
+ nishita / chandrodaya), transit-based Sankranti, Ekadashi viddha (Smarta/Vaishnava split),
116
+ or Bhadra-aware Raksha Bandhan exclusion. For reliable festival dating, use
117
+ `getDailyPanchang`.
118
+
119
+ ---
126
120
 
127
- ### Language & Masa System
121
+ # Feature Reference
122
+
123
+ Each section below shows how to access one feature category. Every feature is also
124
+ returned as a field on the unified `DailyPanchangResult` from `getDailyPanchang(…)` if you
125
+ prefer one call over the per-feature helpers.
126
+
127
+ ## 1. Pancha Anga — the Five Limbs
128
+
129
+ Tithi, Nakshatra, Yoga, Karana, Vara — with start / end times for every transition during
130
+ the Hindu day.
128
131
 
129
132
  ```typescript
130
- // Hindi names (Devanagari)
131
- const hi = getDailyPanchang(date, location, {
132
- timezone: 330,
133
- language: 'hi',
134
- });
135
- console.log(hi.tithis[0].name); // "कृष्ण चतुर्दशी"
136
- console.log(hi.vara.name); // "मंगलवार"
133
+ import { getDailyPanchang } from 'panchang-ts';
137
134
 
138
- // Amanta (South Indian) masa system
139
- const amanta = getDailyPanchang(date, location, {
140
- timezone: 330,
141
- masaSystem: 'amanta',
135
+ const r = getDailyPanchang(date, location, { timezone: 330 })!;
136
+
137
+ // Tithis active during the day (usually 1-2)
138
+ r.tithis.forEach(t => {
139
+ console.log(t.name, t.paksha, t.completionPercentage, t.endTime);
142
140
  });
143
- console.log(amanta.chandramasa.name); // Amanta month name
144
- console.log(amanta.chandramasa.system); // "amanta"
145
- ```
146
141
 
147
- ### Regional Festival Filtering
142
+ // Nakshatras (with pada)
143
+ r.nakshatras.forEach(n => console.log(n.name, n.pada, n.endTime));
148
144
 
149
- The `region` option scopes regional festival variants to one Indian state.
150
- Pan-Indian festivals (Diwali, Holi, Raksha Bandhan, the canonical
151
- `sankranti` event, …) emit regardless.
145
+ // Yogas (27-name lunisolar cycle)
146
+ r.yogas.forEach(y => console.log(y.name, y.endTime));
152
147
 
153
- ```typescript
154
- // Default every regional variant emits on Makar Sankranti day:
155
- const all = getDailyPanchang(jan14, chennai, { timezone: 330 });
156
- all.festivals.map(f => f.name);
157
- // → ["Sankranti", "Makar Sankranti", "Pongal", "Uttarayan",
158
- // "Magh Bihu", "Ayyappa Makara Jyothi"]
148
+ // Karanas (half-tithi; usually 2-4 per day)
149
+ r.karanas.forEach(k => console.log(k.name, k.type, k.endTime));
159
150
 
160
- // Scope to Tamil Nadu — drops Bihu/Ayyappa/Uttarayan:
161
- const tn = getDailyPanchang(jan14, chennai, { timezone: 330, region: 'tamil-nadu' });
162
- tn.festivals.map(f => f.name);
163
- // → ["Sankranti", "Makar Sankranti", "Pongal"]
151
+ // Vara (weekday)
152
+ console.log(r.vara.name, r.vara.englishName); // "Mangalawara", "Tuesday"
153
+ ```
164
154
 
165
- // Lohri fires on the Hindu day BEFORE Makara transit, scoped to Punjab/
166
- // Haryana/Himachal — no extra wiring required, just the region option:
167
- const lohri = getDailyPanchang(jan13, amritsar, { timezone: 330, region: 'punjab' });
168
- lohri.festivals.some(f => f.name === 'Lohri'); // true
155
+ For a single-instant snapshot use `getInstantPanchang`:
169
156
 
170
- // Pre-v2.1 region values still work but log a one-shot deprecation warning:
171
- getDailyPanchang(date, loc, { timezone: 330, region: 'tamil' });
172
- // console.warn: [panchang-ts] FestivalRegion 'tamil' is deprecated;
173
- // use 'tamil-nadu'. Legacy value will be removed in v3.
157
+ ```typescript
158
+ import { getInstantPanchang } from 'panchang-ts';
159
+
160
+ const i = getInstantPanchang(new Date(), location)!;
161
+ console.log(i.tithi.name, i.nakshatra.name, i.yoga.name, i.karana.name, i.vara.name);
174
162
  ```
175
163
 
176
- See [`FestivalRegion`](#types) for the full state-slug list (21 states + `'nepal'`).
164
+ ## 2. Lunar Calendar
177
165
 
178
- ---
166
+ Chandra Masa with **Purnimanta** (North Indian, default) and **Amanta** (South Indian)
167
+ naming, **Adhika** (leap-month) detection, **Vikram** and **Shaka** samvat year numbers.
168
+
169
+ ```typescript
170
+ const r = getDailyPanchang(date, loc, { timezone: 330, masaSystem: 'purnimanta' })!;
179
171
 
180
- ## Features
172
+ console.log(r.chandramasa.name); // "Magha" (active system)
173
+ console.log(r.chandramasa.amantaName); // "Pausha" (South Indian)
174
+ console.log(r.chandramasa.purnimantaName); // "Magha" (North Indian)
175
+ console.log(r.chandramasa.isAdhika); // false (true during leap months)
181
176
 
182
- ### Pancha Anga (5 Limbs)
183
- Tithi, Nakshatra, Yoga, Karana, Vara — with transition times throughout the day.
177
+ console.log(r.samvat.vikramSamvat); // 2081
178
+ console.log(r.samvat.shakaSamvat); // 1946
179
+ ```
184
180
 
185
- ### Lunar Calendar
186
- Chandra Masa with Adhika (leap month) detection, both **Purnimanta** (North Indian, default) and **Amanta** (South Indian) systems, Vikram Samvat, Shaka Samvat.
181
+ ## 3. Solar Calendar
187
182
 
188
- ### Muhurta & Auspicious Timing
189
- Brahma Muhurta, Abhijit Muhurta, Vijaya Muhurta (11th day-muhurta), Godhuli (sunset muhurta), Nishita (midnight muhurta, used for Shivaratri), **Madhyahna** (solar noon ±24 min ritual window), **Pratah Sandhya** / **Sayahna Sandhya** (asymmetric dawn / dusk twilight windows, width = `nightDuration / 10` — ~62–81 min depending on season, ending *at* sunrise / starting *at* sunset; matches DrikPanchang within ±2 min), classical aliases `dinamanaMinutes` / `ratrimanaMinutes`, nakshatra-keyed Amrit Kala. Choghadiya (16 slots), Gowri Panchangam / Nalla Neram (16 slots), Hora (24 planetary hours), Dur Muhurta (2 inauspicious windows), **Do Ghati Muhurta** (15 day + 15 night ~48-min slots, deity-keyed, no vara rotation), **Panchaka Rahita Muhurta** (slices of the day free of Panchaka), **Anandadi Yoga** (28-name Vara × Nakshatra cycle).
183
+ Saura Masa (solar month), Surya Nakshatra (the Sun's nakshatra, ~13–14 day transit),
184
+ Sankranti (solar-month boundary, transit-based emitted as a festival).
190
185
 
191
- ### Inauspicious Periods
192
- Rahu Kalam, Gulika Kalam, Yamaganda, Panchaka detection, Bhadra Kala (Vishti karana window with earth / heaven / paatal location), **Varjyam** (BPHS-keyed forbidden ~96-min window per nakshatra), **Ganda Mula** (Moon in the 6 root nakshatras — Ashwini / Ashlesha / Magha / Jyeshtha / Mula / Revati — with `mild` / `severe` severity).
186
+ ```typescript
187
+ const r = getDailyPanchang(date, loc, { timezone: 330 })!;
193
188
 
194
- ### Special Yogas & Festivals
195
- Amrit Siddhi, Sarvartha Siddhi, Ravi Pushya, Guru Pushya, **Dwipushkar**, **Tripushkar**, **Jwalamukhi**, **Aadal**, **Vidaal**, **Ravi** yoga detection.
189
+ console.log(r.masa.name); // "Makara" (current solar month)
190
+ console.log(r.suryaNakshatra.name); // "Uttara Ashadha"
191
+ console.log(r.chandraRashi.name); // "Mithuna" (Moon sign)
196
192
 
197
- **80+ festivals** spanning pan-Indian, regional, and classical observances:
193
+ // Sankranti and its regional variants emit through r.festivals — see §9.
194
+ ```
198
195
 
199
- - **Ekadashi** — 26 named variants (Putrada, Shat Tila, Nirjala, Devshayani, etc.) with **Smarta / Vaishnava split** via Dashami-viddha rule; Smarta fast emits a `deferralDate` for Dwadashi.
200
- - **Pradosha** — 7 weekday-qualified variants (Som Pradosh, Bhauma Pradosh, Shani Pradosh, etc.) firing on both Shukla & Krishna paksha.
201
- - **Sankranti** — transit-based solar-month boundary detection plus regional variants (**Pongal**, **Vishu**, **Baisakhi**, **Pohela Boishakh**, **Bohag Bihu**, **Magh Bihu**, **Kati Bihu**, **Uttarayan**, **Ayyappa Makara Jyothi**, **Raja Sankranti**, **Harela**, **Sair**, **Singh Sankranti**) scoped by the `region` option. **Lohri** fires on the Hindu day immediately preceding Makara Sankranti under Punjab/Haryana/Himachal scopes.
202
- - **Canonical-time classical festivals** — Ganesh Chaturthi (madhyahna), Shivaratri (nishita), Diwali, Holi, Raksha Bandhan (Bhadra-aware, suppressed when Bhadra straddles Purnima), Karva Chauth (chandrodaya), Janmashtami, Dussehra, Navaratri, Ram Navami, Hanuman Jayanti, **Akshaya Tritiya & Parashurama Jayanti** (madhyahna-vyapini, co-emitted on Vaishakha Shukla Tritiya), Makar Sankranti.
203
- - **Regional festivals (v2.1)** — **Gudi Padwa** (Maharashtra/Goa), **Gangaur** (Rajasthan), **Karaga** (Karnataka), **Bonalu** (Telangana, recurring Sundays in Ashadha), **Varamahalakshmi** (last Friday of Shravana Shukla before Purnima, Karnataka/AP/Telangana/Tamil Nadu), **Bathukamma** (Telangana — Engili Pula + Saddula markers), **Hariyali / Kajari / Hartalika Teej**, **Govardhan Puja**, **Bhai Dooj**, **Phagli** (Himachal), **Jagannath Rath Yatra** (pan-Indian, Ashadha Shukla Dwitiya), **Raja Parba** 3-day arc (Odisha — Pahili / Sankranti / Basi) — all filtered by per-state allow-lists on the rule.
204
- - **Regional & seasonal** — Chhath (4-day sequence), Vat Savitri, Upakarma (3 shakha variants via nakshatra+chandraMasa), Onam (nakshatra+solarMasa).
205
- - **Monthly observances** — Masik Shivaratri, Vinayaka Chaturthi (suppressed in Maha-month), **Masik Karthigai** (any day Krittika nakshatra prevails — sampled at sunrise / midday / sunset / nishita), Pushya days, Shravan Somvar and other month+weekday patterns.
206
- - Adhika (leap) months auto-skipped for tithi-based rules; Purnimanta naming respected.
196
+ ## 4. Sun & Moon
207
197
 
208
- ### Eclipses (Grahan)
209
- Solar & lunar eclipse detection with subtype (partial / total / annular / penumbral), magnitude at peak, observer-horizon visibility, and pre-eclipse **sutak** impurity window.
198
+ Sunrise, sunset, moonrise, moonset (Meeus apparent-upper-limb), plus Chandra Rashi
199
+ (Moon's zodiac sign).
210
200
 
211
- ### Jyotish (Vedic Astrology)
212
- All 9 graha positions (geocentric, sidereal) with rashi, nakshatra, pada, and retrograde status. Vimshottari Dasha with Antardasha and **Pratyantar** (third-level) breakdown — from a birth moment alone or from an explicit Moon longitude. Chandra Balam (transit-Moon favorability relative to janma rashi). **Tarabala** (9-tara cycle — Janma, Sampat, Vipat, Kshema, Pratyari, Sadhaka, Vadha, Mitra, Ati-Mitra — keyed off janma nakshatra; parallel to Chandra Balam). Optional `nodeType: 'true'` for Rahu/Ketu replaces the mean-node default with Meeus's dominant periodic correction (~±0.6° vs ±2° worst-case for the mean node).
201
+ ```typescript
202
+ import { getSunrise, getSunset, getMoonrise, getMoonset } from 'panchang-ts';
213
203
 
214
- ### Birth Chart (Kundli)
215
- Full natal-chart foundation built on top of the planetary engine: sidereal **Lagna** (ascendant) via Meeus eq. 13.6 (atan2 form); **Bhava** (12 houses) under three configurable house systems — `'whole-sign'` (default classical Vedic), `'equal'`, or `'placidus-kp'`; full **D1 (Rashi)** and **D9 (Navamsa)** charts placing all 9 grahas with house assignments; **Ashtakoot Guna Milan** (36-point marriage compatibility); **Mangal Dosha** (Manglik affliction with cancellations); **Sade Sati** (current Saturn-arc phase + arc start/end dates within ±2 days); **Planetary dignity** (exalted / debilitated / moolatrikona / own / friend / neutral / enemy per BPHS Ch.3-4).
204
+ const loc = { latitude: 28.6139, longitude: 77.2090 }; // New Delhi
216
205
 
217
- ### Astronomy
218
- Sunrise, Sunset, Moonrise, Moonset, Chandra Rashi (Moon sign), Surya Nakshatra. Cross-verified across diaspora locations (New York, London, Sydney, Dubai, Singapore) including DST transitions via IANA timezone strings.
206
+ const sunrise = getSunrise(localMidnightUtc, loc);
207
+ const sunset = getSunset(sunrise, loc);
219
208
 
220
- ### Localization
221
- 2 languages: **English** and **Hindi** (Devanagari). All returned display strings respect the `language` option.
209
+ // Moonrise / moonset can be null on days the Moon doesn't rise/set
210
+ const moonrise = getMoonrise(localMidnightUtc, loc);
211
+ const moonset = getMoonset(localMidnightUtc, loc);
222
212
 
223
- ### Configuration
224
- 5 ayanamsa systems (Lahiri, B.V. Raman, KP, **True Chitrapaksha**, **Thirukanitham**), 2 masa systems (Purnimanta, Amanta), 3 house systems (whole-sign, equal, Placidus-KP), adjustable precision, optional fast mode (`computeEndTimes: false` for ~5x speedup).
213
+ // Or read all of them off the daily result:
214
+ const r = getDailyPanchang(date, loc, { timezone: 330 })!;
215
+ console.log(r.sunrise, r.sunset, r.moonrise, r.moonset, r.nextSunrise);
216
+ console.log(r.dayDurationMinutes, r.nightDurationMinutes);
217
+ ```
225
218
 
226
- ---
219
+ ## 5. Auspicious Muhurta
227
220
 
228
- ## API Reference
221
+ Classical auspicious time windows: Brahma, Abhijit, Vijaya, Godhuli, Nishita, Madhyahna,
222
+ Pratah / Sayahna Sandhya, and nakshatra-keyed Amrit Kala.
229
223
 
230
- ### `getDailyPanchang(date, location, options)`
224
+ ```typescript
225
+ const r = getDailyPanchang(date, loc, { timezone: 330 })!;
226
+
227
+ r.brahmaMuhurta; // two muhurtas before sunrise
228
+ r.abhijitMuhurta; // 8th day-muhurta — universally auspicious
229
+ r.vijayaMuhurta; // 11th day-muhurta — auspicious for success
230
+ r.godhuliMuhurta; // "cow-dust" — sunset muhurta
231
+ r.nishitaMuhurta; // midnight muhurta (Shivaratri)
232
+ r.madhyahna; // solar noon ±24 min
233
+ r.pratahSandhya; // dawn twilight, ends *at* sunrise
234
+ r.sayahnaSandhya; // dusk twilight, starts *at* sunset
235
+ r.amritKala; // nakshatra-specific window (null when nakshatra has none)
236
+
237
+ // Direct helpers:
238
+ import {
239
+ computeBrahmaMuhurta, computeAbhijitMuhurta, computeVijayaMuhurta,
240
+ computeGodhuliMuhurta, computeNishitaMuhurta, computeMadhyahna,
241
+ computePratahSandhya, computeSayahnaSandhya, computeAmritKala,
242
+ } from 'panchang-ts';
243
+ ```
231
244
 
232
- Returns the full Hindu day from sunrise to next sunrise, with all element transitions.
245
+ `pratahSandhya` and `sayahnaSandhya` are asymmetric width = `nightDuration / 10`
246
+ (~62–81 min depending on season), matching DrikPanchang within ±2 min.
247
+
248
+ ## 6. Inauspicious Periods
249
+
250
+ Rahu Kalam, Gulika Kalam, Yamaganda, Dur Muhurta (2 windows), Varjyam (BPHS-keyed
251
+ ~96-min forbidden window), Ganda Mula (Moon in root nakshatras), Bhadra Kala (Vishti
252
+ karana with earth/heaven/paatal location), Panchaka.
233
253
 
234
254
  ```typescript
235
- import { getDailyPanchang } from 'panchang-ts';
255
+ const r = getDailyPanchang(date, loc, { timezone: 330 })!;
256
+
257
+ r.rahuKalam; // { start, end }
258
+ r.gulikaKalam; // { start, end }
259
+ r.yamaganda; // { start, end }
260
+ r.durMuhurta; // [TimePeriod, TimePeriod] — two ~48-min windows
261
+ r.varjyam; // { start, end } | null
262
+ r.gandaMula; // { active: boolean, severity: 'mild' | 'severe' | null, ... }
263
+ r.bhadra; // { start, end, location: 'earth'|'heaven'|'paatal', isActive } | null
264
+ r.panchaka; // boolean — Moon in last 5 nakshatras
265
+
266
+ // Direct helpers (varaIndex: 0=Sun ... 6=Sat):
267
+ import {
268
+ computeRahuKalam, computeGulikaKalam, computeYamaganda,
269
+ computeVarjyam, computeGandaMula,
270
+ } from 'panchang-ts';
236
271
 
237
- const result = getDailyPanchang(
238
- date, // Date — any moment within the local calendar day
239
- location, // GeoLocation — { latitude, longitude, elevation? }
240
- options, // PanchangOptions — { timezone, ayanamsa?, language?, ... }
241
- );
272
+ const rahu = computeRahuKalam(sunrise, sunset, varaIndex);
242
273
  ```
243
274
 
244
- **Returns: `DailyPanchangResult | null`**
245
-
246
- `null` is returned for polar locations on dates where sunrise or sunset cannot be computed (midnight sun, polar night). On every other location/date the function returns a populated result.
247
-
248
- | Field | Type | Description |
249
- |-------|------|-------------|
250
- | `date` | `Date` | Input date |
251
- | `location` | `GeoLocation` | Input location |
252
- | `timezone` | `number` | Resolved UTC offset in minutes |
253
- | `sunrise` | `Date` | Sunrise (offset-adjusted) |
254
- | `sunset` | `Date` | Sunset (offset-adjusted) |
255
- | `nextSunrise` | `Date` | Following day's sunrise (offset-adjusted) |
256
- | `dayDurationMinutes` | `number` | Length of daytime in minutes |
257
- | `nightDurationMinutes` | `number` | Length of night in minutes |
258
- | `tithis` | `DailyTithiInfo[]` | Tithis active during the day (usually 1-2) |
259
- | `nakshatras` | `DailyNakshatraInfo[]` | Nakshatras active during the day |
260
- | `yogas` | `DailyYogaInfo[]` | Yogas active during the day |
261
- | `karanas` | `DailyKaranaInfo[]` | Karanas active during the day (usually 2-4) |
262
- | `vara` | `VaraInfo` | Weekday (Vara) |
263
- | `rahuKalam` | `TimePeriod` | Rahu Kalam start/end |
264
- | `gulikaKalam` | `TimePeriod` | Gulika Kalam start/end |
265
- | `yamaganda` | `TimePeriod` | Yamaganda start/end |
266
- | `abhijitMuhurta` | `TimePeriod` | Abhijit Muhurta start/end |
267
- | `brahmaMuhurta` | `TimePeriod` | Brahma Muhurta — two muhurtas before sunrise |
268
- | `masa` | `MasaInfo` | Solar month (Saura Masa) |
269
- | `chandramasa` | `ChandraMasaInfo` | Lunar month + Adhika (leap) flag |
270
- | `samvat` | `SamvatInfo` | Vikram Samvat and Shaka Samvat year numbers |
271
- | `chandraRashi` | `RashiInfo` | Moon's zodiac sign (changes every ~2.5 days) |
272
- | `suryaNakshatra` | `RashiInfo` | Sun's nakshatra (changes every ~13-14 days) |
273
- | `choghadiya` | `ChoghadiyaInfo` | 8 day + 8 night slots, each named and rated |
274
- | `gowriPanchangam` | `GowriInfo` | 8 day + 8 night Gowri Nalla Neram slots |
275
- | `hora` | `HoraInfo` | 12 day + 12 night horas, each with ruling planet |
276
- | `moonrise` | `Date \| null` | Moonrise; `null` if none that day |
277
- | `moonset` | `Date \| null` | Moonset; `null` if none that day |
278
- | `panchaka` | `boolean` | `true` when Moon is in last 5 nakshatras |
279
- | `panchakaRahita` | `TimePeriod[]` | Slices of the Hindu day FREE of Panchaka; `[]` when Panchaka pervades the entire day |
280
- | `doGhatiMuhurta` | `DoGhatiInfo` | 15 day + 15 night ~48-min deity-keyed slots covering sunrise→sunset and sunset→nextSunrise |
281
- | `gandaMula` | `GandaMulaInfo` | Moon-in-root-nakshatra detection at sunrise; `active: false` for the 21 non-root nakshatras |
282
- | `anandadiYoga` | `AnandadiYogaInfo` | Vara × Nakshatra 28-name cycle yoga at sunrise |
283
- | `specialYogas` | `SpecialYogaInfo[]` | Auspicious yogas active today |
284
- | `durMuhurta` | `[TimePeriod, TimePeriod]` | Two inauspicious ~48-min windows |
285
- | `vijayaMuhurta` | `TimePeriod` | Vijaya Muhurta — 11th day-muhurta, auspicious for success |
286
- | `godhuliMuhurta` | `TimePeriod` | Godhuli ("cow-dust") — sunset muhurta, auspicious for ceremonies |
287
- | `nishitaMuhurta` | `TimePeriod` | Nishita — midnight muhurta, used for Shivaratri and nocturnal rites |
288
- | `madhyahna` | `TimePeriod` | Madhyahna — solar noon as a ±24-min ritual window (one classical muhurta wide) |
289
- | `pratahSandhya` | `TimePeriod` | Dawn-twilight ritual window — three nighttime ghatikas ending *at* sunrise (asymmetric; width = `nightDuration / 10` ≈ 62–81 min) |
290
- | `sayahnaSandhya` | `TimePeriod` | Dusk-twilight ritual window — three nighttime ghatikas starting *at* sunset (asymmetric; width = `nightDuration / 10`) |
291
- | `dinamanaMinutes` | `number` | Classical alias of `dayDurationMinutes` (sunrise → sunset) |
292
- | `ratrimanaMinutes` | `number` | Classical alias of `nightDurationMinutes` (sunset → next sunrise) |
293
- | `amritKala` | `TimePeriod \| null` | Amrit Kala — nakshatra-specific auspicious window (null when nakshatra has none) |
294
- | `varjyam` | `TimePeriod \| null` | Varjyam (Vishaghati / Nakshatra Thyajyam) — BPHS-keyed forbidden ~96-min window; `null` when none overlaps the Hindu day |
295
- | `bhadra` | `BhadraInfo \| null` | Bhadra Kala (Vishti karana) window overlapping this Hindu day, or `null` |
296
- | `eclipse` | `EclipseInfo \| null` | Solar/lunar eclipse overlapping this Hindu day with sutak window, or `null` |
297
- | `festivals` | `FestivalInfo[]` | Festivals / observances today (filtered by `region` option) |
298
- | `chandraBalam` | `ChandraBalamInfo?` | Transit-Moon favorability — only present when `janmaRashi` option is passed |
299
- | `tarabala` | `TarabalaInfo?` | 9-tara cycle position — only present when `janmaNakshatra` option is passed |
300
- | `ayanamsa` | `number` | Ayanamsa in degrees at sunrise |
301
- | `siderealSunAtSunrise` | `number` | Sun sidereal longitude at sunrise (degrees) |
302
- | `siderealMoonAtSunrise` | `number` | Moon sidereal longitude at sunrise (degrees) |
275
+ ## 7. Time-Slot Systems
303
276
 
304
- ---
277
+ Four parallel slot systems covering the Hindu day:
305
278
 
306
- ### `getInstantPanchang(date, location, options?)`
279
+ ```typescript
280
+ const r = getDailyPanchang(date, loc, { timezone: 330 })!;
307
281
 
308
- Returns the single Panchang element active at an exact UTC moment.
282
+ // Choghadiya 8 day + 8 night slots, each named (Amrit, Kaal, Shubh, Rog, ...) and rated
283
+ r.choghadiya.day.forEach(s => console.log(s.name, s.qualityName, s.start, s.end));
284
+ r.choghadiya.night.forEach(s => console.log(s.name, s.qualityName));
309
285
 
310
- ```typescript
311
- import { getInstantPanchang } from 'panchang-ts';
286
+ // Gowri Panchangam (Tamil "Nalla Neram") — 8 day + 8 night slots
287
+ r.gowriPanchangam.day.forEach(s => console.log(s.name, s.qualityName));
312
288
 
313
- const result = getInstantPanchang(
314
- new Date('2025-01-14T03:00:00Z'), // UTC moment
315
- { latitude: 18.5204, longitude: 73.8567 },
316
- { language: 'hi' }, // Hindi (Devanagari) names
317
- );
289
+ // Hora 12 day + 12 night planetary hours (Chaldean order)
290
+ r.hora.day.forEach(h => console.log(h.planet, h.start, h.end));
318
291
 
319
- console.log(result.tithi.name); // "कृष्ण चतुर्दशी"
320
- console.log(result.nakshatra.name); // "मृगशिरा"
321
- console.log(result.chandramasa.name); // "माघ"
322
- console.log(result.chandraRashi.name); // "मिथुन"
323
- console.log(result.samvat.vikramSamvat); // 2081
324
- console.log(result.panchaka); // false
292
+ // Do Ghati Muhurta — 15 day + 15 night ~48-min deity-keyed slots (no vara rotation)
293
+ r.doGhatiMuhurta.day.forEach(g => console.log(g.name, g.start, g.end));
294
+
295
+ // Panchaka Rahita — slices of the day FREE of Panchaka ([] when Panchaka pervades)
296
+ r.panchakaRahita.forEach(slice => console.log(slice.start, slice.end));
325
297
  ```
326
298
 
327
- **Returns: `InstantPanchangResult | null`**
328
-
329
- `null` is returned for polar locations where sunrise can't be computed (the Hindu-day weekday is undefined). On every other location/date the function returns a populated result.
330
-
331
- | Field | Type | Description |
332
- |-------|------|-------------|
333
- | `timestamp` | `Date` | Input UTC moment |
334
- | `location` | `GeoLocation` | Input location |
335
- | `tithi` | `TithiInfo` | Active Tithi with paksha, number, completion % |
336
- | `nakshatra` | `NakshatraInfo` | Active Nakshatra with pada, degrees |
337
- | `yoga` | `YogaInfo` | Active Yoga |
338
- | `karana` | `KaranaInfo` | Active Karana (movable or fixed) |
339
- | `vara` | `VaraInfo` | Active Vara (weekday) |
340
- | `chandramasa` | `ChandraMasaInfo` | Lunar month + Adhika flag |
341
- | `samvat` | `SamvatInfo` | Vikram Samvat and Shaka Samvat year numbers |
342
- | `chandraRashi` | `RashiInfo` | Moon's zodiac sign |
343
- | `suryaNakshatra` | `RashiInfo` | Sun's nakshatra |
344
- | `panchaka` | `boolean` | `true` when Moon is in last 5 nakshatras |
345
- | `gandaMula` | `GandaMulaInfo` | Moon-in-root-nakshatra detection at the queried instant |
346
- | `anandadiYoga` | `AnandadiYogaInfo` | Vara × Nakshatra 28-name cycle yoga at the queried instant |
347
- | `specialYogas` | `SpecialYogaInfo[]` | Auspicious yogas at this moment |
348
- | `festivals` | `FestivalInfo[]` | Festivals / observances at this moment (see caveat below) |
349
- | `chandraBalam` | `ChandraBalamInfo?` | Transit-Moon favorability — only present when `janmaRashi` option is passed |
350
- | `tarabala` | `TarabalaInfo?` | 9-tara cycle position — only present when `janmaNakshatra` option is passed |
351
- | `ayanamsa` | `number` | Ayanamsa in degrees |
352
- | `siderealSun` | `number` | Sun sidereal longitude (degrees) |
353
- | `siderealMoon` | `number` | Moon sidereal longitude (degrees) |
299
+ ## 8. Special Yogas
354
300
 
355
- ---
301
+ Auspicious / inauspicious yogas formed by Vara × Tithi × Nakshatra combinations and
302
+ Moon-from-Sun nakshatra-distance rules. The 28-name **Anandadi Yoga** cycle is also
303
+ returned at sunrise.
356
304
 
357
- ### When to use `getInstantPanchang` vs `getDailyPanchang`
305
+ ```typescript
306
+ const r = getDailyPanchang(date, loc, { timezone: 330 })!;
307
+
308
+ // Anandadi Yoga (Vara × Nakshatra cycle of 28 names)
309
+ console.log(r.anandadiYoga.name); // "Ananda"
310
+
311
+ // Special yogas active today
312
+ r.specialYogas.forEach(y => {
313
+ console.log(y.name, y.type);
314
+ // type: 'amrit_siddhi' | 'sarvartha_siddhi' | 'ravi_pushya' | 'guru_pushya'
315
+ // | 'dwipushkar' | 'tripushkar' ← actions doubled / tripled
316
+ // | 'jwalamukhi' ← inauspicious (Muhurta-chintamani 6.32)
317
+ // | 'aadal' | 'vidaal' | 'ravi' ← Moon-from-Sun nakshatra-distance rules
318
+ });
319
+ ```
358
320
 
359
- Both functions share the same core astronomy, but `getDailyPanchang` operates on the full Vedic day (local sunrise → next sunrise) while `getInstantPanchang` samples a single UTC moment. That distinction matters most for **festivals** and classical rules that reference a specific canonical time of the Hindu day.
321
+ ## 9. Festivals
360
322
 
361
- | Use case | Recommended | Why |
362
- |----------|-------------|-----|
363
- | "What Panchang elements are active right now?" | `getInstantPanchang` | Single-moment snapshot; no sunrise needed. |
364
- | Birth chart / muhurta picking at a specific instant | `getInstantPanchang` | Exact element at that UTC moment. |
365
- | Daily calendar / almanac row for a date | `getDailyPanchang` | Lists all element transitions for the day. |
366
- | Displaying today's festivals & observances | `getDailyPanchang` | Full canonical-time festival refinement. |
367
- | Sankranti / solar-month boundary dates | `getDailyPanchang` | Uses sunrise-to-next-sunrise transit detection. |
368
- | Ekadashi (Smarta vs Vaishnava), Shivaratri, Ganesh Chaturthi, Karva Chauth | `getDailyPanchang` | Requires madhyahna / pradosha / nishita / chandrodaya refinement. |
369
- | Raksha Bandhan date (Bhadra-aware) / long-tithi dedupe | `getDailyPanchang` | Rules key off the Hindu day window, not an instant. |
370
- | Rahu Kalam / Gulika / Choghadiya / Gowri / Hora / Durmuhurta | `getDailyPanchang` | Computed from sunrise, sunset, and day length. |
371
- | Eclipse (Grahan) detection with sutak window | `getDailyPanchang` | Overlapping the day needs the day window. |
372
-
373
- **Instant-mode festival caveat:** `getInstantPanchang` does emit `festivals`, but it evaluates rules against the tithi / nakshatra / chandraMasa at the given instant only. It **does not** run the canonical-time refinements (madhyahna / pradosha / nishita / chandrodaya), transit-based Sankranti, Ekadashi viddha (Smarta/Vaishnava split), or Bhadra-aware Raksha Bandhan exclusion — those require the full sunrise-to-next-sunrise Hindu day window and are only available in `getDailyPanchang`. If you need reliable festival dating, use `getDailyPanchang`.
323
+ **80+ festivals** spanning pan-Indian, regional, and classical observances:
374
324
 
375
- ---
325
+ - **Ekadashi** — 26 named variants (Putrada, Shat Tila, Nirjala, Devshayani, …) with
326
+ **Smarta / Vaishnava split** via Dashami-viddha rule; Smarta fast emits a `deferralDate`
327
+ for Dwadashi.
328
+ - **Pradosha** — 7 weekday-qualified variants (Som, Bhauma, Shani, …) on both pakshas.
329
+ - **Sankranti** — transit-based detection plus regional variants (Pongal, Vishu, Baisakhi,
330
+ Pohela Boishakh, Bohag / Magh / Kati Bihu, Uttarayan, Ayyappa Makara Jyothi, Raja
331
+ Sankranti, Harela, Sair, Singh Sankranti). **Lohri** fires on the Hindu day immediately
332
+ preceding Makara Sankranti under Punjab / Haryana / Himachal scopes.
333
+ - **Canonical-time classical festivals** — Ganesh Chaturthi (madhyahna), Shivaratri
334
+ (nishita), Diwali, Holi, Raksha Bandhan (Bhadra-aware), Karva Chauth (chandrodaya),
335
+ Janmashtami, Dussehra, Navaratri, Ram Navami, Hanuman Jayanti, Akshaya Tritiya &
336
+ Parashurama Jayanti (madhyahna-vyapini), Makar Sankranti.
337
+ - **Regional festivals** — Gudi Padwa, Gangaur, Karaga, Bonalu, Varamahalakshmi,
338
+ Bathukamma, Hariyali / Kajari / Hartalika Teej, Govardhan Puja, Bhai Dooj, Phagli,
339
+ Jagannath Rath Yatra, Raja Parba 3-day arc.
340
+ - **Regional & seasonal** — Chhath (4-day sequence), Vat Savitri, Upakarma, Onam.
341
+ - **Monthly observances** — Masik Shivaratri, Vinayaka Chaturthi, Masik Karthigai, Pushya
342
+ days, Shravan Somvar, and other month + weekday patterns.
376
343
 
377
- ### Options
344
+ ```typescript
345
+ const r = getDailyPanchang(date, loc, { timezone: 330 })!;
378
346
 
379
- **`PanchangOptions`** (required for `getDailyPanchang`):
347
+ r.festivals.forEach(f => {
348
+ console.log(f.name, f.type, f.deferralDate);
349
+ // type: 'major' | 'minor' | 'ekadashi'
350
+ // | 'smarta_ekadashi' | 'vaishnava_ekadashi' ← Smarta sets deferralDate
351
+ // | 'pradosha' | 'sankranti' | 'eclipse'
352
+ });
353
+ ```
380
354
 
381
- | Option | Type | Default | Description |
382
- |--------|------|---------|-------------|
383
- | `timezone` | `number \| string` | **required** | UTC offset in minutes (330 for IST) **or** IANA zone name (`'America/New_York'`). IANA strings require `Intl` — use a number on older Hermes. DST resolves automatically for IANA zones via the reference date. |
384
- | `ayanamsa` | `'lahiri' \| 'raman' \| 'krishnamurti'` | `'lahiri'` | Ayanamsa system |
385
- | `language` | `'en' \| 'hi'` | `'en'` | Language for all element names (English or Hindi Devanagari). |
386
- | `computeEndTimes` | `boolean` | `true` | Set `false` for ~5x faster, names-only output |
387
- | `precision` | `'standard' \| 'high'` | `'standard'` | Binary-search iterations (15 vs 25). High precision is rarely needed. |
388
- | `masaSystem` | `'purnimanta' \| 'amanta'` | `'purnimanta'` | Lunar month naming system. Purnimanta (North Indian) or Amanta (South Indian). |
389
- | `region` | `FestivalRegion` | `'all'` | Scopes regional festival variants (Pongal, Vishu, Gudi Padwa, Lohri, Govardhan Puja, Bonalu, …) to a specific Indian state. See [`FestivalRegion`](#types) for the full list. Pre-v2.1 values (`'tamil'`, `'bengal'`, `'north-india'`) are still accepted but emit a deprecation warning; removal in v3. Pan-Indian festivals and the canonical `sankranti` event emit regardless of this setting. |
390
- | `janmaRashi` | `number` | _(omitted)_ | Native's birth Moon rashi index (0 = Mesha … 11 = Meena). When provided, the result includes `chandraBalam`. |
391
- | `janmaNakshatra` | `number` | _(omitted)_ | Native's birth Moon nakshatra index (0 = Ashwini … 26 = Revati). When provided, the result includes `tarabala`. |
355
+ ### Regional festival scoping
392
356
 
393
- **`InstantPanchangOptions`** (optional for `getInstantPanchang`): same as above but without `timezone` (instant mode works in UTC).
357
+ The `region` option scopes regional festival variants to one Indian state. Pan-Indian
358
+ festivals (Diwali, Holi, Raksha Bandhan, the canonical `sankranti` event) emit regardless.
394
359
 
395
- ---
360
+ ```typescript
361
+ // Default — every regional variant emits on Makar Sankranti day:
362
+ const all = getDailyPanchang(jan14, chennai, { timezone: 330 })!;
363
+ all.festivals.map(f => f.name);
364
+ // → ["Sankranti", "Makar Sankranti", "Pongal", "Uttarayan",
365
+ // "Magh Bihu", "Ayyappa Makara Jyothi"]
396
366
 
397
- ### Low-level Utilities
367
+ // Scope to Tamil Nadu — drops Bihu/Ayyappa/Uttarayan:
368
+ const tn = getDailyPanchang(jan14, chennai, { timezone: 330, region: 'tamil-nadu' })!;
369
+ tn.festivals.map(f => f.name);
370
+ // → ["Sankranti", "Makar Sankranti", "Pongal"]
398
371
 
399
- Exported for advanced use cases building custom tools, visualizations, or Jyotish applications.
372
+ // Lohri fires on the Hindu day BEFORE Makara transit, scoped to Punjab/Haryana/Himachal
373
+ const lohri = getDailyPanchang(jan13, amritsar, { timezone: 330, region: 'punjab' })!;
374
+ lohri.festivals.some(f => f.name === 'Lohri'); // true
375
+ ```
400
376
 
401
- ```typescript
402
- import {
403
- getSunrise, getSunset,
404
- getMoonrise, getMoonset,
405
- getSiderealSunLongitude, getSiderealMoonLongitude,
406
- getAyanamsa,
407
- computeRahuKalam, computeGulikaKalam, computeYamaganda,
408
- computeAbhijitMuhurta, computeBrahmaMuhurta,
409
- computeVijayaMuhurta, computeGodhuliMuhurta,
410
- computeNishitaMuhurta, computeAmritKala,
411
- computeMadhyahna, computePratahSandhya, computeSayahnaSandhya,
412
- computeVarjyam, computeGandaMula,
413
- computeAnandadiYoga, computePanchakaRahita, computeDoGhati,
414
- computeGowriPanchangam,
415
- // Eclipses (signature: (fromUtc, location, withinDays))
416
- getUpcomingSolarEclipse, getUpcomingLunarEclipse, getEclipseDuringDay,
417
- // Jyotish
418
- computePlanetaryPositions,
419
- computeVimshottariDasha, computeVimshottariDashaFromBirth,
420
- computeChandraBalam,
421
- computeTarabala,
422
- GRAHA_ABBR,
423
- } from 'panchang-ts';
377
+ `FestivalRegion` covers 21 Indian states + `'nepal'` + `'all'` (default). See
378
+ [Types](#types--exports) for the full slug list.
424
379
 
425
- // Sunrise/sunset
426
- const sunrise = getSunrise(localMidnightUtc, { latitude: 28.6, longitude: 77.2 });
427
- const sunset = getSunset(sunrise, { latitude: 28.6, longitude: 77.2 });
380
+ ## 10. Eclipses
428
381
 
429
- // Moonrise/moonset return null when the Moon doesn't rise/set that day
430
- const moonrise = getMoonrise(localMidnightUtc, { latitude: 28.6, longitude: 77.2 });
431
- const moonset = getMoonset(localMidnightUtc, { latitude: 28.6, longitude: 77.2 });
382
+ Solar / lunar eclipse detection with subtype, magnitude, observer-horizon visibility, and
383
+ classical pre-eclipse **sutak** impurity window.
432
384
 
433
- // Sidereal longitudes
434
- const moonLon = getSiderealMoonLongitude(new Date(), 'lahiri'); // degrees [0, 360)
435
- const sunLon = getSiderealSunLongitude(new Date(), 'lahiri');
385
+ ```typescript
386
+ const r = getDailyPanchang(date, loc, { timezone: 330 })!;
387
+
388
+ if (r.eclipse) {
389
+ console.log(r.eclipse.kind); // 'solar' | 'lunar'
390
+ console.log(r.eclipse.subtype); // 'partial' | 'total' | 'annular' | 'penumbral'
391
+ console.log(r.eclipse.magnitude); // 0..1 fraction of disc obscured at peak
392
+ console.log(r.eclipse.visibleFromLocation); // body above horizon at peak?
393
+ console.log(r.eclipse.start, r.eclipse.peak, r.eclipse.end);
394
+ console.log(r.eclipse.sutakStart, r.eclipse.sutakEnd);
395
+ // Sutak: 12 h (4 prahara) before solar, 9 h (3 prahara) before lunar
396
+ }
397
+
398
+ // Or look ahead:
399
+ import { getUpcomingSolarEclipse, getUpcomingLunarEclipse } from 'panchang-ts';
400
+ const next = getUpcomingSolarEclipse(new Date(), loc, /* withinDays */ 365);
401
+ ```
436
402
 
437
- // Ayanamsa
438
- const ayan = getAyanamsa(new Date(), 'lahiri'); // e.g. 24.10
403
+ ## 11. Planetary Positions
439
404
 
440
- // Inauspicious periods (varaIndex: 0=Sun ... 6=Sat)
441
- const rahu = computeRahuKalam(sunrise, sunset, varaIndex); // { start, end }
442
- const gulika = computeGulikaKalam(sunrise, sunset, varaIndex);
443
- const yama = computeYamaganda(sunrise, sunset, varaIndex);
405
+ All 9 grahas (Sun Saturn + Rahu / Ketu) — geocentric, sidereal — with rashi, nakshatra,
406
+ pada, retrograde flag. Optional `nodeType: 'true'` upgrades Rahu / Ketu from mean node
407
+ (±2° worst-case) to Meeus's dominant periodic correction (~±0.6°).
444
408
 
445
- // Muhurta
446
- const abhijit = computeAbhijitMuhurta(sunrise, sunset); // { start, end }
447
- const brahma = computeBrahmaMuhurta(sunrise, sunset); // { start, end }
409
+ ```typescript
410
+ import { computePlanetaryPositions, GRAHA_ABBR } from 'panchang-ts';
411
+
412
+ const grahas = computePlanetaryPositions(new Date(), 'lahiri');
413
+ console.log(grahas.jupiter.rashi.name); // "Dhanu"
414
+ console.log(grahas.jupiter.degreeInRashi); // 18.42
415
+ console.log(grahas.jupiter.nakshatra.name); // "Purva Ashadha"
416
+ console.log(grahas.jupiter.nakshatra.pada); // 3
417
+ console.log(grahas.saturn.isRetrograde); // true / false
418
+ console.log(GRAHA_ABBR['Jupiter']); // "Ju"
419
+
420
+ // True node (more accurate Rahu / Ketu)
421
+ const grahasTrue = computePlanetaryPositions(new Date(), 'lahiri', undefined, 'true');
448
422
  ```
449
423
 
450
- **Jyotish (Vedic Astrology):**
424
+ ## 12. Vimshottari Dasha
425
+
426
+ Maha → Antar → Pratyantar (3-level) breakdown, derived from a birth moment alone or from
427
+ an explicit Moon longitude.
451
428
 
452
429
  ```typescript
453
- // All 9 graha positions (sidereal — Rahu/Ketu use mean node)
454
- const grahas = computePlanetaryPositions(birthDate, 'lahiri');
455
- console.log(grahas.jupiter.rashi.name); // "Dhanu"
456
- console.log(grahas.saturn.isRetrograde); // true/false
457
- console.log(GRAHA_ABBR['Jupiter']); // "Ju"
430
+ import {
431
+ computeVimshottariDasha, computeVimshottariDashaFromBirth,
432
+ computeVimshottariPratyantar, getSiderealMoonLongitude,
433
+ } from 'panchang-ts';
458
434
 
459
- // Vimshottari Dasha — convenience form: birth date only (Moon longitude derived)
435
+ // Convenience: from birth date alone (Moon longitude derived)
460
436
  const dasha = computeVimshottariDashaFromBirth(birthDate, 'lahiri');
461
- console.log(dasha.currentMahaDashaLord); // "Rahu"
462
- console.log(dasha.mahaDashas[0]!.antarDashas[0]!.lord); // "Rahu"
437
+ console.log(dasha.currentMahaDashaLord); // "Rahu"
438
+ console.log(dasha.mahaDashas[0]!.antarDashas[0]!.lord); // "Rahu"
463
439
 
464
- // Or pass an explicit Moon sidereal longitude (useful when you already have one)
440
+ // Or pass an explicit Moon sidereal longitude
465
441
  const moonLon = getSiderealMoonLongitude(birthDate, 'lahiri');
466
442
  const dasha2 = computeVimshottariDasha(birthDate, moonLon);
467
443
 
468
- // Chandra Balam transit Moon's favorability vs. janma rashi
469
- // janmaRashi and transitMoonRashi are 0-indexed (0 = Mesha ... 11 = Meena)
470
- const cb = computeChandraBalam(3 /* Karka */, 6 /* Tula */);
471
- console.log(cb.house); // 4
472
- console.log(cb.quality); // "weak"
473
- console.log(cb.englishName); // "Ashubha"
474
-
475
- // Tarabala — 9-tara cycle from janma nakshatra → transit Moon nakshatra.
476
- // Inputs are 0-indexed nakshatra (0 = Ashwini ... 26 = Revati).
477
- const tb = computeTarabala(0 /* janma: Ashwini */, 4 /* transit: Mrigashira */);
478
- console.log(tb.taraIndex); // 4
479
- console.log(tb.englishName); // "Pratyari"
480
- console.log(tb.quality); // "inauspicious"
444
+ // Pratyantarthird-level sub-sub-periods within an Antardasha
445
+ const firstAntar = dasha.mahaDashas[0]!.antarDashas[0]!;
446
+ const pratyantars = computeVimshottariPratyantar(firstAntar); // PratyantarDasha[9]
481
447
  ```
482
448
 
483
- ---
449
+ ## 13. Personal Transits
450
+
451
+ Daily transit-based favorability relative to the native's birth Moon. Pass `janmaRashi`
452
+ or `janmaNakshatra` to `getDailyPanchang` and the corresponding field is added to the
453
+ result; or call the helpers directly.
454
+
455
+ ```typescript
456
+ const r = getDailyPanchang(date, loc, {
457
+ timezone: 330,
458
+ janmaRashi: 3, // 0 = Mesha ... 11 = Meena
459
+ janmaNakshatra: 0, // 0 = Ashwini ... 26 = Revati
460
+ })!;
461
+
462
+ r.chandraBalam!; // { house, quality: 'strong' | 'weak', name, englishName }
463
+ r.tarabala!; // { taraIndex, name, englishName, quality }
484
464
 
485
- ### Birth Chart (Kundli) API
465
+ // Direct helpers:
466
+ import { computeChandraBalam, computeTarabala, computeSadeSati } from 'panchang-ts';
486
467
 
487
- Vedic kundli foundation. Each helper is independent calling birth-chart APIs
488
- does **not** add any work to `getDailyPanchang`.
468
+ computeChandraBalam(3 /* janma */, 6 /* transit Moon rashi */);
469
+ computeTarabala(0 /* janma nakshatra */, 4 /* transit Moon nakshatra */);
470
+
471
+ // Sade Sati — Saturn currently transiting 12th, 1st, or 2nd from natal Moon
472
+ const sadeSati = computeSadeSati(natalMoonRashiIndex, new Date());
473
+ // → { active, phase: 1|2|3|null, currentArcStart, currentArcEnd, nextArcStart }
474
+ ```
475
+
476
+ ## 14. Birth Chart (Kundli)
477
+
478
+ Sidereal **Lagna**, **Bhava** under three house systems, **D1 (Rashi)** + six classical
479
+ divisional charts (**D2 Hora**, **D3 Drekkana**, **D7 Saptamsa**, **D9 Navamsa**, **D10
480
+ Dasamsa**, **D12 Dwadasamsa**, **D30 Trimsamsa**) placing all 9 grahas, and **Planetary
481
+ Dignity**.
489
482
 
490
483
  ```typescript
491
484
  import {
492
- computeLagna, computeBhava,
493
- computeRashiChart, computeNavamsa,
494
- computeAshtakoot, computeMangalDosha, computeSadeSati,
495
- computeDignity, computeVimshottariPratyantar,
496
- computeVimshottariDashaFromBirth,
485
+ computeLagna, computeBhava, computeRashiChart, computeNavamsa,
486
+ computeDivisionalChart, computeDignity,
497
487
  } from 'panchang-ts';
498
488
 
499
- const birth = new Date('1995-08-15T05:30:00Z'); // 11:00 IST
500
- const loc = { latitude: 28.6139, longitude: 77.2090 }; // New Delhi
489
+ const birth = new Date('1995-08-15T05:30:00Z');
490
+ const loc = { latitude: 28.6139, longitude: 77.2090 };
501
491
 
502
492
  // 1. Lagna (sidereal ascendant)
503
493
  const lagna = computeLagna(birth, loc, 'lahiri', 'en');
504
- // → { siderealLongitude, rashi: { index, name }, degreeInRashi,
505
- // nakshatra: { index, name }, pada }
494
+ // → { siderealLongitude, rashi, degreeInRashi, nakshatra, pada }
506
495
 
507
- // 2. Bhava (12 houses) under any of three systems
508
- const houses = computeBhava(birth, loc, { houseSystem: 'whole-sign' });
509
- // → { system, houses: HouseInfo[12], ascendantLongitude, mcLongitude }
510
- // - 'whole-sign' (default) — each rashi is one house, cusps at 0°
496
+ // 2. Bhava (12 houses)
497
+ // - 'whole-sign' (default classical Vedic) each rashi is one house
511
498
  // - 'equal' — each house spans 30° starting at lagna's exact degree
512
- // - 'placidus-kp' — true cuspal positions; throws PanchangError('CIRCUMPOLAR')
513
- // above ~|66.5°| latitude
499
+ // - 'placidus-kp' — true cuspal positions; throws PanchangError('CIRCUMPOLAR') > ±66.5°
500
+ const houses = computeBhava(birth, loc, { houseSystem: 'whole-sign' });
514
501
 
515
502
  // 3. D1 (Rashi) chart — lagna + bhava + 9 grahas with house placement
516
503
  const d1 = computeRashiChart(birth, loc, { houseSystem: 'whole-sign' });
517
- // → { divisional: 'D1', lagna, bhava, planets: PlanetPlacement[9] }
518
- d1.planets.find((p) => p.planet === 'Jupiter')?.house; // e.g. 5
519
- d1.planets.find((p) => p.planet === 'Saturn')?.isRetrograde;
504
+ d1.planets.find(p => p.planet === 'Jupiter')?.house; // e.g. 5
505
+ d1.planets.find(p => p.planet === 'Saturn')?.isRetrograde;
520
506
 
521
507
  // 4. D9 (Navamsa) chart — classical sign-based per-rashi-type rule
522
508
  const d9 = computeNavamsa(birth, loc);
523
- // → { divisional: 'D9', lagnaRashi, planets: PlanetPlacement[9] }
524
509
 
525
- // 5. Ashtakoot Guna Milan 36-point marriage compatibility from natal Moons
526
- const ashtakoot = computeAshtakoot(
510
+ // 5. Divisional charts (D2/D3/D7/D10/D12/D30) via the unified API
511
+ const d10 = computeDivisionalChart(birth, loc, 'D10'); // career
512
+ const d30 = computeDivisionalChart(birth, loc, 'D30'); // misfortune
513
+ // → { divisional: 'D10', lagnaRashi, planets[] }
514
+
515
+ // 6. Planetary dignity (BPHS Ch.3-4)
516
+ computeDignity('Mars', 0); // 'moolatrikona' (Aries)
517
+ computeDignity('Mars', 9); // 'exalted' (Capricorn)
518
+ computeDignity('Sun', 6); // 'debilitated' (Libra)
519
+ ```
520
+
521
+ The seven divisional kinds are: **D2 Hora** (wealth), **D3 Drekkana** (siblings),
522
+ **D7 Saptamsa** (children), **D9 Navamsa** (partner / dharma), **D10 Dasamsa** (career),
523
+ **D12 Dwadasamsa** (parents), **D30 Trimsamsa** (misfortune). Each follows its classical
524
+ per-rashi-type mapping per BPHS Ch. 6; D30 uses the non-uniform 5-segment split with
525
+ Mars / Saturn / Jupiter / Mercury / Venus rulership (no Sun / Moon segments).
526
+
527
+ Birth-chart helpers accept the full ayanamsa set including `'true-chitra'` (True
528
+ Chitrapaksha) and `'thirukanitham'` (Tamil-Vakya). Pass via `options.ayanamsa` or the
529
+ ayanamsa positional arg.
530
+
531
+ ## 15. Compatibility & Doshas
532
+
533
+ **Ashtakoot Guna Milan** (36-point marriage compatibility), **Mangal Dosha** (Manglik
534
+ with cancellations), **Kaal Sarp Dosha** (12 named subtypes by Rahu's house), and
535
+ **Pitru Dosha** (ancestral affliction triggers).
536
+
537
+ ```typescript
538
+ import {
539
+ computeAshtakoot, computeMangalDosha,
540
+ computeKaalSarp, computePitruDosha,
541
+ } from 'panchang-ts';
542
+
543
+ // Ashtakoot — from natal Moons
544
+ const match = computeAshtakoot(
527
545
  { rashi: 4, nakshatra: 9 }, // boy: Simha / Magha
528
546
  { rashi: 0, nakshatra: 1 }, // girl: Mesha / Bharani
529
547
  );
530
- // → { totalScore: 0..36, koots: KootScore[8], cancellations: string[] }
531
- // koots in canonical order: Varna, Vashya, Tara, Yoni, Graha Maitri, Gana,
532
- // Bhakoot, Nadi (max scores 1, 2, 3, 4, 5, 6, 7, 8 respectively)
548
+ // → { totalScore: 0..36, koots: KootScore[8], cancellations: string[] }
549
+ // Koots in canonical order: Varna, Vashya, Tara, Yoni, Graha Maitri, Gana, Bhakoot, Nadi
550
+ // (max scores 1, 2, 3, 4, 5, 6, 7, 8 respectively)
533
551
 
534
- // 6. Mangal Dosha (Manglik) — checks Mars from lagna, Moon, and Venus
552
+ // Mangal Dosha — checks Mars from lagna, Moon, and Venus
535
553
  const mangal = computeMangalDosha(d1);
536
- // → { afflicted: boolean,
537
- // fromLagna: { afflicted, house }, fromMoon: ..., fromVenus: ...,
538
- // cancellations: string[] }
554
+ // → { afflicted, fromLagna, fromMoon, fromVenus, cancellations }
539
555
 
540
- // 7. Sade SatiSaturn currently transiting 12th, 1st, or 2nd from natal Moon
541
- const sadeSati = computeSadeSati(d1.planets[1]!.rashi.index, new Date());
542
- // → { active, phase: 1|2|3|null, currentArcStart, currentArcEnd, nextArcStart }
556
+ // Kaal Sarp Doshaall 7 visible planets between Rahu and Ketu axis
557
+ const ksd = computeKaalSarp(d1);
558
+ // → { afflicted, subtype, partial, rahuHouse, ketuHouse }
559
+ // subtype is one of: anant, kulik, vasuki, shankhpal, padma, mahapadma,
560
+ // takshak, karkotak, shankhachud, ghatak, vishdhar, sheshnag — by Rahu's house.
543
561
 
544
- // 8. Planetary dignity (BPHS Ch.3-4)
545
- computeDignity('Mars', 0); // 'moolatrikona' (Aries)
546
- computeDignity('Mars', 9); // 'exalted' (Capricorn)
547
- computeDignity('Sun', 6); // 'debilitated' (Libra)
548
- computeDignity('Saturn', 10); // 'moolatrikona' (Aquarius)
562
+ // Pitru Dosha Sun + Rahu/Ketu in same house, OR Sun + Saturn in 9th
563
+ const pitru = computePitruDosha(d1);
564
+ // { afflicted, reasons: string[] }
565
+ ```
566
+
567
+ **Documented limitations** — Mangal Dosha cancellations only cover Mars in own sign
568
+ (Aries / Scorpio) or exalted (Capricorn); other classical cancellations (mutual Mangalik,
569
+ Mars-Jupiter aspect, Mars-Saturn conjunction) are not applied. Ashtakoot Vashya koot is
570
+ simplified to single-vashya per rashi. Pitru Dosha surfaces the two highest-frequency
571
+ classical triggers (Sun + node, Sun + Saturn in 9th); the full BPHS catalog of triggers
572
+ (debilitated 9th lord, 9th lord in dusthana, etc.) is out of scope.
549
573
 
550
- // 9. Pratyantar (3rd-level) Vimshottari sub-sub-periods
551
- const dasha = computeVimshottariDashaFromBirth(birth);
552
- const firstAntar = dasha.mahaDashas[0]!.antarDashas[0]!;
553
- const pratyantars = computeVimshottariPratyantar(firstAntar);
554
- // → PratyantarDasha[9] — 9 sub-sub-periods covering the antardasha proportionally
574
+ ## 16. Aspects & Strength
575
+
576
+ **Drishti** (planetary aspects per BPHS Ch. 26) and **Shadbala** (six-fold strength per
577
+ BPHS Ch. 27).
578
+
579
+ ```typescript
580
+ import { computeAspects, computeShadbala } from 'panchang-ts';
581
+
582
+ // Aspects — every graha aspects the 7th house from itself; malefics gain
583
+ // extra special aspects (Mars 4 + 8, Jupiter 5 + 9, Saturn 3 + 10).
584
+ const aspects = computeAspects(d1);
585
+ // → { Sun: [houses…], Moon: [...], …, Saturn: [...], Rahu: [...], Ketu: [...] }
586
+ //
587
+ // Default treats Rahu/Ketu with the 7th-only BPHS-literal rule. Pass
588
+ // { nodeAspects: '5-and-9' } to extend nodes with Jupiter-like 5/9 aspects
589
+ // (BV Raman / KP convention).
590
+
591
+ // Shadbala — 7 visible grahas, 6 components per planet, in Virupas (60 V = 1 Rupa).
592
+ const bala = computeShadbala(birth, loc);
593
+ // → { Sun: { sthana, dig, kala, chesta, naisargika, drik, total }, Moon: …, … }
594
+ //
595
+ // Components implemented at the simplified-model level used by ProKerala /
596
+ // PyJHora — Uchcha-only Sthana, Dig from directional cusp, Nathonatha + Paksha
597
+ // for Kala, retrograde-bucket Chesta, fixed Naisargika rank, weighted Drik.
555
598
  ```
556
599
 
557
- **Ayanamsa options**any birth-chart helper accepts the new
558
- `'true-chitra'` (True Chitrapaksha Spica-anchored) or `'thirukanitham'`
559
- (South Indian Tamil-Vakya tradition) ayanamsas in addition to the original
560
- `'lahiri'`, `'raman'`, `'krishnamurti'`. Pass via the `options.ayanamsa`
561
- field on `BirthChartOptions`.
562
-
563
- **True Rahu/Ketu node** — `computePlanetaryPositions(date, ayanamsa, …, 'true')`
564
- or `options.nodeType: 'true'` on the chart helpers replaces the mean-node
565
- default with Meeus's dominant periodic correction (`-1.4979°·sin(2D-2F)`).
566
- Typical accuracy improves from ±0.5° (worst ±2°) on the mean node to
567
- ±0.6° on the true node.
568
-
569
- **Documented limitations:**
570
-
571
- - **Mangal Dosha cancellations**: only Mars in own sign (Aries/Scorpio) or
572
- exalted (Capricorn). Other classical cancellations — mutual Mangalik,
573
- Mars-Jupiter aspect, Mars-Saturn conjunction are not applied.
574
- - **Sade Sati boundary precision**: ±1-2 days. Saturn retrograde re-crossings
575
- of a rashi boundary within a 90-day window are absorbed; longer dips are
576
- treated as boundary events. Both first-touch and permanent-ingress
577
- conventions are within tolerance.
578
- - **Placidus-KP**: throws `PanchangError('CIRCUMPOLAR')` at high latitudes
579
- where the cusp's semi-diurnal arc doesn't exist. Use `'whole-sign'` or
580
- `'equal'` north of the Arctic Circle / south of the Antarctic Circle.
581
- - **Navamsa (D9)**: longitude is scaled (3°20' source arc 30° D9 arc) so
582
- `degreeInRashi` is meaningful within the navamsa rashi. Houses are
583
- whole-sign relative to the navamsa lagna (the classical Vedic convention).
584
- - **Ashtakoot Vashya koot**: simplified single-vashya per rashi (half-sign
585
- nuance — e.g. Sagittarius's centaur first half is collapsed).
586
- - **True node**: only the dominant Meeus Ch.47 perturbation term is applied.
587
- Higher-order (sub-arcminute) corrections are omitted; for KP-style
588
- sub-arcminute work, use a dedicated KP node calculator.
600
+ Both functions return additive surface they do **not** modify the
601
+ `getDailyPanchang` / birth-chart pipelines. Call them on demand.
602
+
603
+ ## 17. Dasha Systems
604
+
605
+ Four classical dasha systems are exposed:
606
+
607
+ ```typescript
608
+ import {
609
+ computeVimshottariDashaFromBirth, computeVimshottariPratyantar,
610
+ computeAshtottariDasha, computeYoginiDasha, computeCharaDasha,
611
+ } from 'panchang-ts';
612
+
613
+ const birth = new Date('1995-08-15T05:30:00Z');
614
+ const loc = { latitude: 28.6139, longitude: 77.2090 };
615
+
616
+ // 1. Vimshottari (120-year, 9-lord)already in v1; pratyantar (3-level) added in v3
617
+ const vim = computeVimshottariDashaFromBirth(birth);
618
+ const pratyantars = computeVimshottariPratyantar(vim.mahaDashas[0].antarDashas[0]);
619
+
620
+ // 2. Ashtottari (108-year, 8-lord, no Ketu) — used when Moon in Krishna Paksha
621
+ const moonLon = /* sidereal Moon longitude */ 145.7;
622
+ const ash = computeAshtottariDasha(birth, moonLon);
623
+ // → mahaDashas[0..7], lord cycle Sun(6)→Moon(15)→Mars(8)→Mercury(17)→
624
+ // Saturn(10)→Jupiter(19)Rahu(12)→Venus(21)
625
+
626
+ // 3. Yogini (36-year, 8 yoginis with planetary lords)
627
+ const yog = computeYoginiDasha(birth, moonLon);
628
+ yog.mahaDashas[0].yogini; // 'Dhanya' (Magha nakshatra 10, 10 % 8 = 2)
629
+ yog.mahaDashas[0].lord; // 'Jupiter' (Dhanya's planet)
630
+
631
+ // 4. Chara (Jaimini, sign-based, 9-8-7 years per modality)
632
+ const cha = computeCharaDasha(birth, loc);
633
+ cha.mahaDashas[0].rashi; // lagna's rashi
634
+ cha.mahaDashas[0].lord; // sign-lord planet
635
+ cha.mahaDashas[0].years; // 9 (movable) | 8 (fixed) | 7 (dual)
636
+ ```
637
+
638
+ **Sourcing:** Vimshottari per Parashara (BPHS Ch. 51); Ashtottari per Satya Acharya;
639
+ Yogini per Sanjay Rath (1999) / Charak; Chara per Jaimini Sutras Ch. 1 (9-8-7 years
640
+ variant). Documented limitations: Chara uses the forward zodiacal direction
641
+ unconditionally (Sundar / Achyutananda variant); the reverse-direction rule for
642
+ even-rashi lagnas is not currently exposed.
643
+
644
+ ## 18. Muhurta Engine
645
+
646
+ A configurable rule + scoring engine for picking auspicious dates. Ships with **13 stock
647
+ rules** (vivah, griha pravesh, namakarana, vidyarambh, vahan kharidi, annaprashan,
648
+ mundan, upanayanam, karnavedha, aksharabhyasam, seemantham, shop opening, travel
649
+ start). Each rule is a pure data declaration — write your own without touching the
650
+ engine.
651
+
652
+ ```typescript
653
+ import { scoreMuhurta, findAuspiciousDates, vivahRule } from 'panchang-ts';
654
+
655
+ // Score a single date
656
+ const r = scoreMuhurta(new Date('2026-05-12'), DELHI, vivahRule, { timezone: 330 });
657
+ // → { date, score: 0..100, passes: boolean, reasons: string[] }
658
+
659
+ // Find all auspicious dates in a range, sorted by score descending
660
+ const dates = findAuspiciousDates(
661
+ vivahRule,
662
+ new Date('2026-05-01'),
663
+ new Date('2026-05-31'),
664
+ DELHI,
665
+ { timezone: 330 },
666
+ );
667
+ // → MuhurtaDay[] with full panchang attached for each result
668
+
669
+ // Custom rule
670
+ const myRule: MuhurtaRule = {
671
+ occasion: 'launch_party',
672
+ auspiciousVaras: [3, 4, 5], // Wed/Thu/Fri
673
+ auspiciousNakshatras: [11, 12, 21], // Uttara Phalguni / Hasta / Shravana
674
+ excludeBhadra: true,
675
+ excludeEkadashi: true,
676
+ excludeAdhikaMasa: true,
677
+ };
678
+ ```
679
+
680
+ Scoring model: starts at 50 (neutral), +10 per matching auspicious axis (tithi,
681
+ nakshatra, vara, yoga), -15 per matching inauspicious axis, hard exclusions
682
+ (`excludeBhadra` / `excludeEkadashi` / `excludeEclipse` / `excludeAdhikaMasa` /
683
+ `excludeGandaMula` / `excludePanchaka` / `requirePaksha` mismatch) zero the score.
684
+ Special yogas — Amrit Siddhi, Sarvartha Siddhi, Ravi Pushya, Guru Pushya — add +5;
685
+ Jwalamukhi yoga subtracts -10. Final score clamped to 0..100; `passes: true` when
686
+ score ≥ 50.
687
+
688
+ ## 19. Calendar Conversion
689
+
690
+ Gregorian↔Hindu lunar coordinates, Kali Yuga year, regional Hindu New Year, and
691
+ yearly listings of Ekadashis / Sankrantis / festivals / eclipses.
692
+
693
+ ```typescript
694
+ import {
695
+ convertGregorianToHindu, convertHinduToGregorian,
696
+ getKaliYugaYear, getHinduNewYear,
697
+ getEkadashiDatesForYear, getSankrantisForYear,
698
+ getFestivalsInRange, getUpcomingEclipses,
699
+ } from 'panchang-ts';
700
+
701
+ // Gregorian → Hindu coordinates at sunrise
702
+ const h = convertGregorianToHindu(new Date('2026-04-15'), DELHI, { timezone: 330 });
703
+ // → { tithiName, tithi (1..30), pakshaTithi (1..15), paksha,
704
+ // masaName, masaIndex, isAdhika, vikramSamvat, shakaSamvat,
705
+ // varaName, varaIndex }
706
+
707
+ // Hindu → Gregorian: which Gregorian dates correspond to a (samvat, masa, paksha, tithi)?
708
+ const dates = convertHinduToGregorian(
709
+ { vikramSamvat: 2083, masaIndex: 0, paksha: 'shukla', pakshaTithi: 9 },
710
+ DELHI, { timezone: 330 },
711
+ );
712
+ // dates[0] → Rama Navami in VS 2083
713
+
714
+ getKaliYugaYear(new Date('2026-04-01')); // 5127
715
+ getHinduNewYear(2026, 'tamil-nadu', DELHI, { timezone: 330 }); // Puthandu
716
+
717
+ // Yearly listings
718
+ getEkadashiDatesForYear(2026, DELHI, { timezone: 330 }); // ~24 Date[]
719
+ getSankrantisForYear(2026, DELHI, { timezone: 330 }); // 12 SankrantiEvent[]
720
+ getFestivalsInRange(start, end, DELHI, { timezone: 330 }); // FestivalDay[]
721
+ getUpcomingEclipses(new Date(), DELHI, 5); // 5 EclipseInfo[]
722
+ ```
723
+
724
+ `getHinduNewYear` is region-aware: Tamil Nadu / Kerala / Punjab / Bengal / Assam use
725
+ the **solar** (Mesha Sankranti) anchor; everywhere else uses **Chaitra Shukla Pratipada**
726
+ (Ugadi / Gudi Padwa / Cheti Chand). When the Pratipada is a kshaya tithi (e.g. Ugadi
727
+ 2026), the function falls back to the Amanta-Chaitra-masa boundary.
728
+
729
+ ## 20. Localization
730
+
731
+ All returned display names respect the `language` option. **English** and **Hindi
732
+ (Devanagari)** are supported.
733
+
734
+ ```typescript
735
+ const hi = getDailyPanchang(date, loc, { timezone: 330, language: 'hi' })!;
736
+
737
+ console.log(hi.tithis[0].name); // "कृष्ण चतुर्दशी"
738
+ console.log(hi.vara.name); // "मंगलवार"
739
+ console.log(hi.chandramasa.name); // "माघ"
740
+ console.log(hi.choghadiya.day[0].name); // "अमृत"
741
+
742
+ // englishName is always English on Vara / Tarabala / Chandra Balam
743
+ console.log(hi.vara.englishName); // "Tuesday"
744
+ ```
745
+
746
+ ## 21. Configuration
747
+
748
+ ```typescript
749
+ const r = getDailyPanchang(date, loc, {
750
+ timezone: 330, // number (UTC offset in min) or IANA string
751
+ ayanamsa: 'lahiri', // 'lahiri' | 'raman' | 'krishnamurti'
752
+ // | 'true-chitra' | 'thirukanitham'
753
+ language: 'en', // 'en' | 'hi'
754
+ masaSystem: 'purnimanta', // 'purnimanta' | 'amanta'
755
+ region: 'all', // 21 state slugs + 'nepal' + 'all'
756
+ computeEndTimes: true, // false → ~5x speedup, names only
757
+ precision: 'standard', // 'standard' (15 iter) | 'high' (25 iter)
758
+ janmaRashi: undefined, // pass to add r.chandraBalam
759
+ janmaNakshatra: undefined, // pass to add r.tarabala
760
+ });
761
+ ```
762
+
763
+ **Timezone handling** — `timezone` accepts either a number (UTC offset in minutes, e.g.
764
+ `330` for IST) or an IANA zone name (e.g. `'America/New_York'`). IANA strings need `Intl`,
765
+ which older Hermes versions don't fully support — pass a number on those targets. DST
766
+ resolves automatically for IANA zones via the reference date.
589
767
 
590
768
  ---
591
769
 
592
- ## Types
770
+ ## Types & Exports
593
771
 
594
772
  <details>
595
773
  <summary><strong>Core Types</strong> — GeoLocation, TimePeriod</summary>
@@ -615,7 +793,7 @@ interface TimePeriod {
615
793
  interface TithiInfo {
616
794
  index: number; // 0-29
617
795
  name: string; // e.g. "Shukla Pratipada"
618
- paksha: string; // "Shukla"/"Krishna" (en), "शुक्ल"/"कृष्ण" (sa/hi)
796
+ paksha: string; // "Shukla"/"Krishna" (en), "शुक्ल"/"कृष्ण" (hi)
619
797
  number: number; // 1-15 within the paksha
620
798
  completionPercentage: number;
621
799
  endTime: Date | null;
@@ -632,10 +810,10 @@ interface NakshatraInfo {
632
810
 
633
811
  interface DailyTithiInfo extends TithiInfo {
634
812
  startTime: Date | null; // null when isActiveAtSunrise is true
635
- isActiveAtSunrise: boolean; // true = present at sunrise; false = started mid-day
813
+ isActiveAtSunrise: boolean;
636
814
  }
637
815
 
638
- // DailyNakshatraInfo, DailyYogaInfo, DailyKaranaInfo follow the same pattern
816
+ // DailyNakshatraInfo, DailyYogaInfo, DailyKaranaInfo follow the same pattern.
639
817
 
640
818
  interface VaraInfo {
641
819
  index: number; // 0 = Sunday ... 6 = Saturday
@@ -652,12 +830,12 @@ interface KaranaInfo {
652
830
  type: 'fixed' | 'movable';
653
831
  }
654
832
 
655
- // Note: endTime and startTime are null when computeEndTimes: false.
833
+ // endTime / startTime are null when computeEndTimes: false.
656
834
  ```
657
835
  </details>
658
836
 
659
837
  <details>
660
- <summary><strong>Lunar Calendar</strong> — ChandraMasaInfo, SamvatInfo, MasaInfo</summary>
838
+ <summary><strong>Lunar Calendar</strong> — ChandraMasaInfo, SamvatInfo, MasaInfo, RashiInfo</summary>
661
839
 
662
840
  ```typescript
663
841
  interface ChandraMasaInfo {
@@ -665,10 +843,10 @@ interface ChandraMasaInfo {
665
843
  name: string; // follows masaSystem option
666
844
  isAdhika: boolean; // true = leap/intercalary month
667
845
  system: 'purnimanta' | 'amanta';
668
- amantaIndex: number; // month index in Amanta system
669
- amantaName: string; // month name in Amanta system
670
- purnimantaIndex: number; // month index in Purnimanta system
671
- purnimantaName: string; // month name in Purnimanta system
846
+ amantaIndex: number;
847
+ amantaName: string;
848
+ purnimantaIndex: number;
849
+ purnimantaName: string;
672
850
  }
673
851
 
674
852
  interface SamvatInfo {
@@ -689,7 +867,7 @@ interface RashiInfo {
689
867
  </details>
690
868
 
691
869
  <details>
692
- <summary><strong>Time Slots</strong> — Choghadiya, Gowri Panchangam, Hora</summary>
870
+ <summary><strong>Time Slots</strong> — Choghadiya, Gowri, Hora, Do Ghati</summary>
693
871
 
694
872
  ```typescript
695
873
  type ChoghadiyaQuality = 'auspicious' | 'inauspicious' | 'neutral';
@@ -698,34 +876,29 @@ interface ChoghadiyaSlot extends TimePeriod {
698
876
  index: number;
699
877
  name: string; // e.g. "Amrit", "Kaal" (localized)
700
878
  quality: ChoghadiyaQuality;
701
- qualityName: string; // localized: "Auspicious", "शुभ", "शुभम्"
879
+ qualityName: string; // localized: "Auspicious", "शुभ"
702
880
  }
703
881
 
704
882
  interface ChoghadiyaInfo {
705
- day: ChoghadiyaSlot[]; // 8 slots (sunrise -> sunset)
706
- night: ChoghadiyaSlot[]; // 8 slots (sunset -> next sunrise)
707
- }
708
-
709
- interface GowriSlot extends TimePeriod {
710
- index: number; // 0-7 within the 8-name cycle
711
- name: string; // e.g. "Amrit", "Kaal" (localized)
712
- quality: ChoghadiyaQuality;
713
- qualityName: string;
883
+ day: ChoghadiyaSlot[]; // 8 slots (sunrise -> sunset)
884
+ night: ChoghadiyaSlot[]; // 8 slots (sunset -> next sunrise)
714
885
  }
715
886
 
716
- interface GowriInfo {
717
- day: GowriSlot[]; // 8 slots (sunrise -> sunset)
718
- night: GowriSlot[]; // 8 slots (sunset -> next sunrise)
719
- }
887
+ // GowriSlot / GowriInfo mirror Choghadiya.
720
888
 
721
889
  interface HoraSlot extends TimePeriod {
722
- planet: string; // e.g. "Sun", "Venus", "Mercury"
890
+ planet: string; // "Sun", "Venus", "Mercury", ...
723
891
  planetIndex: number; // 0-6 in Chaldean order
724
892
  }
725
893
 
726
894
  interface HoraInfo {
727
- day: HoraSlot[]; // 12 slots (sunrise -> sunset)
728
- night: HoraSlot[]; // 12 slots (sunset -> next sunrise)
895
+ day: HoraSlot[]; // 12 slots (sunrise -> sunset)
896
+ night: HoraSlot[]; // 12 slots (sunset -> next sunrise)
897
+ }
898
+
899
+ interface DoGhatiInfo {
900
+ day: DoGhatiSlot[]; // 15 ~48-min deity-keyed slots
901
+ night: DoGhatiSlot[]; // 15 ~48-min deity-keyed slots
729
902
  }
730
903
  ```
731
904
  </details>
@@ -735,37 +908,28 @@ interface HoraInfo {
735
908
 
736
909
  ```typescript
737
910
  interface SpecialYogaInfo {
738
- name: string; // e.g. "Guru Pushya Yoga", "Dwipushkar Yoga"
911
+ name: string;
739
912
  type:
740
913
  | 'amrit_siddhi' | 'sarvartha_siddhi' | 'ravi_pushya' | 'guru_pushya'
741
- // Vara × Tithi × Nakshatra patterns + Moon-from-Sun distance yogas
742
- | 'dwipushkar' // Bhadra-tithi + Bhadra-vara + nakshatra ∈ {Mrigashira, Chitra, Dhanishtha} — actions doubled
743
- | 'tripushkar' // same Bhadra-tithi/vara + nakshatra {Krittika, Punarvasu, U.Phalguni, Vishakha, U.Ashadha, P.Bhadrapada} — actions tripled
744
- | 'jwalamukhi' // inauspicioustithi × nakshatra lookup per Muhurta-chintamani 6.32
745
- | 'aadal' // auspicious — Moon-from-Sun nakshatra-distance (28-scheme) ∈ {2,7,9,14,16,21,23,28}
746
- | 'vidaal' // inauspicious — Moon-from-Sun nakshatra-distance (28-scheme) ∈ {3,6,10,13,17,20,24,27}
747
- | 'ravi'; // auspicious — Moon-from-Sun nakshatra-distance (27-scheme) ∈ {4,6,9,10,13,20}
914
+ | 'dwipushkar' // Bhadra-tithi + vara + nakshatra {Mrig, Chitra, Dhan} — doubled
915
+ | 'tripushkar' // same Bhadra rules + nakshatra ∈ {Krit, Punar, U.Phal, Vish, U.Ash, P.Bhad} — tripled
916
+ | 'jwalamukhi' // inauspicious tithi × nakshatra (Muhurta-chintamani 6.32)
917
+ | 'aadal' // auspiciousMoon-from-Sun nakshatra distance
918
+ | 'vidaal' // inauspicious — Moon-from-Sun nakshatra distance
919
+ | 'ravi'; // auspicious — Moon-from-Sun nakshatra distance (27-scheme)
748
920
  }
749
921
 
750
922
  interface FestivalInfo {
751
- name: string; // e.g. "Diwali", "Putrada Ekadashi", "Som Pradosh"
923
+ name: string;
752
924
  type:
753
- | 'major' // Diwali, Holi, Raksha Bandhan, Navaratri, Sankranti variants ...
754
- | 'minor' // Masik Shivaratri, Vinayaka Chaturthi, Pushya days, Shravan Somvar ...
755
- | 'ekadashi' // Generic Ekadashi (when Smarta/Vaishnava split doesn't apply)
756
- | 'smarta_ekadashi' // Smarta fast day; emits `deferralDate` when Dashami-viddha
757
- | 'vaishnava_ekadashi' // Vaishnava fast day (observed on following day if Smarta defers)
758
- | 'pradosha' // Weekday-qualified Pradosha (Som / Bhauma / Shani / etc.)
759
- | 'sankranti' // Solar-month boundary (pan-Indian + regional variants)
760
- | 'eclipse'; // Solar or lunar Grahan
925
+ | 'major' | 'minor'
926
+ | 'ekadashi' | 'smarta_ekadashi' | 'vaishnava_ekadashi'
927
+ | 'pradosha' | 'sankranti' | 'eclipse';
761
928
  description?: string;
762
929
  /** Smarta-only: when Ekadashi is Dashami-viddha, the Dwadashi fast date. */
763
930
  deferralDate?: Date;
764
931
  }
765
932
 
766
- // State-slug scheme. A caller sets `region` to limit regional variants to
767
- // their state; pan-Indian festivals (Holi, Diwali, Sankranti itself, …)
768
- // emit regardless.
769
933
  type FestivalRegion =
770
934
  | 'all' // default — emits every regional variant
771
935
  // South
@@ -780,21 +944,19 @@ type FestivalRegion =
780
944
  // Neighbour
781
945
  | 'nepal';
782
946
 
783
- // Pre-v2.1 identifiers. Accepted as input and mapped at call time; a
784
- // one-shot console warning fires per distinct legacy value. Removal in v3.
947
+ // Pre-v2.1 identifiers accepted with a one-shot deprecation warning. Removed in v3.
785
948
  // 'tamil' → 'tamil-nadu'
786
949
  // 'bengal' → 'west-bengal'
787
- // 'north-india' → 'all' (Makar Sankranti is pan-Indian; use state
788
- // slugs for Lohri / Govardhan / Bhai Dooj)
950
+ // 'north-india' → 'all'
789
951
  type LegacyFestivalRegion = 'tamil' | 'bengal' | 'north-india';
790
952
  ```
791
953
 
792
- **Region-scoped festivals** (non-exhaustive — see `src/core/festivals.ts`):
954
+ **Region-scoped festivals** (non-exhaustive):
793
955
 
794
956
  | Region | Festival names (keys) |
795
957
  |---|---|
796
958
  | `tamil-nadu` | pongal, puthandu, varamahalakshmi |
797
- | `kerala` | vishu, ayyappa_makara_jyothi, onam *(solar-nakshatra)* |
959
+ | `kerala` | vishu, ayyappa_makara_jyothi, onam |
798
960
  | `karnataka` | karaga, varamahalakshmi |
799
961
  | `andhra-pradesh` | varamahalakshmi |
800
962
  | `telangana` | bonalu, varamahalakshmi, bathukamma_start, bathukamma_saddula |
@@ -827,9 +989,9 @@ interface EclipseInfo {
827
989
  start: Date; // UTC — observable phase begins
828
990
  peak: Date; // UTC — greatest eclipse
829
991
  end: Date; // UTC — observable phase ends
830
- visibleFromLocation: boolean; // body above horizon at peak for observer
992
+ visibleFromLocation: boolean;
831
993
  magnitude: number; // fraction of disc obscured at peak, [0, 1]
832
- sutakStart: Date; // pre-eclipse impurity window begins — 12 h (4 prahara) before for solar, 9 h (3 prahara) before for lunar, per classical Smarta convention
994
+ sutakStart: Date; // 12 h before solar / 9 h before lunar
833
995
  sutakEnd: Date; // coincides with eclipse end (moksha)
834
996
  description: string;
835
997
  }
@@ -843,7 +1005,7 @@ interface EclipseInfo {
843
1005
  interface BhadraInfo {
844
1006
  start: Date;
845
1007
  end: Date;
846
- /** Loka: 'earth' = malefic for all work; 'heaven' / 'paatal' = non-terrestrial, milder. */
1008
+ /** 'earth' = malefic for all work; 'heaven' / 'paatal' = non-terrestrial, milder. */
847
1009
  location: 'earth' | 'heaven' | 'paatal';
848
1010
  /** True when Bhadra is active at some point during the Hindu day window. */
849
1011
  isActive: boolean;
@@ -852,7 +1014,7 @@ interface BhadraInfo {
852
1014
  </details>
853
1015
 
854
1016
  <details>
855
- <summary><strong>Jyotish (Vedic Astrology)</strong> — Graha positions, Vimshottari Dasha</summary>
1017
+ <summary><strong>Jyotish</strong> — Graha positions, Vimshottari Dasha, Chandra Balam, Tarabala</summary>
856
1018
 
857
1019
  ```typescript
858
1020
  type GrahaName = 'Sun' | 'Moon' | 'Mars' | 'Mercury' | 'Jupiter'
@@ -861,9 +1023,9 @@ type GrahaName = 'Sun' | 'Moon' | 'Mars' | 'Mercury' | 'Jupiter'
861
1023
  interface GrahaPosition {
862
1024
  planet: GrahaName;
863
1025
  siderealLongitude: number; // degrees [0, 360)
864
- rashi: RashiInfo; // zodiac sign
865
- degreeInRashi: number; // degrees within sign [0, 30)
866
- nakshatra: NakshatraInfo; // nakshatra + pada + completion %
1026
+ rashi: RashiInfo;
1027
+ degreeInRashi: number; // [0, 30)
1028
+ nakshatra: NakshatraInfo;
867
1029
  isRetrograde: boolean; // always false for Sun/Moon; always true for Rahu/Ketu
868
1030
  }
869
1031
 
@@ -876,24 +1038,13 @@ interface PlanetaryPositions {
876
1038
  type DashaLord = 'Ketu' | 'Venus' | 'Sun' | 'Moon' | 'Mars'
877
1039
  | 'Rahu' | 'Jupiter' | 'Saturn' | 'Mercury';
878
1040
 
879
- interface AntarDasha {
880
- lord: DashaLord;
881
- startDate: Date;
882
- endDate: Date;
883
- }
884
-
885
- interface MahaDasha {
886
- lord: DashaLord;
887
- startDate: Date;
888
- endDate: Date;
889
- years: number;
890
- antarDashas: AntarDasha[];
891
- }
892
-
1041
+ interface AntarDasha { lord: DashaLord; startDate: Date; endDate: Date; }
1042
+ interface MahaDasha { lord: DashaLord; startDate: Date; endDate: Date;
1043
+ years: number; antarDashas: AntarDasha[]; }
893
1044
  interface VimshottariDashaResult {
894
1045
  currentMahaDashaLord: DashaLord;
895
1046
  currentIndex: number;
896
- mahaDashas: MahaDasha[]; // 9-entry sequence starting from birth
1047
+ mahaDashas: MahaDasha[]; // 9-entry sequence starting from birth
897
1048
  }
898
1049
 
899
1050
  interface ChandraBalamInfo {
@@ -904,23 +1055,68 @@ interface ChandraBalamInfo {
904
1055
  }
905
1056
 
906
1057
  interface TarabalaInfo {
907
- taraIndex: number; // 0..8 — position in the 9-tara cycle from janma nakshatra
1058
+ taraIndex: number; // 0..8 in the 9-tara cycle from janma nakshatra
908
1059
  englishName: string; // "Janma" | "Sampat" | "Vipat" | "Kshema" | "Pratyari"
909
1060
  // | "Sadhaka" | "Vadha" | "Mitra" | "Ati-Mitra"
910
- name: string; // localized
1061
+ name: string;
911
1062
  quality: 'auspicious' | 'inauspicious';
912
- // 'inauspicious' for Vipat (2) / Pratyari (4) / Vadha (6); rest auspicious
913
1063
  }
914
1064
  ```
915
1065
  </details>
916
1066
 
1067
+ ### Full export list
1068
+
1069
+ ```typescript
1070
+ // Primary entry points
1071
+ getDailyPanchang, getInstantPanchang
1072
+
1073
+ // Astronomy
1074
+ getSunrise, getSunset, getMoonrise, getMoonset
1075
+ getSiderealSunLongitude, getSiderealMoonLongitude, getAyanamsa
1076
+
1077
+ // Inauspicious / Muhurta
1078
+ computeRahuKalam, computeGulikaKalam, computeYamaganda
1079
+ computeVarjyam, computeGandaMula, computeAnandadiYoga
1080
+ computePanchakaRahita, computeDoGhati, computeGowriPanchangam
1081
+ computeAbhijitMuhurta, computeBrahmaMuhurta, computeVijayaMuhurta
1082
+ computeGodhuliMuhurta, computeNishitaMuhurta, computeAmritKala
1083
+ computeMadhyahna, computePratahSandhya, computeSayahnaSandhya
1084
+
1085
+ // Eclipses
1086
+ getUpcomingSolarEclipse, getUpcomingLunarEclipse, getEclipseDuringDay
1087
+
1088
+ // Jyotish
1089
+ computePlanetaryPositions, GRAHA_ABBR
1090
+ computeVimshottariDasha, computeVimshottariDashaFromBirth, computeVimshottariPratyantar
1091
+ computeAshtottariDasha, computeYoginiDasha, computeCharaDasha
1092
+ computeChandraBalam, computeTarabala
1093
+ computeLagna, computeBhava, computeRashiChart, computeNavamsa, computeDivisionalChart
1094
+ computeAspects, computeShadbala
1095
+ computeAshtakoot, computeMangalDosha, computeKaalSarp, computePitruDosha
1096
+ computeSadeSati, computeDignity
1097
+
1098
+ // Muhurta engine
1099
+ scoreMuhurta, findAuspiciousDates, STOCK_MUHURTA_RULES
1100
+ vivahRule, grihaPraveshRule, namakaranaRule, vidyarambhRule, vahanKharidiRule
1101
+ annaprashanRule, mundanRule, upanayanamRule, karnavedhaRule
1102
+ aksharabhyasamRule, seemanthamRule, shopOpeningRule, travelStartRule
1103
+
1104
+ // Calendar conversion + yearly listings
1105
+ convertGregorianToHindu, convertHinduToGregorian
1106
+ getKaliYugaYear, getHinduNewYear, computeSamvat
1107
+ getEkadashiDatesForYear, getSankrantisForYear, getFestivalsInRange, getUpcomingEclipses
1108
+
1109
+ // Errors
1110
+ PanchangError
1111
+ ```
1112
+
917
1113
  ---
918
1114
 
919
1115
  ## React Native / Hermes
920
1116
 
921
- Works with Expo and bare React Native (Hermes engine). Pass `timezone` as a **number**
922
- IANA timezone strings (`'Asia/Kolkata'`) require `Intl`, which older Hermes versions
923
- don't fully support.
1117
+ Works with Expo and bare React Native (Hermes engine). Pass `timezone` as a **number**
1118
+ IANA timezone strings (`'Asia/Kolkata'`) require `Intl`, which older Hermes versions don't
1119
+ fully support.
924
1120
 
925
1121
  **Two-pass rendering** for smooth UI:
926
1122
 
@@ -946,42 +1142,47 @@ InteractionManager.runAfterInteractions(() => {
946
1142
 
947
1143
  ## Accuracy
948
1144
 
949
- 6,912 tests passing across 74 files, including fixtures cross-verified
950
- against reference panchang calculations spanning 2025–2026 across 10
951
- Indian cities, plus New York, London, Sydney, Dubai, and Singapore
952
- (diaspora fixtures cover DST transitions on `America/New_York`).
1145
+ 7,156 tests passing across 81 files, including fixtures cross-verified against reference
1146
+ panchang calculations spanning 2025–2026 across 10 Indian cities, plus New York, London,
1147
+ Sydney, Dubai, and Singapore (diaspora fixtures cover DST transitions on
1148
+ `America/New_York`).
953
1149
 
954
1150
  | Element | Accuracy | Validation |
955
1151
  |---------|----------|------------|
956
- | Sunrise / Sunset | **≤29 s observed vs reference minute-midpoint** (±45 s tolerance) | 16 assertions |
957
- | Moonrise / Moonset | Meeus apparent-upper-limb convention (refraction + parallax); ~3–5 min disagreement vs panchang authorities that use a simpler horizon model is expected and documented | Strict fixtures |
1152
+ | Sunrise / Sunset | 29 s observed vs reference minute-midpoint (±45 s tolerance) | 16 assertions |
1153
+ | Moonrise / Moonset | Meeus apparent-upper-limb (refraction + parallax); ~3–5 min vs simpler-horizon authorities is expected | Strict fixtures |
958
1154
  | Tithi, Nakshatra, Yoga, Karana names | Exact match vs reference | Strict fixtures |
959
- | Tithi / Nakshatra / Yoga / Karana end-times | **±3 min tolerance, max 2.01 min observed** | 20 assertions |
1155
+ | Tithi / Nakshatra / Yoga / Karana end-times | ±3 min tolerance, max 2.01 min observed | 20 assertions |
960
1156
  | Ayanamsa | ±0.005° vs Swiss Ephemeris | Unit tests |
961
- | Planetary positions (Sun–Saturn) | **±0.02° vs reference sidereal** | Fixtures |
962
- | Planetary positions (Rahu/Ketu, mean node) | ≤0.5° typical; ±2° tolerance to absorb mean-vs-true drift | Fixtures |
963
- | Planetary positions (Rahu/Ketu, true node — `nodeType: 'true'`) | ≤0.6° typical (Meeus periodic correction) | Fixtures |
1157
+ | Planetary positions (Sun–Saturn) | ±0.02° vs reference sidereal | Fixtures |
1158
+ | Planetary positions (Rahu/Ketu, mean node) | ≤0.5° typical; ±2° tolerance | Fixtures |
1159
+ | Planetary positions (Rahu/Ketu, true node) | ≤0.6° typical (Meeus periodic correction) | Fixtures |
964
1160
  | Rashi / Nakshatra / Retrograde flag | Exact match vs reference | Fixtures |
965
1161
  | Festival dates | 12 cross-verified festivals (2025–2026) — see caveats below | Fixtures |
966
1162
  | Choghadiya / Hora / Gowri slots | Derived from sunrise/sunset — inherits ±2 min | — |
967
- | Madhyahna midpoint, Anandadi Yoga name, Ganda Mula active flag | **Exact match across 50 reference fixtures** (10 cities × 5 dates) | Cross-verify suite |
968
- | Pratah / Sayahna Sandhya start + end | **±2 min** across all 50 fixtures | Cross-verify suite |
969
- | Varjyam start + end | **±2 min** on every fixture where the library emits a non-null window (≥30 of 50 emit; transition days return `null` by design) | Cross-verify suite |
970
- | Lagna (ascendant) sidereal longitude | Cross-checked against Jagannath Hora reference charts | Birth-chart fixtures |
1163
+ | Madhyahna midpoint, Anandadi Yoga, Ganda Mula active flag | Exact match across 50 reference fixtures | Cross-verify suite |
1164
+ | Pratah / Sayahna Sandhya start + end | ±2 min across all 50 fixtures | Cross-verify suite |
1165
+ | Varjyam start + end | ±2 min on every emit (transition days return `null` by design) | Cross-verify suite |
1166
+ | Lagna sidereal longitude | Cross-checked against Jagannath Hora reference charts | Birth-chart fixtures |
971
1167
  | D1 (Rashi) & D9 (Navamsa) house placements | Exact match vs reference for 9-graha placement | Birth-chart fixtures |
972
1168
  | Ashtakoot Guna Milan total score | ±1 point per pair across 30+ matched pairs | Match fixtures |
973
1169
  | Sade Sati arc start / end | ±1–2 days vs authoritative ephemerides | Saturn-transit fixtures |
974
1170
 
975
- **Detection sourcing notes.** **Aadal / Vidaal** follow the classical Moon-from-Sun nakshatra-distance rule (AstroShastra, HoraSarvam, Ernst Wilhelm), NOT the popular Tamil-Vakya weekday rule used by some online panchangs — output may therefore differ from sites that use the weekday rule. **Varjyam** emits the sunrise-anchored nakshatra's window only — printed panchangs may show a second window on nakshatra-transition days. **Do Ghati Muhurta** does not rotate by weekday: the same 30-name deity-keyed sequence applies every day, verified against multiple reference sources for distinct weekdays.
1171
+ **Detection sourcing notes.** **Aadal / Vidaal** follow the classical Moon-from-Sun
1172
+ nakshatra-distance rule (AstroShastra, HoraSarvam, Ernst Wilhelm), NOT the popular
1173
+ Tamil-Vakya weekday rule used by some online panchangs — output may differ from sites that
1174
+ use the weekday rule. **Varjyam** emits the sunrise-anchored nakshatra's window only —
1175
+ printed panchangs may show a second window on nakshatra-transition days. **Do Ghati
1176
+ Muhurta** does not rotate by weekday: the same 30-name deity-keyed sequence applies every
1177
+ day, verified against multiple reference sources for distinct weekdays.
976
1178
 
977
1179
  ### Festival Detection — Documented Tradeoff
978
1180
 
979
- The library uses **tithi-at-sunrise** to resolve a festival to a calendar
980
- day. Some traditional panchang authorities apply other classical rules
981
- (tithi-at-midnight, madhyahna-vyapini, kshaya-tithi handling) for certain
982
- festivals; where those rules pick a different day, our output can drift
983
- ±1 day. This is a rule-choice tradeoff, not a computation bug — it is
984
- documented and deliberately surfaced rather than hidden.
1181
+ The library uses **tithi-at-sunrise** to resolve a festival to a calendar day. Some
1182
+ traditional panchang authorities apply other classical rules (tithi-at-midnight,
1183
+ madhyahna-vyapini, kshaya-tithi handling) for certain festivals; where those rules pick a
1184
+ different day, our output can drift ±1 day. This is a rule-choice tradeoff, not a
1185
+ computation bug.
985
1186
 
986
1187
  | Alternative classical rule | Festivals affected |
987
1188
  |----------------------------|--------------------|
@@ -989,11 +1190,11 @@ documented and deliberately surfaced rather than hidden.
989
1190
  | Madhyahna-vyapini (tithi overlapping noon) | Ganesh Chaturthi on edge years, Akshaya Tritiya 2026 |
990
1191
  | Kshaya-tithi handling (tithi never at sunrise) | Ugadi 2026-03-19 (Pratipada is Kshaya) |
991
1192
 
992
- If strict parity with a specific panchang authority matters for your use
993
- case, cross-check the above festival set for the target year. Everything
994
- else — Holi, Ugadi (non-Kshaya years), Rama Navami, Raksha Bandhan,
995
- Ganesh Chaturthi (normal years), Navaratri, Dussehra, Karva Chauth,
996
- Hanuman Jayanti — matches the canonical date across 2025 and 2026 fixtures.
1193
+ If strict parity with a specific panchang authority matters for your use case, cross-check
1194
+ the above festival set for the target year. Everything else — Holi, Ugadi (non-Kshaya
1195
+ years), Rama Navami, Raksha Bandhan, Ganesh Chaturthi (normal years), Navaratri,
1196
+ Dussehra, Karva Chauth, Hanuman Jayanti matches the canonical date across 2025 and 2026
1197
+ fixtures.
997
1198
 
998
1199
  ---
999
1200
 
@@ -1004,6 +1205,9 @@ Hanuman Jayanti — matches the canonical date across 2025 and 2026 fixtures.
1004
1205
  | Names-only (`computeEndTimes: false`) | ~0.1 ms | <100 ms |
1005
1206
  | Full with end-times | ~0.5 ms | <500 ms |
1006
1207
 
1208
+ Birth-chart helpers are independent — calling them does not add work to
1209
+ `getDailyPanchang`.
1210
+
1007
1211
  ---
1008
1212
 
1009
1213
  ## Error Handling
@@ -1021,15 +1225,15 @@ try {
1021
1225
  }
1022
1226
  ```
1023
1227
 
1024
- Error codes: `INVALID_DATE`, `INVALID_LATITUDE`, `INVALID_LONGITUDE`,
1025
- `INVALID_ELEVATION`, `INVALID_TIMEZONE`, `INVALID_AYANAMSA`, `TIMEZONE_RESOLUTION_FAILED`,
1026
- `NO_SUNRISE`, `NO_SUNSET`, `SEARCH_DIVERGED`.
1228
+ Error codes: `INVALID_DATE`, `INVALID_LATITUDE`, `INVALID_LONGITUDE`, `INVALID_ELEVATION`,
1229
+ `INVALID_TIMEZONE`, `INVALID_AYANAMSA`, `TIMEZONE_RESOLUTION_FAILED`, `NO_SUNRISE`,
1230
+ `NO_SUNSET`, `SEARCH_DIVERGED`, `CIRCUMPOLAR` (Placidus-KP houses above ±66.5°).
1027
1231
 
1028
1232
  **Polar locations (no sunrise / no sunset):** `getDailyPanchang` and `getInstantPanchang`
1029
1233
  return `null` rather than throwing — the Hindu day is undefined when sunrise can't be
1030
- computed. The low-level `computeSunrise` / `computeSunset` primitives still throw
1031
- `PanchangError(NO_SUNRISE)` / `PanchangError(NO_SUNSET)` for direct callers who need
1032
- the precise reason. `getMoonrise` / `getMoonset` return `null` (normal for the Moon).
1234
+ computed. The low-level `getSunrise` / `getSunset` primitives still throw
1235
+ `PanchangError(NO_SUNRISE)` / `PanchangError(NO_SUNSET)` for direct callers who need the
1236
+ precise reason. `getMoonrise` / `getMoonset` return `null` (normal for the Moon).
1033
1237
 
1034
1238
  ---
1035
1239
 
@@ -1045,13 +1249,10 @@ the precise reason. `getMoonrise` / `getMoonset` return `null` (normal for the M
1045
1249
 
1046
1250
  ---
1047
1251
 
1048
- ## Used By
1049
-
1050
- - [dharmagya.app](https://dharmagya.app) — Daily Panchang and Hindu calendar
1051
-
1052
1252
  ## Acknowledgements
1053
1253
 
1054
- [astronomy-engine](https://github.com/cosinekitty/astronomy) by Don Cross — the sole runtime dependency. MIT licensed.
1254
+ [astronomy-engine](https://github.com/cosinekitty/astronomy) by Don Cross — the sole
1255
+ runtime dependency. MIT licensed.
1055
1256
 
1056
1257
  ## License
1057
1258