panchang-ts 3.0.0 → 3.0.1

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.
Files changed (2) hide show
  1. package/README.md +546 -547
  2. package/package.json +1 -1
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) | **6,912 tests**
30
9
 
31
10
  ---
32
11
 
@@ -40,6 +19,41 @@ 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 (Rashi), D9 (Navamsa), Planetary Dignity | [↓](#14-birth-chart-kundli) |
45
+ | **Compatibility & Doshas** | Ashtakoot Guna Milan (36-point), Mangal Dosha (Manglik) | [↓](#15-compatibility--doshas) |
46
+ | **Localization** | English + Hindi (Devanagari) on every returned name | [↓](#16-localization) |
47
+ | **Configuration** | 5 ayanamsas (Lahiri, Raman, KP, True Chitrapaksha, Thirukanitham), 2 masa systems, 3 house systems, 21 regional festival scopes | [↓](#17-configuration) |
48
+
49
+ ---
50
+
51
+ ## Used By
52
+
53
+ - [dharmagya.app](https://dharmagya.app) — Daily Panchang and Hindu calendar
54
+
55
+ ---
56
+
43
57
  ## Quick Start
44
58
 
45
59
  ```typescript
@@ -53,57 +67,17 @@ const result = getDailyPanchang(
53
67
  // result is `DailyPanchangResult | null` — null only at polar latitudes
54
68
  // where sunrise can't be computed. Anywhere else, narrow with `if (!result) return;`
55
69
 
56
- // Pancha Anga
57
70
  console.log(result.tithis[0].name); // "Krishna Chaturdashi"
58
71
  console.log(result.nakshatras[0].name); // "Mrigashira"
59
72
  console.log(result.vara.name); // "Mangalawara"
60
-
61
- // Lunar calendar (Purnimanta by default)
62
73
  console.log(result.chandramasa.name); // "Magha"
63
- console.log(result.chandramasa.amantaName); // "Pausha" (South Indian)
64
74
  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
75
  ```
102
76
 
103
77
  ### Reading Output Times
104
78
 
105
- All `Date` objects in the result are **offset-adjusted** to the requested timezone.
106
- Always read time components via `getUTC*` methods:
79
+ All `Date` objects in the result are **offset-adjusted** to the requested timezone. Always
80
+ read time components via `getUTC*` methods — `.getHours()` would use your system zone:
107
81
 
108
82
  ```typescript
109
83
  const sunrise = result.sunrise;
@@ -111,7 +85,6 @@ const h = sunrise.getUTCHours(); // 7
111
85
  const m = sunrise.getUTCMinutes(); // 4
112
86
  // → Sunrise at 07:04 local time
113
87
 
114
- // Format helper:
115
88
  function fmt(d: Date) {
116
89
  const h = d.getUTCHours(), m = d.getUTCMinutes();
117
90
  return `${h}:${String(m).padStart(2, '0')}`;
@@ -119,477 +92,494 @@ function fmt(d: Date) {
119
92
  fmt(result.rahuKalam.start); // "09:04"
120
93
  ```
121
94
 
122
- Do **not** use `.getHours()` — it uses your system timezone, which may differ.
95
+ `moonrise` and `moonset` can be `null`the Moon occasionally does not rise or set on a
96
+ given calendar day, which is normal.
123
97
 
124
- `moonrise` and `moonset` can be `null` — the Moon occasionally does not rise or set
125
- on a given calendar day, which is normal.
98
+ ### `getDailyPanchang` vs `getInstantPanchang`
126
99
 
127
- ### Language & Masa System
100
+ | Use case | Recommended | Why |
101
+ |----------|-------------|-----|
102
+ | "What Panchang elements are active right now?" | `getInstantPanchang` | Single-moment snapshot; no sunrise needed |
103
+ | Birth chart / muhurta picking at a specific instant | `getInstantPanchang` | Exact element at that UTC moment |
104
+ | Daily calendar / almanac row for a date | `getDailyPanchang` | Lists all element transitions for the day |
105
+ | Today's festivals & observances | `getDailyPanchang` | Full canonical-time festival refinement |
106
+ | Rahu Kalam / Choghadiya / Gowri / Hora / muhurtas | `getDailyPanchang` | Computed from sunrise, sunset, day length |
107
+ | Eclipse detection with sutak window | `getDailyPanchang` | Overlapping the day needs the day window |
108
+
109
+ `getInstantPanchang` does emit `festivals`, but evaluates rules against the elements at the
110
+ given instant only. It does not run canonical-time refinements (madhyahna / pradosha /
111
+ nishita / chandrodaya), transit-based Sankranti, Ekadashi viddha (Smarta/Vaishnava split),
112
+ or Bhadra-aware Raksha Bandhan exclusion. For reliable festival dating, use
113
+ `getDailyPanchang`.
114
+
115
+ ---
116
+
117
+ # Feature Reference
118
+
119
+ Each section below shows how to access one feature category. Every feature is also
120
+ returned as a field on the unified `DailyPanchangResult` from `getDailyPanchang(…)` if you
121
+ prefer one call over the per-feature helpers.
122
+
123
+ ## 1. Pancha Anga — the Five Limbs
124
+
125
+ Tithi, Nakshatra, Yoga, Karana, Vara — with start / end times for every transition during
126
+ the Hindu day.
128
127
 
129
128
  ```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); // "मंगलवार"
129
+ import { getDailyPanchang } from 'panchang-ts';
137
130
 
138
- // Amanta (South Indian) masa system
139
- const amanta = getDailyPanchang(date, location, {
140
- timezone: 330,
141
- masaSystem: 'amanta',
131
+ const r = getDailyPanchang(date, location, { timezone: 330 })!;
132
+
133
+ // Tithis active during the day (usually 1-2)
134
+ r.tithis.forEach(t => {
135
+ console.log(t.name, t.paksha, t.completionPercentage, t.endTime);
142
136
  });
143
- console.log(amanta.chandramasa.name); // Amanta month name
144
- console.log(amanta.chandramasa.system); // "amanta"
145
- ```
146
137
 
147
- ### Regional Festival Filtering
138
+ // Nakshatras (with pada)
139
+ r.nakshatras.forEach(n => console.log(n.name, n.pada, n.endTime));
148
140
 
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.
141
+ // Yogas (27-name lunisolar cycle)
142
+ r.yogas.forEach(y => console.log(y.name, y.endTime));
152
143
 
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"]
144
+ // Karanas (half-tithi; usually 2-4 per day)
145
+ r.karanas.forEach(k => console.log(k.name, k.type, k.endTime));
159
146
 
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"]
147
+ // Vara (weekday)
148
+ console.log(r.vara.name, r.vara.englishName); // "Mangalawara", "Tuesday"
149
+ ```
164
150
 
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
151
+ For a single-instant snapshot use `getInstantPanchang`:
169
152
 
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.
153
+ ```typescript
154
+ import { getInstantPanchang } from 'panchang-ts';
155
+
156
+ const i = getInstantPanchang(new Date(), location)!;
157
+ console.log(i.tithi.name, i.nakshatra.name, i.yoga.name, i.karana.name, i.vara.name);
174
158
  ```
175
159
 
176
- See [`FestivalRegion`](#types) for the full state-slug list (21 states + `'nepal'`).
160
+ ## 2. Lunar Calendar
177
161
 
178
- ---
162
+ Chandra Masa with **Purnimanta** (North Indian, default) and **Amanta** (South Indian)
163
+ naming, **Adhika** (leap-month) detection, **Vikram** and **Shaka** samvat year numbers.
164
+
165
+ ```typescript
166
+ const r = getDailyPanchang(date, loc, { timezone: 330, masaSystem: 'purnimanta' })!;
167
+
168
+ console.log(r.chandramasa.name); // "Magha" (active system)
169
+ console.log(r.chandramasa.amantaName); // "Pausha" (South Indian)
170
+ console.log(r.chandramasa.purnimantaName); // "Magha" (North Indian)
171
+ console.log(r.chandramasa.isAdhika); // false (true during leap months)
179
172
 
180
- ## Features
173
+ console.log(r.samvat.vikramSamvat); // 2081
174
+ console.log(r.samvat.shakaSamvat); // 1946
175
+ ```
181
176
 
182
- ### Pancha Anga (5 Limbs)
183
- Tithi, Nakshatra, Yoga, Karana, Vara — with transition times throughout the day.
177
+ ## 3. Solar Calendar
184
178
 
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.
179
+ Saura Masa (solar month), Surya Nakshatra (the Sun's nakshatra, ~13–14 day transit),
180
+ Sankranti (solar-month boundary, transit-based emitted as a festival).
187
181
 
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).
182
+ ```typescript
183
+ const r = getDailyPanchang(date, loc, { timezone: 330 })!;
190
184
 
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).
185
+ console.log(r.masa.name); // "Makara" (current solar month)
186
+ console.log(r.suryaNakshatra.name); // "Uttara Ashadha"
187
+ console.log(r.chandraRashi.name); // "Mithuna" (Moon sign)
193
188
 
194
- ### Special Yogas & Festivals
195
- Amrit Siddhi, Sarvartha Siddhi, Ravi Pushya, Guru Pushya, **Dwipushkar**, **Tripushkar**, **Jwalamukhi**, **Aadal**, **Vidaal**, **Ravi** yoga detection.
189
+ // Sankranti and its regional variants emit through r.festivals — see §9.
190
+ ```
196
191
 
197
- **80+ festivals** spanning pan-Indian, regional, and classical observances:
192
+ ## 4. Sun & Moon
198
193
 
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.
194
+ Sunrise, sunset, moonrise, moonset (Meeus apparent-upper-limb), plus Chandra Rashi
195
+ (Moon's zodiac sign).
207
196
 
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.
197
+ ```typescript
198
+ import { getSunrise, getSunset, getMoonrise, getMoonset } from 'panchang-ts';
210
199
 
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).
200
+ const loc = { latitude: 28.6139, longitude: 77.2090 }; // New Delhi
213
201
 
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).
202
+ const sunrise = getSunrise(localMidnightUtc, loc);
203
+ const sunset = getSunset(sunrise, loc);
216
204
 
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.
205
+ // Moonrise / moonset can be null on days the Moon doesn't rise/set
206
+ const moonrise = getMoonrise(localMidnightUtc, loc);
207
+ const moonset = getMoonset(localMidnightUtc, loc);
219
208
 
220
- ### Localization
221
- 2 languages: **English** and **Hindi** (Devanagari). All returned display strings respect the `language` option.
209
+ // Or read all of them off the daily result:
210
+ const r = getDailyPanchang(date, loc, { timezone: 330 })!;
211
+ console.log(r.sunrise, r.sunset, r.moonrise, r.moonset, r.nextSunrise);
212
+ console.log(r.dayDurationMinutes, r.nightDurationMinutes);
213
+ ```
222
214
 
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).
215
+ ## 5. Auspicious Muhurta
225
216
 
226
- ---
217
+ Classical auspicious time windows: Brahma, Abhijit, Vijaya, Godhuli, Nishita, Madhyahna,
218
+ Pratah / Sayahna Sandhya, and nakshatra-keyed Amrit Kala.
219
+
220
+ ```typescript
221
+ const r = getDailyPanchang(date, loc, { timezone: 330 })!;
222
+
223
+ r.brahmaMuhurta; // two muhurtas before sunrise
224
+ r.abhijitMuhurta; // 8th day-muhurta — universally auspicious
225
+ r.vijayaMuhurta; // 11th day-muhurta — auspicious for success
226
+ r.godhuliMuhurta; // "cow-dust" — sunset muhurta
227
+ r.nishitaMuhurta; // midnight muhurta (Shivaratri)
228
+ r.madhyahna; // solar noon ±24 min
229
+ r.pratahSandhya; // dawn twilight, ends *at* sunrise
230
+ r.sayahnaSandhya; // dusk twilight, starts *at* sunset
231
+ r.amritKala; // nakshatra-specific window (null when nakshatra has none)
232
+
233
+ // Direct helpers:
234
+ import {
235
+ computeBrahmaMuhurta, computeAbhijitMuhurta, computeVijayaMuhurta,
236
+ computeGodhuliMuhurta, computeNishitaMuhurta, computeMadhyahna,
237
+ computePratahSandhya, computeSayahnaSandhya, computeAmritKala,
238
+ } from 'panchang-ts';
239
+ ```
227
240
 
228
- ## API Reference
241
+ `pratahSandhya` and `sayahnaSandhya` are asymmetric — width = `nightDuration / 10`
242
+ (~62–81 min depending on season), matching DrikPanchang within ±2 min.
229
243
 
230
- ### `getDailyPanchang(date, location, options)`
244
+ ## 6. Inauspicious Periods
231
245
 
232
- Returns the full Hindu day from sunrise to next sunrise, with all element transitions.
246
+ Rahu Kalam, Gulika Kalam, Yamaganda, Dur Muhurta (2 windows), Varjyam (BPHS-keyed
247
+ ~96-min forbidden window), Ganda Mula (Moon in root nakshatras), Bhadra Kala (Vishti
248
+ karana with earth/heaven/paatal location), Panchaka.
233
249
 
234
250
  ```typescript
235
- import { getDailyPanchang } from 'panchang-ts';
251
+ const r = getDailyPanchang(date, loc, { timezone: 330 })!;
252
+
253
+ r.rahuKalam; // { start, end }
254
+ r.gulikaKalam; // { start, end }
255
+ r.yamaganda; // { start, end }
256
+ r.durMuhurta; // [TimePeriod, TimePeriod] — two ~48-min windows
257
+ r.varjyam; // { start, end } | null
258
+ r.gandaMula; // { active: boolean, severity: 'mild' | 'severe' | null, ... }
259
+ r.bhadra; // { start, end, location: 'earth'|'heaven'|'paatal', isActive } | null
260
+ r.panchaka; // boolean — Moon in last 5 nakshatras
261
+
262
+ // Direct helpers (varaIndex: 0=Sun ... 6=Sat):
263
+ import {
264
+ computeRahuKalam, computeGulikaKalam, computeYamaganda,
265
+ computeVarjyam, computeGandaMula,
266
+ } from 'panchang-ts';
236
267
 
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
- );
268
+ const rahu = computeRahuKalam(sunrise, sunset, varaIndex);
242
269
  ```
243
270
 
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) |
271
+ ## 7. Time-Slot Systems
303
272
 
304
- ---
273
+ Four parallel slot systems covering the Hindu day:
305
274
 
306
- ### `getInstantPanchang(date, location, options?)`
275
+ ```typescript
276
+ const r = getDailyPanchang(date, loc, { timezone: 330 })!;
307
277
 
308
- Returns the single Panchang element active at an exact UTC moment.
278
+ // Choghadiya 8 day + 8 night slots, each named (Amrit, Kaal, Shubh, Rog, ...) and rated
279
+ r.choghadiya.day.forEach(s => console.log(s.name, s.qualityName, s.start, s.end));
280
+ r.choghadiya.night.forEach(s => console.log(s.name, s.qualityName));
309
281
 
310
- ```typescript
311
- import { getInstantPanchang } from 'panchang-ts';
282
+ // Gowri Panchangam (Tamil "Nalla Neram") — 8 day + 8 night slots
283
+ r.gowriPanchangam.day.forEach(s => console.log(s.name, s.qualityName));
312
284
 
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
- );
285
+ // Hora 12 day + 12 night planetary hours (Chaldean order)
286
+ r.hora.day.forEach(h => console.log(h.planet, h.start, h.end));
287
+
288
+ // Do Ghati Muhurta 15 day + 15 night ~48-min deity-keyed slots (no vara rotation)
289
+ r.doGhatiMuhurta.day.forEach(g => console.log(g.name, g.start, g.end));
318
290
 
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
291
+ // Panchaka Rahita — slices of the day FREE of Panchaka ([] when Panchaka pervades)
292
+ r.panchakaRahita.forEach(slice => console.log(slice.start, slice.end));
325
293
  ```
326
294
 
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) |
295
+ ## 8. Special Yogas
354
296
 
355
- ---
297
+ Auspicious / inauspicious yogas formed by Vara × Tithi × Nakshatra combinations and
298
+ Moon-from-Sun nakshatra-distance rules. The 28-name **Anandadi Yoga** cycle is also
299
+ returned at sunrise.
356
300
 
357
- ### When to use `getInstantPanchang` vs `getDailyPanchang`
301
+ ```typescript
302
+ const r = getDailyPanchang(date, loc, { timezone: 330 })!;
303
+
304
+ // Anandadi Yoga (Vara × Nakshatra cycle of 28 names)
305
+ console.log(r.anandadiYoga.name); // "Ananda"
306
+
307
+ // Special yogas active today
308
+ r.specialYogas.forEach(y => {
309
+ console.log(y.name, y.type);
310
+ // type: 'amrit_siddhi' | 'sarvartha_siddhi' | 'ravi_pushya' | 'guru_pushya'
311
+ // | 'dwipushkar' | 'tripushkar' ← actions doubled / tripled
312
+ // | 'jwalamukhi' ← inauspicious (Muhurta-chintamani 6.32)
313
+ // | 'aadal' | 'vidaal' | 'ravi' ← Moon-from-Sun nakshatra-distance rules
314
+ });
315
+ ```
358
316
 
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.
317
+ ## 9. Festivals
360
318
 
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`.
319
+ **80+ festivals** spanning pan-Indian, regional, and classical observances:
374
320
 
375
- ---
321
+ - **Ekadashi** — 26 named variants (Putrada, Shat Tila, Nirjala, Devshayani, …) with
322
+ **Smarta / Vaishnava split** via Dashami-viddha rule; Smarta fast emits a `deferralDate`
323
+ for Dwadashi.
324
+ - **Pradosha** — 7 weekday-qualified variants (Som, Bhauma, Shani, …) on both pakshas.
325
+ - **Sankranti** — transit-based detection plus regional variants (Pongal, Vishu, Baisakhi,
326
+ Pohela Boishakh, Bohag / Magh / Kati Bihu, Uttarayan, Ayyappa Makara Jyothi, Raja
327
+ Sankranti, Harela, Sair, Singh Sankranti). **Lohri** fires on the Hindu day immediately
328
+ preceding Makara Sankranti under Punjab / Haryana / Himachal scopes.
329
+ - **Canonical-time classical festivals** — Ganesh Chaturthi (madhyahna), Shivaratri
330
+ (nishita), Diwali, Holi, Raksha Bandhan (Bhadra-aware), Karva Chauth (chandrodaya),
331
+ Janmashtami, Dussehra, Navaratri, Ram Navami, Hanuman Jayanti, Akshaya Tritiya &
332
+ Parashurama Jayanti (madhyahna-vyapini), Makar Sankranti.
333
+ - **Regional festivals** — Gudi Padwa, Gangaur, Karaga, Bonalu, Varamahalakshmi,
334
+ Bathukamma, Hariyali / Kajari / Hartalika Teej, Govardhan Puja, Bhai Dooj, Phagli,
335
+ Jagannath Rath Yatra, Raja Parba 3-day arc.
336
+ - **Regional & seasonal** — Chhath (4-day sequence), Vat Savitri, Upakarma, Onam.
337
+ - **Monthly observances** — Masik Shivaratri, Vinayaka Chaturthi, Masik Karthigai, Pushya
338
+ days, Shravan Somvar, and other month + weekday patterns.
376
339
 
377
- ### Options
340
+ ```typescript
341
+ const r = getDailyPanchang(date, loc, { timezone: 330 })!;
378
342
 
379
- **`PanchangOptions`** (required for `getDailyPanchang`):
343
+ r.festivals.forEach(f => {
344
+ console.log(f.name, f.type, f.deferralDate);
345
+ // type: 'major' | 'minor' | 'ekadashi'
346
+ // | 'smarta_ekadashi' | 'vaishnava_ekadashi' ← Smarta sets deferralDate
347
+ // | 'pradosha' | 'sankranti' | 'eclipse'
348
+ });
349
+ ```
380
350
 
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`. |
351
+ ### Regional festival scoping
392
352
 
393
- **`InstantPanchangOptions`** (optional for `getInstantPanchang`): same as above but without `timezone` (instant mode works in UTC).
353
+ The `region` option scopes regional festival variants to one Indian state. Pan-Indian
354
+ festivals (Diwali, Holi, Raksha Bandhan, the canonical `sankranti` event) emit regardless.
394
355
 
395
- ---
356
+ ```typescript
357
+ // Default — every regional variant emits on Makar Sankranti day:
358
+ const all = getDailyPanchang(jan14, chennai, { timezone: 330 })!;
359
+ all.festivals.map(f => f.name);
360
+ // → ["Sankranti", "Makar Sankranti", "Pongal", "Uttarayan",
361
+ // "Magh Bihu", "Ayyappa Makara Jyothi"]
396
362
 
397
- ### Low-level Utilities
363
+ // Scope to Tamil Nadu — drops Bihu/Ayyappa/Uttarayan:
364
+ const tn = getDailyPanchang(jan14, chennai, { timezone: 330, region: 'tamil-nadu' })!;
365
+ tn.festivals.map(f => f.name);
366
+ // → ["Sankranti", "Makar Sankranti", "Pongal"]
398
367
 
399
- Exported for advanced use cases building custom tools, visualizations, or Jyotish applications.
368
+ // Lohri fires on the Hindu day BEFORE Makara transit, scoped to Punjab/Haryana/Himachal
369
+ const lohri = getDailyPanchang(jan13, amritsar, { timezone: 330, region: 'punjab' })!;
370
+ lohri.festivals.some(f => f.name === 'Lohri'); // true
371
+ ```
400
372
 
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';
373
+ `FestivalRegion` covers 21 Indian states + `'nepal'` + `'all'` (default). See
374
+ [Types](#types--exports) for the full slug list.
424
375
 
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 });
376
+ ## 10. Eclipses
428
377
 
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 });
378
+ Solar / lunar eclipse detection with subtype, magnitude, observer-horizon visibility, and
379
+ classical pre-eclipse **sutak** impurity window.
432
380
 
433
- // Sidereal longitudes
434
- const moonLon = getSiderealMoonLongitude(new Date(), 'lahiri'); // degrees [0, 360)
435
- const sunLon = getSiderealSunLongitude(new Date(), 'lahiri');
381
+ ```typescript
382
+ const r = getDailyPanchang(date, loc, { timezone: 330 })!;
383
+
384
+ if (r.eclipse) {
385
+ console.log(r.eclipse.kind); // 'solar' | 'lunar'
386
+ console.log(r.eclipse.subtype); // 'partial' | 'total' | 'annular' | 'penumbral'
387
+ console.log(r.eclipse.magnitude); // 0..1 fraction of disc obscured at peak
388
+ console.log(r.eclipse.visibleFromLocation); // body above horizon at peak?
389
+ console.log(r.eclipse.start, r.eclipse.peak, r.eclipse.end);
390
+ console.log(r.eclipse.sutakStart, r.eclipse.sutakEnd);
391
+ // Sutak: 12 h (4 prahara) before solar, 9 h (3 prahara) before lunar
392
+ }
436
393
 
437
- // Ayanamsa
438
- const ayan = getAyanamsa(new Date(), 'lahiri'); // e.g. 24.10
394
+ // Or look ahead:
395
+ import { getUpcomingSolarEclipse, getUpcomingLunarEclipse } from 'panchang-ts';
396
+ const next = getUpcomingSolarEclipse(new Date(), loc, /* withinDays */ 365);
397
+ ```
439
398
 
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);
399
+ ## 11. Planetary Positions
444
400
 
445
- // Muhurta
446
- const abhijit = computeAbhijitMuhurta(sunrise, sunset); // { start, end }
447
- const brahma = computeBrahmaMuhurta(sunrise, sunset); // { start, end }
401
+ All 9 grahas (Sun → Saturn + Rahu / Ketu) — geocentric, sidereal — with rashi, nakshatra,
402
+ pada, retrograde flag. Optional `nodeType: 'true'` upgrades Rahu / Ketu from mean node
403
+ (±2° worst-case) to Meeus's dominant periodic correction (~±0.6°).
404
+
405
+ ```typescript
406
+ import { computePlanetaryPositions, GRAHA_ABBR } from 'panchang-ts';
407
+
408
+ const grahas = computePlanetaryPositions(new Date(), 'lahiri');
409
+ console.log(grahas.jupiter.rashi.name); // "Dhanu"
410
+ console.log(grahas.jupiter.degreeInRashi); // 18.42
411
+ console.log(grahas.jupiter.nakshatra.name); // "Purva Ashadha"
412
+ console.log(grahas.jupiter.nakshatra.pada); // 3
413
+ console.log(grahas.saturn.isRetrograde); // true / false
414
+ console.log(GRAHA_ABBR['Jupiter']); // "Ju"
415
+
416
+ // True node (more accurate Rahu / Ketu)
417
+ const grahasTrue = computePlanetaryPositions(new Date(), 'lahiri', undefined, 'true');
448
418
  ```
449
419
 
450
- **Jyotish (Vedic Astrology):**
420
+ ## 12. Vimshottari Dasha
421
+
422
+ Maha → Antar → Pratyantar (3-level) breakdown, derived from a birth moment alone or from
423
+ an explicit Moon longitude.
451
424
 
452
425
  ```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"
426
+ import {
427
+ computeVimshottariDasha, computeVimshottariDashaFromBirth,
428
+ computeVimshottariPratyantar, getSiderealMoonLongitude,
429
+ } from 'panchang-ts';
458
430
 
459
- // Vimshottari Dasha — convenience form: birth date only (Moon longitude derived)
431
+ // Convenience: from birth date alone (Moon longitude derived)
460
432
  const dasha = computeVimshottariDashaFromBirth(birthDate, 'lahiri');
461
- console.log(dasha.currentMahaDashaLord); // "Rahu"
462
- console.log(dasha.mahaDashas[0]!.antarDashas[0]!.lord); // "Rahu"
433
+ console.log(dasha.currentMahaDashaLord); // "Rahu"
434
+ console.log(dasha.mahaDashas[0]!.antarDashas[0]!.lord); // "Rahu"
463
435
 
464
- // Or pass an explicit Moon sidereal longitude (useful when you already have one)
436
+ // Or pass an explicit Moon sidereal longitude
465
437
  const moonLon = getSiderealMoonLongitude(birthDate, 'lahiri');
466
438
  const dasha2 = computeVimshottariDasha(birthDate, moonLon);
467
439
 
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"
440
+ // Pratyantarthird-level sub-sub-periods within an Antardasha
441
+ const firstAntar = dasha.mahaDashas[0]!.antarDashas[0]!;
442
+ const pratyantars = computeVimshottariPratyantar(firstAntar); // PratyantarDasha[9]
481
443
  ```
482
444
 
483
- ---
445
+ ## 13. Personal Transits
446
+
447
+ Daily transit-based favorability relative to the native's birth Moon. Pass `janmaRashi`
448
+ or `janmaNakshatra` to `getDailyPanchang` and the corresponding field is added to the
449
+ result; or call the helpers directly.
450
+
451
+ ```typescript
452
+ const r = getDailyPanchang(date, loc, {
453
+ timezone: 330,
454
+ janmaRashi: 3, // 0 = Mesha ... 11 = Meena
455
+ janmaNakshatra: 0, // 0 = Ashwini ... 26 = Revati
456
+ })!;
484
457
 
485
- ### Birth Chart (Kundli) API
458
+ r.chandraBalam!; // { house, quality: 'strong' | 'weak', name, englishName }
459
+ r.tarabala!; // { taraIndex, name, englishName, quality }
486
460
 
487
- Vedic kundli foundation. Each helper is independent — calling birth-chart APIs
488
- does **not** add any work to `getDailyPanchang`.
461
+ // Direct helpers:
462
+ import { computeChandraBalam, computeTarabala, computeSadeSati } from 'panchang-ts';
463
+
464
+ computeChandraBalam(3 /* janma */, 6 /* transit Moon rashi */);
465
+ computeTarabala(0 /* janma nakshatra */, 4 /* transit Moon nakshatra */);
466
+
467
+ // Sade Sati — Saturn currently transiting 12th, 1st, or 2nd from natal Moon
468
+ const sadeSati = computeSadeSati(natalMoonRashiIndex, new Date());
469
+ // → { active, phase: 1|2|3|null, currentArcStart, currentArcEnd, nextArcStart }
470
+ ```
471
+
472
+ ## 14. Birth Chart (Kundli)
473
+
474
+ Sidereal **Lagna**, **Bhava** under three house systems, **D1 (Rashi)** and **D9
475
+ (Navamsa)** charts placing all 9 grahas, and **Planetary Dignity**.
489
476
 
490
477
  ```typescript
491
478
  import {
492
- computeLagna, computeBhava,
493
- computeRashiChart, computeNavamsa,
494
- computeAshtakoot, computeMangalDosha, computeSadeSati,
495
- computeDignity, computeVimshottariPratyantar,
496
- computeVimshottariDashaFromBirth,
479
+ computeLagna, computeBhava, computeRashiChart, computeNavamsa,
480
+ computeDignity,
497
481
  } from 'panchang-ts';
498
482
 
499
- const birth = new Date('1995-08-15T05:30:00Z'); // 11:00 IST
500
- const loc = { latitude: 28.6139, longitude: 77.2090 }; // New Delhi
483
+ const birth = new Date('1995-08-15T05:30:00Z');
484
+ const loc = { latitude: 28.6139, longitude: 77.2090 };
501
485
 
502
486
  // 1. Lagna (sidereal ascendant)
503
487
  const lagna = computeLagna(birth, loc, 'lahiri', 'en');
504
- // → { siderealLongitude, rashi: { index, name }, degreeInRashi,
505
- // nakshatra: { index, name }, pada }
488
+ // → { siderealLongitude, rashi, degreeInRashi, nakshatra, pada }
506
489
 
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°
490
+ // 2. Bhava (12 houses)
491
+ // - 'whole-sign' (default classical Vedic) each rashi is one house
511
492
  // - '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
493
+ // - 'placidus-kp' — true cuspal positions; throws PanchangError('CIRCUMPOLAR') > ±66.5°
494
+ const houses = computeBhava(birth, loc, { houseSystem: 'whole-sign' });
514
495
 
515
496
  // 3. D1 (Rashi) chart — lagna + bhava + 9 grahas with house placement
516
497
  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;
498
+ d1.planets.find(p => p.planet === 'Jupiter')?.house; // e.g. 5
499
+ d1.planets.find(p => p.planet === 'Saturn')?.isRetrograde;
520
500
 
521
501
  // 4. D9 (Navamsa) chart — classical sign-based per-rashi-type rule
522
502
  const d9 = computeNavamsa(birth, loc);
523
- // → { divisional: 'D9', lagnaRashi, planets: PlanetPlacement[9] }
524
503
 
525
- // 5. Ashtakoot Guna Milan — 36-point marriage compatibility from natal Moons
526
- const ashtakoot = computeAshtakoot(
504
+ // 5. Planetary dignity (BPHS Ch.3-4)
505
+ computeDignity('Mars', 0); // 'moolatrikona' (Aries)
506
+ computeDignity('Mars', 9); // 'exalted' (Capricorn)
507
+ computeDignity('Sun', 6); // 'debilitated' (Libra)
508
+ ```
509
+
510
+ Birth-chart helpers accept the full ayanamsa set including `'true-chitra'` (True
511
+ Chitrapaksha) and `'thirukanitham'` (Tamil-Vakya). Pass via `options.ayanamsa` or the
512
+ ayanamsa positional arg.
513
+
514
+ ## 15. Compatibility & Doshas
515
+
516
+ **Ashtakoot Guna Milan** (36-point marriage compatibility) and **Mangal Dosha** (Manglik
517
+ affliction with cancellations).
518
+
519
+ ```typescript
520
+ import { computeAshtakoot, computeMangalDosha } from 'panchang-ts';
521
+
522
+ // Ashtakoot — from natal Moons
523
+ const match = computeAshtakoot(
527
524
  { rashi: 4, nakshatra: 9 }, // boy: Simha / Magha
528
525
  { rashi: 0, nakshatra: 1 }, // girl: Mesha / Bharani
529
526
  );
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)
527
+ // → { totalScore: 0..36, koots: KootScore[8], cancellations: string[] }
528
+ // Koots in canonical order: Varna, Vashya, Tara, Yoni, Graha Maitri, Gana, Bhakoot, Nadi
529
+ // (max scores 1, 2, 3, 4, 5, 6, 7, 8 respectively)
533
530
 
534
- // 6. Mangal Dosha (Manglik) — checks Mars from lagna, Moon, and Venus
531
+ // Mangal Dosha — checks Mars from lagna, Moon, and Venus
535
532
  const mangal = computeMangalDosha(d1);
536
- // → { afflicted: boolean,
537
- // fromLagna: { afflicted, house }, fromMoon: ..., fromVenus: ...,
538
- // cancellations: string[] }
533
+ // → { afflicted, fromLagna, fromMoon, fromVenus, cancellations }
534
+ ```
539
535
 
540
- // 7. Sade Sati Saturn 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 }
536
+ **Documented limitations**Mangal Dosha cancellations only cover Mars in own sign
537
+ (Aries / Scorpio) or exalted (Capricorn); other classical cancellations (mutual Mangalik,
538
+ Mars-Jupiter aspect, Mars-Saturn conjunction) are not applied. Ashtakoot Vashya koot is
539
+ simplified to single-vashya per rashi.
543
540
 
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)
541
+ ## 16. Localization
542
+
543
+ All returned display names respect the `language` option. **English** and **Hindi
544
+ (Devanagari)** are supported.
549
545
 
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
546
+ ```typescript
547
+ const hi = getDailyPanchang(date, loc, { timezone: 330, language: 'hi' })!;
548
+
549
+ console.log(hi.tithis[0].name); // "कृष्ण चतुर्दशी"
550
+ console.log(hi.vara.name); // "मंगलवार"
551
+ console.log(hi.chandramasa.name); // "माघ"
552
+ console.log(hi.choghadiya.day[0].name); // "अमृत"
553
+
554
+ // englishName is always English on Vara / Tarabala / Chandra Balam
555
+ console.log(hi.vara.englishName); // "Tuesday"
555
556
  ```
556
557
 
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.
558
+ ## 17. Configuration
559
+
560
+ ```typescript
561
+ const r = getDailyPanchang(date, loc, {
562
+ timezone: 330, // number (UTC offset in min) or IANA string
563
+ ayanamsa: 'lahiri', // 'lahiri' | 'raman' | 'krishnamurti'
564
+ // | 'true-chitra' | 'thirukanitham'
565
+ language: 'en', // 'en' | 'hi'
566
+ masaSystem: 'purnimanta', // 'purnimanta' | 'amanta'
567
+ region: 'all', // 21 state slugs + 'nepal' + 'all'
568
+ computeEndTimes: true, // false ~5x speedup, names only
569
+ precision: 'standard', // 'standard' (15 iter) | 'high' (25 iter)
570
+ janmaRashi: undefined, // pass to add r.chandraBalam
571
+ janmaNakshatra: undefined, // pass to add r.tarabala
572
+ });
573
+ ```
574
+
575
+ **Timezone handling** `timezone` accepts either a number (UTC offset in minutes, e.g.
576
+ `330` for IST) or an IANA zone name (e.g. `'America/New_York'`). IANA strings need `Intl`,
577
+ which older Hermes versions don't fully support — pass a number on those targets. DST
578
+ resolves automatically for IANA zones via the reference date.
589
579
 
590
580
  ---
591
581
 
592
- ## Types
582
+ ## Types & Exports
593
583
 
594
584
  <details>
595
585
  <summary><strong>Core Types</strong> — GeoLocation, TimePeriod</summary>
@@ -615,7 +605,7 @@ interface TimePeriod {
615
605
  interface TithiInfo {
616
606
  index: number; // 0-29
617
607
  name: string; // e.g. "Shukla Pratipada"
618
- paksha: string; // "Shukla"/"Krishna" (en), "शुक्ल"/"कृष्ण" (sa/hi)
608
+ paksha: string; // "Shukla"/"Krishna" (en), "शुक्ल"/"कृष्ण" (hi)
619
609
  number: number; // 1-15 within the paksha
620
610
  completionPercentage: number;
621
611
  endTime: Date | null;
@@ -632,10 +622,10 @@ interface NakshatraInfo {
632
622
 
633
623
  interface DailyTithiInfo extends TithiInfo {
634
624
  startTime: Date | null; // null when isActiveAtSunrise is true
635
- isActiveAtSunrise: boolean; // true = present at sunrise; false = started mid-day
625
+ isActiveAtSunrise: boolean;
636
626
  }
637
627
 
638
- // DailyNakshatraInfo, DailyYogaInfo, DailyKaranaInfo follow the same pattern
628
+ // DailyNakshatraInfo, DailyYogaInfo, DailyKaranaInfo follow the same pattern.
639
629
 
640
630
  interface VaraInfo {
641
631
  index: number; // 0 = Sunday ... 6 = Saturday
@@ -652,12 +642,12 @@ interface KaranaInfo {
652
642
  type: 'fixed' | 'movable';
653
643
  }
654
644
 
655
- // Note: endTime and startTime are null when computeEndTimes: false.
645
+ // endTime / startTime are null when computeEndTimes: false.
656
646
  ```
657
647
  </details>
658
648
 
659
649
  <details>
660
- <summary><strong>Lunar Calendar</strong> — ChandraMasaInfo, SamvatInfo, MasaInfo</summary>
650
+ <summary><strong>Lunar Calendar</strong> — ChandraMasaInfo, SamvatInfo, MasaInfo, RashiInfo</summary>
661
651
 
662
652
  ```typescript
663
653
  interface ChandraMasaInfo {
@@ -665,10 +655,10 @@ interface ChandraMasaInfo {
665
655
  name: string; // follows masaSystem option
666
656
  isAdhika: boolean; // true = leap/intercalary month
667
657
  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
658
+ amantaIndex: number;
659
+ amantaName: string;
660
+ purnimantaIndex: number;
661
+ purnimantaName: string;
672
662
  }
673
663
 
674
664
  interface SamvatInfo {
@@ -689,7 +679,7 @@ interface RashiInfo {
689
679
  </details>
690
680
 
691
681
  <details>
692
- <summary><strong>Time Slots</strong> — Choghadiya, Gowri Panchangam, Hora</summary>
682
+ <summary><strong>Time Slots</strong> — Choghadiya, Gowri, Hora, Do Ghati</summary>
693
683
 
694
684
  ```typescript
695
685
  type ChoghadiyaQuality = 'auspicious' | 'inauspicious' | 'neutral';
@@ -698,34 +688,29 @@ interface ChoghadiyaSlot extends TimePeriod {
698
688
  index: number;
699
689
  name: string; // e.g. "Amrit", "Kaal" (localized)
700
690
  quality: ChoghadiyaQuality;
701
- qualityName: string; // localized: "Auspicious", "शुभ", "शुभम्"
691
+ qualityName: string; // localized: "Auspicious", "शुभ"
702
692
  }
703
693
 
704
694
  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;
695
+ day: ChoghadiyaSlot[]; // 8 slots (sunrise -> sunset)
696
+ night: ChoghadiyaSlot[]; // 8 slots (sunset -> next sunrise)
714
697
  }
715
698
 
716
- interface GowriInfo {
717
- day: GowriSlot[]; // 8 slots (sunrise -> sunset)
718
- night: GowriSlot[]; // 8 slots (sunset -> next sunrise)
719
- }
699
+ // GowriSlot / GowriInfo mirror Choghadiya.
720
700
 
721
701
  interface HoraSlot extends TimePeriod {
722
- planet: string; // e.g. "Sun", "Venus", "Mercury"
702
+ planet: string; // "Sun", "Venus", "Mercury", ...
723
703
  planetIndex: number; // 0-6 in Chaldean order
724
704
  }
725
705
 
726
706
  interface HoraInfo {
727
- day: HoraSlot[]; // 12 slots (sunrise -> sunset)
728
- night: HoraSlot[]; // 12 slots (sunset -> next sunrise)
707
+ day: HoraSlot[]; // 12 slots (sunrise -> sunset)
708
+ night: HoraSlot[]; // 12 slots (sunset -> next sunrise)
709
+ }
710
+
711
+ interface DoGhatiInfo {
712
+ day: DoGhatiSlot[]; // 15 ~48-min deity-keyed slots
713
+ night: DoGhatiSlot[]; // 15 ~48-min deity-keyed slots
729
714
  }
730
715
  ```
731
716
  </details>
@@ -735,37 +720,28 @@ interface HoraInfo {
735
720
 
736
721
  ```typescript
737
722
  interface SpecialYogaInfo {
738
- name: string; // e.g. "Guru Pushya Yoga", "Dwipushkar Yoga"
723
+ name: string;
739
724
  type:
740
725
  | '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}
726
+ | 'dwipushkar' // Bhadra-tithi + vara + nakshatra {Mrig, Chitra, Dhan} — doubled
727
+ | 'tripushkar' // same Bhadra rules + nakshatra ∈ {Krit, Punar, U.Phal, Vish, U.Ash, P.Bhad} — tripled
728
+ | 'jwalamukhi' // inauspicious tithi × nakshatra (Muhurta-chintamani 6.32)
729
+ | 'aadal' // auspiciousMoon-from-Sun nakshatra distance
730
+ | 'vidaal' // inauspicious — Moon-from-Sun nakshatra distance
731
+ | 'ravi'; // auspicious — Moon-from-Sun nakshatra distance (27-scheme)
748
732
  }
749
733
 
750
734
  interface FestivalInfo {
751
- name: string; // e.g. "Diwali", "Putrada Ekadashi", "Som Pradosh"
735
+ name: string;
752
736
  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
737
+ | 'major' | 'minor'
738
+ | 'ekadashi' | 'smarta_ekadashi' | 'vaishnava_ekadashi'
739
+ | 'pradosha' | 'sankranti' | 'eclipse';
761
740
  description?: string;
762
741
  /** Smarta-only: when Ekadashi is Dashami-viddha, the Dwadashi fast date. */
763
742
  deferralDate?: Date;
764
743
  }
765
744
 
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
745
  type FestivalRegion =
770
746
  | 'all' // default — emits every regional variant
771
747
  // South
@@ -780,21 +756,19 @@ type FestivalRegion =
780
756
  // Neighbour
781
757
  | 'nepal';
782
758
 
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.
759
+ // Pre-v2.1 identifiers accepted with a one-shot deprecation warning. Removed in v3.
785
760
  // 'tamil' → 'tamil-nadu'
786
761
  // 'bengal' → 'west-bengal'
787
- // 'north-india' → 'all' (Makar Sankranti is pan-Indian; use state
788
- // slugs for Lohri / Govardhan / Bhai Dooj)
762
+ // 'north-india' → 'all'
789
763
  type LegacyFestivalRegion = 'tamil' | 'bengal' | 'north-india';
790
764
  ```
791
765
 
792
- **Region-scoped festivals** (non-exhaustive — see `src/core/festivals.ts`):
766
+ **Region-scoped festivals** (non-exhaustive):
793
767
 
794
768
  | Region | Festival names (keys) |
795
769
  |---|---|
796
770
  | `tamil-nadu` | pongal, puthandu, varamahalakshmi |
797
- | `kerala` | vishu, ayyappa_makara_jyothi, onam *(solar-nakshatra)* |
771
+ | `kerala` | vishu, ayyappa_makara_jyothi, onam |
798
772
  | `karnataka` | karaga, varamahalakshmi |
799
773
  | `andhra-pradesh` | varamahalakshmi |
800
774
  | `telangana` | bonalu, varamahalakshmi, bathukamma_start, bathukamma_saddula |
@@ -827,9 +801,9 @@ interface EclipseInfo {
827
801
  start: Date; // UTC — observable phase begins
828
802
  peak: Date; // UTC — greatest eclipse
829
803
  end: Date; // UTC — observable phase ends
830
- visibleFromLocation: boolean; // body above horizon at peak for observer
804
+ visibleFromLocation: boolean;
831
805
  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
806
+ sutakStart: Date; // 12 h before solar / 9 h before lunar
833
807
  sutakEnd: Date; // coincides with eclipse end (moksha)
834
808
  description: string;
835
809
  }
@@ -843,7 +817,7 @@ interface EclipseInfo {
843
817
  interface BhadraInfo {
844
818
  start: Date;
845
819
  end: Date;
846
- /** Loka: 'earth' = malefic for all work; 'heaven' / 'paatal' = non-terrestrial, milder. */
820
+ /** 'earth' = malefic for all work; 'heaven' / 'paatal' = non-terrestrial, milder. */
847
821
  location: 'earth' | 'heaven' | 'paatal';
848
822
  /** True when Bhadra is active at some point during the Hindu day window. */
849
823
  isActive: boolean;
@@ -852,7 +826,7 @@ interface BhadraInfo {
852
826
  </details>
853
827
 
854
828
  <details>
855
- <summary><strong>Jyotish (Vedic Astrology)</strong> — Graha positions, Vimshottari Dasha</summary>
829
+ <summary><strong>Jyotish</strong> — Graha positions, Vimshottari Dasha, Chandra Balam, Tarabala</summary>
856
830
 
857
831
  ```typescript
858
832
  type GrahaName = 'Sun' | 'Moon' | 'Mars' | 'Mercury' | 'Jupiter'
@@ -861,9 +835,9 @@ type GrahaName = 'Sun' | 'Moon' | 'Mars' | 'Mercury' | 'Jupiter'
861
835
  interface GrahaPosition {
862
836
  planet: GrahaName;
863
837
  siderealLongitude: number; // degrees [0, 360)
864
- rashi: RashiInfo; // zodiac sign
865
- degreeInRashi: number; // degrees within sign [0, 30)
866
- nakshatra: NakshatraInfo; // nakshatra + pada + completion %
838
+ rashi: RashiInfo;
839
+ degreeInRashi: number; // [0, 30)
840
+ nakshatra: NakshatraInfo;
867
841
  isRetrograde: boolean; // always false for Sun/Moon; always true for Rahu/Ketu
868
842
  }
869
843
 
@@ -876,24 +850,13 @@ interface PlanetaryPositions {
876
850
  type DashaLord = 'Ketu' | 'Venus' | 'Sun' | 'Moon' | 'Mars'
877
851
  | 'Rahu' | 'Jupiter' | 'Saturn' | 'Mercury';
878
852
 
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
-
853
+ interface AntarDasha { lord: DashaLord; startDate: Date; endDate: Date; }
854
+ interface MahaDasha { lord: DashaLord; startDate: Date; endDate: Date;
855
+ years: number; antarDashas: AntarDasha[]; }
893
856
  interface VimshottariDashaResult {
894
857
  currentMahaDashaLord: DashaLord;
895
858
  currentIndex: number;
896
- mahaDashas: MahaDasha[]; // 9-entry sequence starting from birth
859
+ mahaDashas: MahaDasha[]; // 9-entry sequence starting from birth
897
860
  }
898
861
 
899
862
  interface ChandraBalamInfo {
@@ -904,23 +867,54 @@ interface ChandraBalamInfo {
904
867
  }
905
868
 
906
869
  interface TarabalaInfo {
907
- taraIndex: number; // 0..8 — position in the 9-tara cycle from janma nakshatra
870
+ taraIndex: number; // 0..8 in the 9-tara cycle from janma nakshatra
908
871
  englishName: string; // "Janma" | "Sampat" | "Vipat" | "Kshema" | "Pratyari"
909
872
  // | "Sadhaka" | "Vadha" | "Mitra" | "Ati-Mitra"
910
- name: string; // localized
873
+ name: string;
911
874
  quality: 'auspicious' | 'inauspicious';
912
- // 'inauspicious' for Vipat (2) / Pratyari (4) / Vadha (6); rest auspicious
913
875
  }
914
876
  ```
915
877
  </details>
916
878
 
879
+ ### Full export list
880
+
881
+ ```typescript
882
+ // Primary entry points
883
+ getDailyPanchang, getInstantPanchang
884
+
885
+ // Astronomy
886
+ getSunrise, getSunset, getMoonrise, getMoonset
887
+ getSiderealSunLongitude, getSiderealMoonLongitude, getAyanamsa
888
+
889
+ // Inauspicious / Muhurta
890
+ computeRahuKalam, computeGulikaKalam, computeYamaganda
891
+ computeVarjyam, computeGandaMula, computeAnandadiYoga
892
+ computePanchakaRahita, computeDoGhati, computeGowriPanchangam
893
+ computeAbhijitMuhurta, computeBrahmaMuhurta, computeVijayaMuhurta
894
+ computeGodhuliMuhurta, computeNishitaMuhurta, computeAmritKala
895
+ computeMadhyahna, computePratahSandhya, computeSayahnaSandhya
896
+
897
+ // Eclipses
898
+ getUpcomingSolarEclipse, getUpcomingLunarEclipse, getEclipseDuringDay
899
+
900
+ // Jyotish
901
+ computePlanetaryPositions, GRAHA_ABBR
902
+ computeVimshottariDasha, computeVimshottariDashaFromBirth, computeVimshottariPratyantar
903
+ computeChandraBalam, computeTarabala
904
+ computeLagna, computeBhava, computeRashiChart, computeNavamsa
905
+ computeAshtakoot, computeMangalDosha, computeSadeSati, computeDignity
906
+
907
+ // Errors
908
+ PanchangError
909
+ ```
910
+
917
911
  ---
918
912
 
919
913
  ## React Native / Hermes
920
914
 
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.
915
+ Works with Expo and bare React Native (Hermes engine). Pass `timezone` as a **number**
916
+ IANA timezone strings (`'Asia/Kolkata'`) require `Intl`, which older Hermes versions don't
917
+ fully support.
924
918
 
925
919
  **Two-pass rendering** for smooth UI:
926
920
 
@@ -946,42 +940,47 @@ InteractionManager.runAfterInteractions(() => {
946
940
 
947
941
  ## Accuracy
948
942
 
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`).
943
+ 6,912 tests passing across 74 files, including fixtures cross-verified against reference
944
+ panchang calculations spanning 2025–2026 across 10 Indian cities, plus New York, London,
945
+ Sydney, Dubai, and Singapore (diaspora fixtures cover DST transitions on
946
+ `America/New_York`).
953
947
 
954
948
  | Element | Accuracy | Validation |
955
949
  |---------|----------|------------|
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 |
950
+ | Sunrise / Sunset | 29 s observed vs reference minute-midpoint (±45 s tolerance) | 16 assertions |
951
+ | Moonrise / Moonset | Meeus apparent-upper-limb (refraction + parallax); ~3–5 min vs simpler-horizon authorities is expected | Strict fixtures |
958
952
  | 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 |
953
+ | Tithi / Nakshatra / Yoga / Karana end-times | ±3 min tolerance, max 2.01 min observed | 20 assertions |
960
954
  | 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 |
955
+ | Planetary positions (Sun–Saturn) | ±0.02° vs reference sidereal | Fixtures |
956
+ | Planetary positions (Rahu/Ketu, mean node) | ≤0.5° typical; ±2° tolerance | Fixtures |
957
+ | Planetary positions (Rahu/Ketu, true node) | ≤0.6° typical (Meeus periodic correction) | Fixtures |
964
958
  | Rashi / Nakshatra / Retrograde flag | Exact match vs reference | Fixtures |
965
959
  | Festival dates | 12 cross-verified festivals (2025–2026) — see caveats below | Fixtures |
966
960
  | 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 |
961
+ | Madhyahna midpoint, Anandadi Yoga, Ganda Mula active flag | Exact match across 50 reference fixtures | Cross-verify suite |
962
+ | Pratah / Sayahna Sandhya start + end | ±2 min across all 50 fixtures | Cross-verify suite |
963
+ | Varjyam start + end | ±2 min on every emit (transition days return `null` by design) | Cross-verify suite |
964
+ | Lagna sidereal longitude | Cross-checked against Jagannath Hora reference charts | Birth-chart fixtures |
971
965
  | D1 (Rashi) & D9 (Navamsa) house placements | Exact match vs reference for 9-graha placement | Birth-chart fixtures |
972
966
  | Ashtakoot Guna Milan total score | ±1 point per pair across 30+ matched pairs | Match fixtures |
973
967
  | Sade Sati arc start / end | ±1–2 days vs authoritative ephemerides | Saturn-transit fixtures |
974
968
 
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.
969
+ **Detection sourcing notes.** **Aadal / Vidaal** follow the classical Moon-from-Sun
970
+ nakshatra-distance rule (AstroShastra, HoraSarvam, Ernst Wilhelm), NOT the popular
971
+ Tamil-Vakya weekday rule used by some online panchangs — output may differ from sites that
972
+ use the weekday rule. **Varjyam** emits the sunrise-anchored nakshatra's window only —
973
+ printed panchangs may show a second window on nakshatra-transition days. **Do Ghati
974
+ Muhurta** does not rotate by weekday: the same 30-name deity-keyed sequence applies every
975
+ day, verified against multiple reference sources for distinct weekdays.
976
976
 
977
977
  ### Festival Detection — Documented Tradeoff
978
978
 
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.
979
+ The library uses **tithi-at-sunrise** to resolve a festival to a calendar day. Some
980
+ traditional panchang authorities apply other classical rules (tithi-at-midnight,
981
+ madhyahna-vyapini, kshaya-tithi handling) for certain festivals; where those rules pick a
982
+ different day, our output can drift ±1 day. This is a rule-choice tradeoff, not a
983
+ computation bug.
985
984
 
986
985
  | Alternative classical rule | Festivals affected |
987
986
  |----------------------------|--------------------|
@@ -989,11 +988,11 @@ documented and deliberately surfaced rather than hidden.
989
988
  | Madhyahna-vyapini (tithi overlapping noon) | Ganesh Chaturthi on edge years, Akshaya Tritiya 2026 |
990
989
  | Kshaya-tithi handling (tithi never at sunrise) | Ugadi 2026-03-19 (Pratipada is Kshaya) |
991
990
 
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.
991
+ If strict parity with a specific panchang authority matters for your use case, cross-check
992
+ the above festival set for the target year. Everything else — Holi, Ugadi (non-Kshaya
993
+ years), Rama Navami, Raksha Bandhan, Ganesh Chaturthi (normal years), Navaratri,
994
+ Dussehra, Karva Chauth, Hanuman Jayanti matches the canonical date across 2025 and 2026
995
+ fixtures.
997
996
 
998
997
  ---
999
998
 
@@ -1004,6 +1003,9 @@ Hanuman Jayanti — matches the canonical date across 2025 and 2026 fixtures.
1004
1003
  | Names-only (`computeEndTimes: false`) | ~0.1 ms | <100 ms |
1005
1004
  | Full with end-times | ~0.5 ms | <500 ms |
1006
1005
 
1006
+ Birth-chart helpers are independent — calling them does not add work to
1007
+ `getDailyPanchang`.
1008
+
1007
1009
  ---
1008
1010
 
1009
1011
  ## Error Handling
@@ -1021,15 +1023,15 @@ try {
1021
1023
  }
1022
1024
  ```
1023
1025
 
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`.
1026
+ Error codes: `INVALID_DATE`, `INVALID_LATITUDE`, `INVALID_LONGITUDE`, `INVALID_ELEVATION`,
1027
+ `INVALID_TIMEZONE`, `INVALID_AYANAMSA`, `TIMEZONE_RESOLUTION_FAILED`, `NO_SUNRISE`,
1028
+ `NO_SUNSET`, `SEARCH_DIVERGED`, `CIRCUMPOLAR` (Placidus-KP houses above ±66.5°).
1027
1029
 
1028
1030
  **Polar locations (no sunrise / no sunset):** `getDailyPanchang` and `getInstantPanchang`
1029
1031
  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).
1032
+ computed. The low-level `getSunrise` / `getSunset` primitives still throw
1033
+ `PanchangError(NO_SUNRISE)` / `PanchangError(NO_SUNSET)` for direct callers who need the
1034
+ precise reason. `getMoonrise` / `getMoonset` return `null` (normal for the Moon).
1033
1035
 
1034
1036
  ---
1035
1037
 
@@ -1045,13 +1047,10 @@ the precise reason. `getMoonrise` / `getMoonset` return `null` (normal for the M
1045
1047
 
1046
1048
  ---
1047
1049
 
1048
- ## Used By
1049
-
1050
- - [dharmagya.app](https://dharmagya.app) — Daily Panchang and Hindu calendar
1051
-
1052
1050
  ## Acknowledgements
1053
1051
 
1054
- [astronomy-engine](https://github.com/cosinekitty/astronomy) by Don Cross — the sole runtime dependency. MIT licensed.
1052
+ [astronomy-engine](https://github.com/cosinekitty/astronomy) by Don Cross — the sole
1053
+ runtime dependency. MIT licensed.
1055
1054
 
1056
1055
  ## License
1057
1056