panchang-ts 0.6.0 → 0.7.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 +242 -200
- package/dist/index.cjs +44 -25
- package/dist/index.d.cts +20 -4
- package/dist/index.d.ts +20 -4
- package/dist/index.js +44 -25
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,31 +1,32 @@
|
|
|
1
1
|
# panchang-ts
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/panchang-ts)
|
|
4
|
+
|
|
3
5
|
Pure TypeScript Hindu Panchang (almanac) calculations. Zero native dependencies.
|
|
4
6
|
Works offline in React Native (Hermes), Node.js, and browsers.
|
|
5
7
|
|
|
6
|
-
|
|
8
|
+
**Fast** (~0.1 ms names-only, ~0.5 ms full) | **Typed** (full TypeScript types) | **Offline** (pure JS math, no network)
|
|
9
|
+
|
|
10
|
+
---
|
|
7
11
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
- **React Native compatible:** Pure JS math, no native modules, tested on Hermes
|
|
27
|
-
- **Fast:** ~0.1 ms names-only on Node.js; <100 ms on budget Android (Hermes)
|
|
28
|
-
- **Typed:** Full TypeScript types for every result and option
|
|
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
|
+
- [Options](#options)
|
|
21
|
+
- [Low-level Utilities](#low-level-utilities)
|
|
22
|
+
- [Types](#types)
|
|
23
|
+
- [React Native / Hermes](#react-native--hermes)
|
|
24
|
+
- [Accuracy](#accuracy)
|
|
25
|
+
- [Performance](#performance)
|
|
26
|
+
- [Error Handling](#error-handling)
|
|
27
|
+
- [Compatibility](#compatibility)
|
|
28
|
+
|
|
29
|
+
---
|
|
29
30
|
|
|
30
31
|
## Install
|
|
31
32
|
|
|
@@ -53,10 +54,10 @@ console.log(result.tithis[0].name); // "Krishna Chaturdashi"
|
|
|
53
54
|
console.log(result.nakshatras[0].name); // "Mrigashira"
|
|
54
55
|
console.log(result.vara.name); // "Mangalavara"
|
|
55
56
|
|
|
56
|
-
// Lunar calendar
|
|
57
|
-
console.log(result.chandramasa.name); // "
|
|
57
|
+
// Lunar calendar (Purnimanta by default)
|
|
58
|
+
console.log(result.chandramasa.name); // "Magha"
|
|
59
|
+
console.log(result.chandramasa.amantaName); // "Pausha" (South Indian)
|
|
58
60
|
console.log(result.samvat.vikramSamvat); // 2081
|
|
59
|
-
console.log(result.samvat.shakaSamvat); // 1946
|
|
60
61
|
|
|
61
62
|
// Zodiac
|
|
62
63
|
console.log(result.chandraRashi.name); // "Mithuna" (Moon in Gemini)
|
|
@@ -66,45 +67,35 @@ console.log(result.suryaNakshatra.name); // "Uttara Ashadha"
|
|
|
66
67
|
console.log(result.sunrise); // Date (read via getUTC*)
|
|
67
68
|
console.log(result.moonrise); // Date | null
|
|
68
69
|
|
|
69
|
-
// Muhurta
|
|
70
|
+
// Muhurta & inauspicious periods
|
|
70
71
|
console.log(result.brahmaMuhurta); // { start: Date, end: Date }
|
|
71
72
|
console.log(result.rahuKalam); // { start: Date, end: Date }
|
|
72
73
|
|
|
73
74
|
// Choghadiya — 8 daytime slots
|
|
74
75
|
result.choghadiya.day.forEach(slot => {
|
|
75
|
-
console.log(slot.name, slot.
|
|
76
|
+
console.log(slot.name, slot.qualityName); // "Amrit", "Auspicious"
|
|
76
77
|
});
|
|
77
78
|
|
|
78
|
-
//
|
|
79
|
-
|
|
79
|
+
// Gowri Panchangam — 8 daytime slots
|
|
80
|
+
result.gowriPanchangam.day.forEach(slot => {
|
|
81
|
+
console.log(slot.name, slot.qualityName); // "Amrit", "Auspicious"
|
|
82
|
+
});
|
|
80
83
|
|
|
81
84
|
// Special Yogas active today
|
|
82
85
|
result.specialYogas.forEach(yoga => {
|
|
83
86
|
console.log(yoga.name, yoga.type); // "Guru Pushya Yoga", "guru_pushya"
|
|
84
87
|
});
|
|
85
88
|
|
|
86
|
-
// Dur Muhurta — two inauspicious windows
|
|
87
|
-
const [dm1, dm2] = result.durMuhurta;
|
|
88
|
-
console.log(fmt(dm1.start), '-', fmt(dm1.end)); // e.g. "11:36 - 12:24"
|
|
89
|
-
console.log(fmt(dm2.start), '-', fmt(dm2.end));
|
|
90
|
-
|
|
91
89
|
// Festivals today
|
|
92
90
|
result.festivals.forEach(f => {
|
|
93
|
-
console.log(f.name, f.type); // "
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
// Gowri Panchangam — 8 daytime slots
|
|
97
|
-
result.gowriPanchangam.day.forEach(slot => {
|
|
98
|
-
console.log(slot.name, slot.quality); // "Amrit", "auspicious"
|
|
91
|
+
console.log(f.name, f.type); // "Makar Sankranti", "major"
|
|
99
92
|
});
|
|
100
|
-
|
|
101
|
-
|
|
102
93
|
```
|
|
103
94
|
|
|
104
|
-
|
|
95
|
+
### Reading Output Times
|
|
105
96
|
|
|
106
97
|
All `Date` objects in the result are **offset-adjusted** to the requested timezone.
|
|
107
|
-
|
|
98
|
+
Always read time components via `getUTC*` methods:
|
|
108
99
|
|
|
109
100
|
```typescript
|
|
110
101
|
const sunrise = result.sunrise;
|
|
@@ -125,6 +116,64 @@ Do **not** use `.getHours()` — it uses your system timezone, which may differ.
|
|
|
125
116
|
`moonrise` and `moonset` can be `null` — the Moon occasionally does not rise or set
|
|
126
117
|
on a given calendar day, which is normal.
|
|
127
118
|
|
|
119
|
+
### Language & Masa System
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
// Sanskrit names (Devanagari)
|
|
123
|
+
const sa = getDailyPanchang(date, location, {
|
|
124
|
+
timezone: 330,
|
|
125
|
+
language: 'sa',
|
|
126
|
+
});
|
|
127
|
+
console.log(sa.tithis[0].name); // "कृष्ण चतुर्दशी"
|
|
128
|
+
console.log(sa.vara.name); // "मङ्गलवारः"
|
|
129
|
+
|
|
130
|
+
// Hindi names
|
|
131
|
+
const hi = getDailyPanchang(date, location, {
|
|
132
|
+
timezone: 330,
|
|
133
|
+
language: 'hi',
|
|
134
|
+
});
|
|
135
|
+
console.log(hi.tithis[0].name); // "कृष्ण चतुर्दशी"
|
|
136
|
+
|
|
137
|
+
// Amanta (South Indian) masa system
|
|
138
|
+
const amanta = getDailyPanchang(date, location, {
|
|
139
|
+
timezone: 330,
|
|
140
|
+
masaSystem: 'amanta',
|
|
141
|
+
});
|
|
142
|
+
console.log(amanta.chandramasa.name); // Amanta month name
|
|
143
|
+
console.log(amanta.chandramasa.system); // "amanta"
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Features
|
|
149
|
+
|
|
150
|
+
### Pancha Anga (5 Limbs)
|
|
151
|
+
Tithi, Nakshatra, Yoga, Karana, Vara — with transition times throughout the day.
|
|
152
|
+
|
|
153
|
+
### Lunar Calendar
|
|
154
|
+
Chandra Masa with Adhika (leap month) detection, both **Purnimanta** (North Indian, default) and **Amanta** (South Indian) systems, Vikram Samvat, Shaka Samvat.
|
|
155
|
+
|
|
156
|
+
### Muhurta & Auspicious Timing
|
|
157
|
+
Brahma Muhurta, Abhijit Muhurta, Choghadiya (16 slots), Gowri Panchangam / Nalla Neram (16 slots), Hora (24 planetary hours), Dur Muhurta (2 inauspicious windows).
|
|
158
|
+
|
|
159
|
+
### Inauspicious Periods
|
|
160
|
+
Rahu Kalam, Gulika Kalam, Yamaganda, Panchaka detection.
|
|
161
|
+
|
|
162
|
+
### Special Yogas & Festivals
|
|
163
|
+
Amrit Siddhi, Sarvartha Siddhi, Ravi Pushya, Guru Pushya yoga detection. 24 major pan-Indian festivals, recurring Ekadashi & Pradosha Vrata, Sankranti — Adhika months auto-skipped.
|
|
164
|
+
|
|
165
|
+
### Jyotish (Vedic Astrology)
|
|
166
|
+
All 9 graha positions (geocentric, sidereal) with rashi, nakshatra, pada, and retrograde status. Vimshottari Dasha with Antardasha breakdown.
|
|
167
|
+
|
|
168
|
+
### Astronomy
|
|
169
|
+
Sunrise, Sunset, Moonrise, Moonset, Chandra Rashi (Moon sign), Surya Nakshatra.
|
|
170
|
+
|
|
171
|
+
### Localization
|
|
172
|
+
3 languages: **English**, **Sanskrit** (Devanagari), **Hindi**. All returned display strings respect the `language` option.
|
|
173
|
+
|
|
174
|
+
### Configuration
|
|
175
|
+
3 ayanamsa systems (Lahiri, B.V. Raman, KP), 2 masa systems (Purnimanta, Amanta), adjustable precision, optional fast mode (`computeEndTimes: false` for ~5x speedup).
|
|
176
|
+
|
|
128
177
|
---
|
|
129
178
|
|
|
130
179
|
## API Reference
|
|
@@ -155,34 +204,33 @@ const result = getDailyPanchang(
|
|
|
155
204
|
| `nextSunrise` | `Date` | Following day's sunrise (offset-adjusted) |
|
|
156
205
|
| `dayDurationMinutes` | `number` | Length of daytime in minutes |
|
|
157
206
|
| `nightDurationMinutes` | `number` | Length of night in minutes |
|
|
158
|
-
| `tithis` | `DailyTithiInfo[]` | Tithis active during the day (usually 1
|
|
207
|
+
| `tithis` | `DailyTithiInfo[]` | Tithis active during the day (usually 1-2) |
|
|
159
208
|
| `nakshatras` | `DailyNakshatraInfo[]` | Nakshatras active during the day |
|
|
160
209
|
| `yogas` | `DailyYogaInfo[]` | Yogas active during the day |
|
|
161
|
-
| `karanas` | `DailyKaranaInfo[]` | Karanas active during the day (usually 2
|
|
210
|
+
| `karanas` | `DailyKaranaInfo[]` | Karanas active during the day (usually 2-4) |
|
|
162
211
|
| `vara` | `VaraInfo` | Weekday (Vara) |
|
|
163
212
|
| `rahuKalam` | `TimePeriod` | Rahu Kalam start/end |
|
|
164
213
|
| `gulikaKalam` | `TimePeriod` | Gulika Kalam start/end |
|
|
165
214
|
| `yamaganda` | `TimePeriod` | Yamaganda start/end |
|
|
166
215
|
| `abhijitMuhurta` | `TimePeriod` | Abhijit Muhurta start/end |
|
|
167
|
-
| `brahmaMuhurta` | `TimePeriod` | Brahma Muhurta — two muhurtas
|
|
216
|
+
| `brahmaMuhurta` | `TimePeriod` | Brahma Muhurta — two muhurtas before sunrise |
|
|
168
217
|
| `masa` | `MasaInfo` | Solar month (Saura Masa) |
|
|
169
218
|
| `chandramasa` | `ChandraMasaInfo` | Lunar month + Adhika (leap) flag |
|
|
170
219
|
| `samvat` | `SamvatInfo` | Vikram Samvat and Shaka Samvat year numbers |
|
|
171
220
|
| `chandraRashi` | `RashiInfo` | Moon's zodiac sign (changes every ~2.5 days) |
|
|
172
|
-
| `suryaNakshatra` | `RashiInfo` | Sun's nakshatra (changes every ~13
|
|
173
|
-
| `choghadiya` | `ChoghadiyaInfo` | 8 day
|
|
174
|
-
| `gowriPanchangam` | `GowriInfo` | 8 day + 8 night Gowri Nalla Neram slots
|
|
175
|
-
|
|
176
|
-
| `
|
|
177
|
-
| `
|
|
178
|
-
| `moonset` | `Date \| null` | Moonset (offset-adjusted); `null` if none that day |
|
|
221
|
+
| `suryaNakshatra` | `RashiInfo` | Sun's nakshatra (changes every ~13-14 days) |
|
|
222
|
+
| `choghadiya` | `ChoghadiyaInfo` | 8 day + 8 night slots, each named and rated |
|
|
223
|
+
| `gowriPanchangam` | `GowriInfo` | 8 day + 8 night Gowri Nalla Neram slots |
|
|
224
|
+
| `hora` | `HoraInfo` | 12 day + 12 night horas, each with ruling planet |
|
|
225
|
+
| `moonrise` | `Date \| null` | Moonrise; `null` if none that day |
|
|
226
|
+
| `moonset` | `Date \| null` | Moonset; `null` if none that day |
|
|
179
227
|
| `panchaka` | `boolean` | `true` when Moon is in last 5 nakshatras |
|
|
180
|
-
| `specialYogas` | `SpecialYogaInfo[]` | Auspicious yogas active today
|
|
228
|
+
| `specialYogas` | `SpecialYogaInfo[]` | Auspicious yogas active today |
|
|
181
229
|
| `durMuhurta` | `[TimePeriod, TimePeriod]` | Two inauspicious ~48-min windows |
|
|
182
|
-
| `festivals` | `FestivalInfo[]` | Festivals / observances today
|
|
230
|
+
| `festivals` | `FestivalInfo[]` | Festivals / observances today |
|
|
183
231
|
| `ayanamsa` | `number` | Ayanamsa in degrees at sunrise |
|
|
184
|
-
| `siderealSunAtSunrise` | `number` | Sun sidereal longitude at sunrise (
|
|
185
|
-
| `siderealMoonAtSunrise` | `number` | Moon sidereal longitude at sunrise (
|
|
232
|
+
| `siderealSunAtSunrise` | `number` | Sun sidereal longitude at sunrise (degrees) |
|
|
233
|
+
| `siderealMoonAtSunrise` | `number` | Moon sidereal longitude at sunrise (degrees) |
|
|
186
234
|
|
|
187
235
|
---
|
|
188
236
|
|
|
@@ -201,7 +249,7 @@ const result = getInstantPanchang(
|
|
|
201
249
|
|
|
202
250
|
console.log(result.tithi.name); // "कृष्ण चतुर्दशी"
|
|
203
251
|
console.log(result.nakshatra.name); // "मृगशिरा"
|
|
204
|
-
console.log(result.chandramasa.name); // "
|
|
252
|
+
console.log(result.chandramasa.name); // "माघ"
|
|
205
253
|
console.log(result.chandraRashi.name); // "मिथुन"
|
|
206
254
|
console.log(result.samvat.vikramSamvat); // 2081
|
|
207
255
|
console.log(result.panchaka); // false
|
|
@@ -223,11 +271,11 @@ console.log(result.panchaka); // false
|
|
|
223
271
|
| `chandraRashi` | `RashiInfo` | Moon's zodiac sign |
|
|
224
272
|
| `suryaNakshatra` | `RashiInfo` | Sun's nakshatra |
|
|
225
273
|
| `panchaka` | `boolean` | `true` when Moon is in last 5 nakshatras |
|
|
226
|
-
| `specialYogas` | `SpecialYogaInfo[]` | Auspicious yogas at this moment
|
|
227
|
-
| `festivals` | `FestivalInfo[]` | Festivals / observances at this moment
|
|
274
|
+
| `specialYogas` | `SpecialYogaInfo[]` | Auspicious yogas at this moment |
|
|
275
|
+
| `festivals` | `FestivalInfo[]` | Festivals / observances at this moment |
|
|
228
276
|
| `ayanamsa` | `number` | Ayanamsa in degrees |
|
|
229
|
-
| `siderealSun` | `number` | Sun sidereal longitude (
|
|
230
|
-
| `siderealMoon` | `number` | Moon sidereal longitude (
|
|
277
|
+
| `siderealSun` | `number` | Sun sidereal longitude (degrees) |
|
|
278
|
+
| `siderealMoon` | `number` | Moon sidereal longitude (degrees) |
|
|
231
279
|
|
|
232
280
|
---
|
|
233
281
|
|
|
@@ -239,9 +287,10 @@ console.log(result.panchaka); // false
|
|
|
239
287
|
|--------|------|---------|-------------|
|
|
240
288
|
| `timezone` | `number \| string` | **required** | UTC offset in minutes (330 for IST). Use a number on Hermes — IANA strings require `Intl`. |
|
|
241
289
|
| `ayanamsa` | `'lahiri' \| 'raman' \| 'krishnamurti'` | `'lahiri'` | Ayanamsa system |
|
|
242
|
-
| `language` | `'en' \| 'sa' \| 'hi'` | `'en'` | Language for all element names
|
|
243
|
-
| `computeEndTimes` | `boolean` | `true` | Set `false` for ~
|
|
290
|
+
| `language` | `'en' \| 'sa' \| 'hi'` | `'en'` | Language for all element names. `'sa'` = classical Sanskrit Devanagari, `'hi'` = modern Hindi Devanagari. |
|
|
291
|
+
| `computeEndTimes` | `boolean` | `true` | Set `false` for ~5x faster, names-only output |
|
|
244
292
|
| `precision` | `'standard' \| 'high'` | `'standard'` | Binary-search iterations (15 vs 25). High precision is rarely needed. |
|
|
293
|
+
| `masaSystem` | `'purnimanta' \| 'amanta'` | `'purnimanta'` | Lunar month naming system. Purnimanta (North Indian) or Amanta (South Indian). |
|
|
245
294
|
|
|
246
295
|
**`InstantPanchangOptions`** (optional for `getInstantPanchang`): same as above but without `timezone`.
|
|
247
296
|
|
|
@@ -249,7 +298,7 @@ console.log(result.panchaka); // false
|
|
|
249
298
|
|
|
250
299
|
### Low-level Utilities
|
|
251
300
|
|
|
252
|
-
|
|
301
|
+
Exported for advanced use cases — building custom tools, visualizations, or Jyotish applications.
|
|
253
302
|
|
|
254
303
|
```typescript
|
|
255
304
|
import {
|
|
@@ -280,39 +329,38 @@ const sunLon = getSiderealSunLongitude(new Date(), 'lahiri');
|
|
|
280
329
|
// Ayanamsa
|
|
281
330
|
const ayan = getAyanamsa(new Date(), 'lahiri'); // e.g. 24.10
|
|
282
331
|
|
|
283
|
-
// Inauspicious periods (varaIndex: 0=Sun
|
|
284
|
-
const rahu
|
|
332
|
+
// Inauspicious periods (varaIndex: 0=Sun ... 6=Sat)
|
|
333
|
+
const rahu = computeRahuKalam(sunrise, sunset, varaIndex); // { start, end }
|
|
285
334
|
const gulika = computeGulikaKalam(sunrise, sunset, varaIndex);
|
|
286
|
-
const yama
|
|
335
|
+
const yama = computeYamaganda(sunrise, sunset, varaIndex);
|
|
287
336
|
|
|
288
337
|
// Muhurta
|
|
289
|
-
const abhijit
|
|
290
|
-
const brahma
|
|
291
|
-
|
|
338
|
+
const abhijit = computeAbhijitMuhurta(sunrise, sunset); // { start, end }
|
|
339
|
+
const brahma = computeBrahmaMuhurta(sunrise, sunset); // { start, end }
|
|
340
|
+
```
|
|
292
341
|
|
|
293
|
-
|
|
294
|
-
const gowri = computeGowriPanchangam(sunrise, sunset, nextSunrise, varaIndex,
|
|
295
|
-
(i) => ['Udyog','Amrit','Roga','Laabh','Shubh','Kaal','Dhan','Chal'][i]!,
|
|
296
|
-
);
|
|
297
|
-
// gowri.day → 8 GowriSlot (sunrise → sunset)
|
|
298
|
-
// gowri.night → 8 GowriSlot (sunset → next sunrise)
|
|
342
|
+
**Jyotish (Vedic Astrology):**
|
|
299
343
|
|
|
300
|
-
|
|
344
|
+
```typescript
|
|
345
|
+
// All 9 graha positions (sidereal)
|
|
301
346
|
const grahas = computePlanetaryPositions(birthDate, 'lahiri');
|
|
302
|
-
console.log(grahas.jupiter.rashi.name);
|
|
303
|
-
console.log(grahas.saturn.isRetrograde);
|
|
304
|
-
console.log(GRAHA_ABBR['Jupiter']);
|
|
347
|
+
console.log(grahas.jupiter.rashi.name); // "Dhanu"
|
|
348
|
+
console.log(grahas.saturn.isRetrograde); // true/false
|
|
349
|
+
console.log(GRAHA_ABBR['Jupiter']); // "Ju"
|
|
305
350
|
|
|
306
351
|
// Vimshottari Dasha — pass birth date and Moon's sidereal longitude
|
|
307
352
|
const moonLon = getSiderealMoonLongitude(birthDate, 'lahiri');
|
|
308
353
|
const dasha = computeVimshottariDasha(birthDate, moonLon);
|
|
309
|
-
console.log(dasha.currentMahaDashaLord);
|
|
310
|
-
console.log(dasha.mahaDashas[0]!.antarDashas[0]!.lord);
|
|
354
|
+
console.log(dasha.currentMahaDashaLord); // "Rahu"
|
|
355
|
+
console.log(dasha.mahaDashas[0]!.antarDashas[0]!.lord); // "Rahu"
|
|
311
356
|
```
|
|
312
357
|
|
|
313
358
|
---
|
|
314
359
|
|
|
315
|
-
|
|
360
|
+
## Types
|
|
361
|
+
|
|
362
|
+
<details>
|
|
363
|
+
<summary><strong>Core Types</strong> — GeoLocation, TimePeriod</summary>
|
|
316
364
|
|
|
317
365
|
```typescript
|
|
318
366
|
interface GeoLocation {
|
|
@@ -325,45 +373,70 @@ interface TimePeriod {
|
|
|
325
373
|
start: Date;
|
|
326
374
|
end: Date;
|
|
327
375
|
}
|
|
376
|
+
```
|
|
377
|
+
</details>
|
|
328
378
|
|
|
329
|
-
|
|
379
|
+
<details>
|
|
380
|
+
<summary><strong>Pancha Anga</strong> — TithiInfo, NakshatraInfo, YogaInfo, KaranaInfo, VaraInfo</summary>
|
|
330
381
|
|
|
382
|
+
```typescript
|
|
331
383
|
interface TithiInfo {
|
|
332
|
-
index: number; // 0
|
|
384
|
+
index: number; // 0-29
|
|
333
385
|
name: string; // e.g. "Shukla Pratipada"
|
|
334
|
-
paksha: string; // "Shukla"/"Krishna" (en), "शुक्ल"/"कृष्ण" (sa/hi)
|
|
335
|
-
number: number; // 1
|
|
386
|
+
paksha: string; // "Shukla"/"Krishna" (en), "शुक्ल"/"कृष्ण" (sa/hi)
|
|
387
|
+
number: number; // 1-15 within the paksha
|
|
336
388
|
completionPercentage: number;
|
|
337
389
|
endTime: Date | null;
|
|
338
390
|
}
|
|
339
391
|
|
|
340
392
|
interface NakshatraInfo {
|
|
341
|
-
index: number; // 0
|
|
393
|
+
index: number; // 0-26
|
|
342
394
|
name: string;
|
|
343
|
-
pada: number; // 1
|
|
395
|
+
pada: number; // 1-4
|
|
344
396
|
degreesInNakshatra: number;
|
|
345
397
|
completionPercentage: number;
|
|
346
398
|
endTime: Date | null;
|
|
347
399
|
}
|
|
348
400
|
|
|
349
401
|
interface DailyTithiInfo extends TithiInfo {
|
|
350
|
-
startTime: Date | null; // null when isActiveAtSunrise is true
|
|
351
|
-
isActiveAtSunrise: boolean; // true
|
|
402
|
+
startTime: Date | null; // null when isActiveAtSunrise is true
|
|
403
|
+
isActiveAtSunrise: boolean; // true = present at sunrise; false = started mid-day
|
|
352
404
|
}
|
|
353
405
|
|
|
354
406
|
// DailyNakshatraInfo, DailyYogaInfo, DailyKaranaInfo follow the same pattern
|
|
355
407
|
|
|
356
|
-
|
|
357
|
-
//
|
|
408
|
+
interface VaraInfo {
|
|
409
|
+
index: number; // 0 = Sunday ... 6 = Saturday
|
|
410
|
+
name: string; // e.g. "Ravivara" (localized)
|
|
411
|
+
shortName: string; // e.g. "Ravi" (localized)
|
|
412
|
+
englishName: string; // e.g. "Sunday" (always English)
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
interface KaranaInfo {
|
|
416
|
+
index: number;
|
|
417
|
+
name: string;
|
|
418
|
+
completionPercentage: number;
|
|
419
|
+
endTime: Date | null;
|
|
420
|
+
type: 'fixed' | 'movable';
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// Note: endTime and startTime are null when computeEndTimes: false.
|
|
424
|
+
```
|
|
425
|
+
</details>
|
|
358
426
|
|
|
359
|
-
|
|
427
|
+
<details>
|
|
428
|
+
<summary><strong>Lunar Calendar</strong> — ChandraMasaInfo, SamvatInfo, MasaInfo</summary>
|
|
360
429
|
|
|
430
|
+
```typescript
|
|
361
431
|
interface ChandraMasaInfo {
|
|
362
|
-
index: number;
|
|
363
|
-
name: string;
|
|
364
|
-
isAdhika: boolean;
|
|
365
|
-
|
|
366
|
-
|
|
432
|
+
index: number; // 0 = Chaitra ... 11 = Phalguna (in the active system)
|
|
433
|
+
name: string; // follows masaSystem option
|
|
434
|
+
isAdhika: boolean; // true = leap/intercalary month
|
|
435
|
+
system: 'purnimanta' | 'amanta';
|
|
436
|
+
amantaIndex: number; // month index in Amanta system
|
|
437
|
+
amantaName: string; // month name in Amanta system
|
|
438
|
+
purnimantaIndex: number; // month index in Purnimanta system
|
|
439
|
+
purnimantaName: string; // month name in Purnimanta system
|
|
367
440
|
}
|
|
368
441
|
|
|
369
442
|
interface SamvatInfo {
|
|
@@ -371,99 +444,83 @@ interface SamvatInfo {
|
|
|
371
444
|
shakaSamvat: number; // e.g. 1946
|
|
372
445
|
}
|
|
373
446
|
|
|
374
|
-
// ── Zodiac & asterism ────────────────────────────────────────────────────────
|
|
375
|
-
|
|
376
|
-
interface RashiInfo {
|
|
377
|
-
index: number; // 0 = Mesha … 11 = Meena (for rashi); 0–26 for nakshatra
|
|
378
|
-
name: string;
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
// chandraRashi and suryaNakshatra both use RashiInfo
|
|
382
|
-
|
|
383
|
-
interface VaraInfo {
|
|
384
|
-
index: number; // 0 = Sunday … 6 = Saturday
|
|
385
|
-
name: string; // e.g. "Ravivara" (localized full name)
|
|
386
|
-
shortName: string; // e.g. "Ravi" (localized short form, Sanskrit by default)
|
|
387
|
-
englishName: string; // e.g. "Sunday" (always English, locale-independent)
|
|
388
|
-
}
|
|
389
|
-
|
|
390
447
|
interface MasaInfo {
|
|
391
|
-
index: number; // 0 = Mesha
|
|
392
|
-
name: string;
|
|
448
|
+
index: number; // 0 = Mesha ... 11 = Meena (solar month)
|
|
449
|
+
name: string;
|
|
393
450
|
}
|
|
394
451
|
|
|
395
|
-
interface
|
|
396
|
-
index: number;
|
|
452
|
+
interface RashiInfo {
|
|
453
|
+
index: number; // 0 = Mesha ... 11 = Meena
|
|
397
454
|
name: string;
|
|
398
|
-
completionPercentage: number;
|
|
399
|
-
endTime: Date | null;
|
|
400
|
-
type: 'fixed' | 'movable';
|
|
401
455
|
}
|
|
456
|
+
```
|
|
457
|
+
</details>
|
|
402
458
|
|
|
403
|
-
|
|
459
|
+
<details>
|
|
460
|
+
<summary><strong>Time Slots</strong> — Choghadiya, Gowri Panchangam, Hora</summary>
|
|
404
461
|
|
|
462
|
+
```typescript
|
|
405
463
|
type ChoghadiyaQuality = 'auspicious' | 'inauspicious' | 'neutral';
|
|
406
464
|
|
|
407
465
|
interface ChoghadiyaSlot extends TimePeriod {
|
|
408
466
|
index: number;
|
|
409
|
-
name: string;
|
|
467
|
+
name: string; // e.g. "Amrit", "Kaal" (localized)
|
|
410
468
|
quality: ChoghadiyaQuality;
|
|
469
|
+
qualityName: string; // localized: "Auspicious", "शुभ", "शुभम्"
|
|
411
470
|
}
|
|
412
471
|
|
|
413
472
|
interface ChoghadiyaInfo {
|
|
414
|
-
day: ChoghadiyaSlot[]; // 8 slots (sunrise
|
|
415
|
-
night: ChoghadiyaSlot[]; // 8 slots (sunset
|
|
473
|
+
day: ChoghadiyaSlot[]; // 8 slots (sunrise -> sunset)
|
|
474
|
+
night: ChoghadiyaSlot[]; // 8 slots (sunset -> next sunrise)
|
|
416
475
|
}
|
|
417
476
|
|
|
418
|
-
// ── Gowri Panchangam ─────────────────────────────────────────────────────────
|
|
419
|
-
|
|
420
477
|
interface GowriSlot extends TimePeriod {
|
|
421
|
-
index: number;
|
|
422
|
-
name: string;
|
|
478
|
+
index: number; // 0-7 within the 8-name cycle
|
|
479
|
+
name: string; // e.g. "Amrit", "Kaal" (localized)
|
|
423
480
|
quality: ChoghadiyaQuality;
|
|
481
|
+
qualityName: string;
|
|
424
482
|
}
|
|
425
483
|
|
|
426
484
|
interface GowriInfo {
|
|
427
|
-
day: GowriSlot[]; // 8 slots (sunrise
|
|
428
|
-
night: GowriSlot[]; // 8 slots (sunset
|
|
485
|
+
day: GowriSlot[]; // 8 slots (sunrise -> sunset)
|
|
486
|
+
night: GowriSlot[]; // 8 slots (sunset -> next sunrise)
|
|
429
487
|
}
|
|
430
488
|
|
|
431
|
-
// ── Hora ─────────────────────────────────────────────────────────────────────
|
|
432
|
-
|
|
433
489
|
interface HoraSlot extends TimePeriod {
|
|
434
|
-
planet: string; //
|
|
435
|
-
planetIndex: number; // 0
|
|
490
|
+
planet: string; // e.g. "Sun", "Venus", "Mercury"
|
|
491
|
+
planetIndex: number; // 0-6 in Chaldean order
|
|
436
492
|
}
|
|
437
493
|
|
|
438
494
|
interface HoraInfo {
|
|
439
|
-
day: HoraSlot[]; // 12 slots (sunrise
|
|
440
|
-
night: HoraSlot[]; // 12 slots (sunset
|
|
495
|
+
day: HoraSlot[]; // 12 slots (sunrise -> sunset)
|
|
496
|
+
night: HoraSlot[]; // 12 slots (sunset -> next sunrise)
|
|
441
497
|
}
|
|
498
|
+
```
|
|
499
|
+
</details>
|
|
442
500
|
|
|
443
|
-
|
|
501
|
+
<details>
|
|
502
|
+
<summary><strong>Special Yogas & Festivals</strong></summary>
|
|
444
503
|
|
|
504
|
+
```typescript
|
|
445
505
|
interface SpecialYogaInfo {
|
|
446
506
|
name: string; // e.g. "Guru Pushya Yoga"
|
|
447
507
|
type: 'amrit_siddhi' | 'sarvartha_siddhi' | 'ravi_pushya' | 'guru_pushya';
|
|
448
508
|
}
|
|
449
509
|
|
|
450
|
-
// ── Festivals ────────────────────────────────────────────────────────────────
|
|
451
|
-
|
|
452
510
|
interface FestivalInfo {
|
|
453
511
|
name: string; // e.g. "Diwali", "Ekadashi"
|
|
454
512
|
type: 'major' | 'minor' | 'ekadashi' | 'pradosha' | 'sankranti';
|
|
455
|
-
description?: string; // For sankranti:
|
|
513
|
+
description?: string; // For sankranti: localized rashi name
|
|
456
514
|
}
|
|
515
|
+
```
|
|
516
|
+
</details>
|
|
457
517
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
// Pradosha: Krishna Trayodashi only (tithi 27)
|
|
461
|
-
// Sankranti: Sun within 1° past a rashi boundary (degInRashi < 1.0)
|
|
462
|
-
// Fixed festivals (e.g. Diwali): matched by chandramasa index + tithi index; skipped during Adhika months
|
|
463
|
-
|
|
464
|
-
// ── Jyotish (Vedic astrology) ────────────────────────────────────────────────
|
|
518
|
+
<details>
|
|
519
|
+
<summary><strong>Jyotish (Vedic Astrology)</strong> — Graha positions, Vimshottari Dasha</summary>
|
|
465
520
|
|
|
466
|
-
|
|
521
|
+
```typescript
|
|
522
|
+
type GrahaName = 'Sun' | 'Moon' | 'Mars' | 'Mercury' | 'Jupiter'
|
|
523
|
+
| 'Venus' | 'Saturn' | 'Rahu' | 'Ketu';
|
|
467
524
|
|
|
468
525
|
interface GrahaPosition {
|
|
469
526
|
planet: GrahaName;
|
|
@@ -480,7 +537,8 @@ interface PlanetaryPositions {
|
|
|
480
537
|
saturn: GrahaPosition; rahu: GrahaPosition; ketu: GrahaPosition;
|
|
481
538
|
}
|
|
482
539
|
|
|
483
|
-
type DashaLord = 'Ketu' | 'Venus' | 'Sun' | 'Moon' | 'Mars'
|
|
540
|
+
type DashaLord = 'Ketu' | 'Venus' | 'Sun' | 'Moon' | 'Mars'
|
|
541
|
+
| 'Rahu' | 'Jupiter' | 'Saturn' | 'Mercury';
|
|
484
542
|
|
|
485
543
|
interface AntarDasha {
|
|
486
544
|
lord: DashaLord;
|
|
@@ -492,21 +550,21 @@ interface MahaDasha {
|
|
|
492
550
|
lord: DashaLord;
|
|
493
551
|
startDate: Date;
|
|
494
552
|
endDate: Date;
|
|
495
|
-
years: number;
|
|
553
|
+
years: number;
|
|
496
554
|
antarDashas: AntarDasha[];
|
|
497
555
|
}
|
|
498
556
|
|
|
499
557
|
interface VimshottariDashaResult {
|
|
500
|
-
currentMahaDashaLord: DashaLord;
|
|
501
|
-
currentIndex: number;
|
|
502
|
-
mahaDashas: MahaDasha[];
|
|
558
|
+
currentMahaDashaLord: DashaLord;
|
|
559
|
+
currentIndex: number;
|
|
560
|
+
mahaDashas: MahaDasha[]; // 9-entry sequence starting from birth
|
|
503
561
|
}
|
|
504
|
-
|
|
505
562
|
```
|
|
563
|
+
</details>
|
|
506
564
|
|
|
507
565
|
---
|
|
508
566
|
|
|
509
|
-
## React Native / Hermes
|
|
567
|
+
## React Native / Hermes
|
|
510
568
|
|
|
511
569
|
Works with Expo and bare React Native (Hermes engine). Pass `timezone` as a **number**
|
|
512
570
|
— IANA timezone strings (`'Asia/Kolkata'`) require `Intl`, which older Hermes versions
|
|
@@ -534,21 +592,9 @@ InteractionManager.runAfterInteractions(() => {
|
|
|
534
592
|
|
|
535
593
|
---
|
|
536
594
|
|
|
537
|
-
## Performance
|
|
538
|
-
|
|
539
|
-
| Mode | Node.js | Hermes (budget Android) |
|
|
540
|
-
|------|---------|------------------------|
|
|
541
|
-
| Names-only (`computeEndTimes: false`) | ~0.1 ms | <100 ms |
|
|
542
|
-
| Full with end-times | ~0.5 ms | <500 ms |
|
|
543
|
-
|
|
544
|
-
Measured with Vitest benchmarks on Node 22 and on a physical budget Android device
|
|
545
|
-
via the dharmSetu React Native app.
|
|
546
|
-
|
|
547
|
-
---
|
|
548
|
-
|
|
549
595
|
## Accuracy
|
|
550
596
|
|
|
551
|
-
Validated against [DrikPanchang.com](https://www.drikpanchang.com) for 19+ date/city combinations
|
|
597
|
+
Validated against [DrikPanchang.com](https://www.drikpanchang.com) for 19+ date/city combinations across India and New York.
|
|
552
598
|
|
|
553
599
|
| Element | Accuracy |
|
|
554
600
|
|---------|----------|
|
|
@@ -559,32 +605,14 @@ Validated against [DrikPanchang.com](https://www.drikpanchang.com) for 19+ date/
|
|
|
559
605
|
| Ayanamsa | ±0.005° vs Swiss Ephemeris |
|
|
560
606
|
| Choghadiya / Hora / Gowri slots | Derived from sunrise/sunset — inherits ±2 min |
|
|
561
607
|
|
|
562
|
-
### Validation test suite
|
|
563
|
-
|
|
564
|
-
The test suite includes:
|
|
565
|
-
- **242-day structural regression** (Pune, Sep 2025 – Apr 2026): verifies no crash, correct Vara, time-ordering invariants, element counts, and all fields (including Gowri Panchangam) for every day in the window
|
|
566
|
-
- **19 precise-value tests** across 5 Indian cities + New York: exact Tithi name, Nakshatra name, sunrise/sunset HH:MM (±2 min tolerance), Chandra Masa name
|
|
567
|
-
- **10 long-range regression tests** (2030–2050): structural correctness and ayanamsa bounds for future dates
|
|
568
|
-
|
|
569
|
-
To generate fixture stubs for new date ranges (e.g. to populate against DrikPanchang):
|
|
570
|
-
|
|
571
|
-
```bash
|
|
572
|
-
npx tsx scripts/generate-fixtures.ts --start 2027-01-01 --end 2027-03-31 --city Delhi
|
|
573
|
-
```
|
|
574
|
-
|
|
575
608
|
---
|
|
576
609
|
|
|
577
|
-
##
|
|
610
|
+
## Performance
|
|
578
611
|
|
|
579
|
-
|
|
|
580
|
-
|
|
581
|
-
|
|
|
582
|
-
|
|
|
583
|
-
| Node.js 22+ | ✅ |
|
|
584
|
-
| React Native (Hermes) | ✅ (pass `timezone` as number) |
|
|
585
|
-
| Expo (managed + bare) | ✅ |
|
|
586
|
-
| Browser (modern) | ✅ (ESM build) |
|
|
587
|
-
| Browser (legacy / IE) | ✗ |
|
|
612
|
+
| Mode | Node.js | Hermes (budget Android) |
|
|
613
|
+
|------|---------|------------------------|
|
|
614
|
+
| Names-only (`computeEndTimes: false`) | ~0.1 ms | <100 ms |
|
|
615
|
+
| Full with end-times | ~0.5 ms | <500 ms |
|
|
588
616
|
|
|
589
617
|
---
|
|
590
618
|
|
|
@@ -603,21 +631,35 @@ try {
|
|
|
603
631
|
}
|
|
604
632
|
```
|
|
605
633
|
|
|
606
|
-
|
|
634
|
+
Error codes: `INVALID_DATE`, `INVALID_LATITUDE`, `INVALID_LONGITUDE`,
|
|
607
635
|
`INVALID_ELEVATION`, `INVALID_TIMEZONE`, `INVALID_AYANAMSA`, `TIMEZONE_RESOLUTION_FAILED`,
|
|
608
636
|
`NO_SUNRISE`, `NO_SUNSET`, `SEARCH_DIVERGED`.
|
|
609
637
|
|
|
610
|
-
|
|
611
|
-
occurs
|
|
638
|
+
`getMoonrise` / `getMoonset` return `null` instead of throwing when no rise/set
|
|
639
|
+
occurs (normal for the Moon).
|
|
612
640
|
|
|
613
641
|
---
|
|
614
642
|
|
|
615
|
-
##
|
|
643
|
+
## Compatibility
|
|
616
644
|
|
|
617
|
-
|
|
645
|
+
| Environment | Support |
|
|
646
|
+
|-------------|---------|
|
|
647
|
+
| Node.js 18+ | Supported |
|
|
648
|
+
| React Native (Hermes) | Supported (pass `timezone` as number) |
|
|
649
|
+
| Expo (managed + bare) | Supported |
|
|
650
|
+
| Browser (modern) | Supported (ESM build) |
|
|
651
|
+
| Browser (legacy / IE) | Not supported |
|
|
618
652
|
|
|
619
653
|
---
|
|
620
654
|
|
|
655
|
+
## Used By
|
|
656
|
+
|
|
657
|
+
- [dharmagya.app](https://dharmagya.app) — Daily Panchang and Hindu calendar
|
|
658
|
+
|
|
659
|
+
## Acknowledgements
|
|
660
|
+
|
|
661
|
+
[astronomy-engine](https://github.com/cosinekitty/astronomy) by Don Cross — the sole runtime dependency. MIT licensed.
|
|
662
|
+
|
|
621
663
|
## License
|
|
622
664
|
|
|
623
665
|
MIT
|