panchang-ts 0.7.0 → 1.0.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 +61 -16
- package/dist/index.cjs +58 -32
- package/dist/index.d.cts +308 -64
- package/dist/index.d.ts +308 -64
- package/dist/index.js +57 -33
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -163,7 +163,7 @@ Rahu Kalam, Gulika Kalam, Yamaganda, Panchaka detection.
|
|
|
163
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
164
|
|
|
165
165
|
### Jyotish (Vedic Astrology)
|
|
166
|
-
All 9 graha positions (geocentric, sidereal) with rashi, nakshatra, pada, and retrograde status. Vimshottari Dasha with Antardasha breakdown.
|
|
166
|
+
All 9 graha positions (geocentric, sidereal) with rashi, nakshatra, pada, and retrograde status. Vimshottari Dasha with Antardasha breakdown — from a birth moment alone or from an explicit Moon longitude. Chandra Balam (transit-Moon favorability relative to janma rashi).
|
|
167
167
|
|
|
168
168
|
### Astronomy
|
|
169
169
|
Sunrise, Sunset, Moonrise, Moonset, Chandra Rashi (Moon sign), Surya Nakshatra.
|
|
@@ -310,7 +310,9 @@ import {
|
|
|
310
310
|
computeAbhijitMuhurta, computeBrahmaMuhurta,
|
|
311
311
|
computeGowriPanchangam,
|
|
312
312
|
// Jyotish
|
|
313
|
-
computePlanetaryPositions,
|
|
313
|
+
computePlanetaryPositions,
|
|
314
|
+
computeVimshottariDasha, computeVimshottariDashaFromBirth,
|
|
315
|
+
computeChandraBalam,
|
|
314
316
|
GRAHA_ABBR,
|
|
315
317
|
} from 'panchang-ts';
|
|
316
318
|
|
|
@@ -342,17 +344,27 @@ const brahma = computeBrahmaMuhurta(sunrise, sunset); // { start, end }
|
|
|
342
344
|
**Jyotish (Vedic Astrology):**
|
|
343
345
|
|
|
344
346
|
```typescript
|
|
345
|
-
// All 9 graha positions (sidereal)
|
|
347
|
+
// All 9 graha positions (sidereal — Rahu/Ketu use mean node)
|
|
346
348
|
const grahas = computePlanetaryPositions(birthDate, 'lahiri');
|
|
347
349
|
console.log(grahas.jupiter.rashi.name); // "Dhanu"
|
|
348
350
|
console.log(grahas.saturn.isRetrograde); // true/false
|
|
349
351
|
console.log(GRAHA_ABBR['Jupiter']); // "Ju"
|
|
350
352
|
|
|
351
|
-
// Vimshottari Dasha —
|
|
352
|
-
const
|
|
353
|
-
const dasha = computeVimshottariDasha(birthDate, moonLon);
|
|
353
|
+
// Vimshottari Dasha — convenience form: birth date only (Moon longitude derived)
|
|
354
|
+
const dasha = computeVimshottariDashaFromBirth(birthDate, 'lahiri');
|
|
354
355
|
console.log(dasha.currentMahaDashaLord); // "Rahu"
|
|
355
356
|
console.log(dasha.mahaDashas[0]!.antarDashas[0]!.lord); // "Rahu"
|
|
357
|
+
|
|
358
|
+
// Or pass an explicit Moon sidereal longitude (useful when you already have one)
|
|
359
|
+
const moonLon = getSiderealMoonLongitude(birthDate, 'lahiri');
|
|
360
|
+
const dasha2 = computeVimshottariDasha(birthDate, moonLon);
|
|
361
|
+
|
|
362
|
+
// Chandra Balam — transit Moon's favorability vs. janma rashi
|
|
363
|
+
// janmaRashi and transitMoonRashi are 0-indexed (0 = Mesha ... 11 = Meena)
|
|
364
|
+
const cb = computeChandraBalam(3 /* Karka */, 6 /* Tula */);
|
|
365
|
+
console.log(cb.house); // 4
|
|
366
|
+
console.log(cb.quality); // "weak"
|
|
367
|
+
console.log(cb.englishName); // "Ashubha"
|
|
356
368
|
```
|
|
357
369
|
|
|
358
370
|
---
|
|
@@ -559,6 +571,13 @@ interface VimshottariDashaResult {
|
|
|
559
571
|
currentIndex: number;
|
|
560
572
|
mahaDashas: MahaDasha[]; // 9-entry sequence starting from birth
|
|
561
573
|
}
|
|
574
|
+
|
|
575
|
+
interface ChandraBalamInfo {
|
|
576
|
+
house: number; // 1 = janma rashi; 12 = rashi before janma
|
|
577
|
+
quality: 'strong' | 'weak'; // Shubha houses = 1,3,6,7,10,11
|
|
578
|
+
englishName: string; // "Shubha" | "Ashubha"
|
|
579
|
+
name: string; // localized
|
|
580
|
+
}
|
|
562
581
|
```
|
|
563
582
|
</details>
|
|
564
583
|
|
|
@@ -594,16 +613,42 @@ InteractionManager.runAfterInteractions(() => {
|
|
|
594
613
|
|
|
595
614
|
## Accuracy
|
|
596
615
|
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
|
602
|
-
|
|
603
|
-
|
|
|
604
|
-
|
|
|
605
|
-
|
|
|
606
|
-
|
|
|
616
|
+
4,864 tests passing, including Drik-verified fixtures against
|
|
617
|
+
[DrikPanchang.com](https://www.drikpanchang.com) spanning 2025–2026 across
|
|
618
|
+
Delhi, Chennai, and New York.
|
|
619
|
+
|
|
620
|
+
| Element | Accuracy | Validation |
|
|
621
|
+
|---------|----------|------------|
|
|
622
|
+
| Sunrise / Sunset | **≤29 s observed vs Drik minute-midpoint** (±45 s tolerance) | 16 assertions |
|
|
623
|
+
| Moonrise / Moonset | ±2 min vs Drik | Strict fixtures |
|
|
624
|
+
| Tithi, Nakshatra, Yoga, Karana names | Exact match vs Drik | Strict fixtures |
|
|
625
|
+
| Tithi / Nakshatra / Yoga / Karana end-times | **±3 min tolerance, max 2.01 min observed** | 20 assertions |
|
|
626
|
+
| Ayanamsa | ±0.005° vs Swiss Ephemeris | Unit tests |
|
|
627
|
+
| Planetary positions (Sun–Saturn) | **±0.02° vs Drik sidereal** | Drik fixtures |
|
|
628
|
+
| Planetary positions (Rahu/Ketu, mean node) | ≤0.5° typical; ±2° tolerance to absorb mean-vs-true drift | Drik fixtures |
|
|
629
|
+
| Rashi / Nakshatra / Retrograde flag | Exact match vs Drik | Drik fixtures |
|
|
630
|
+
| Festival dates | 12 Drik-verified festivals (2025–2026) — see caveats below | Drik fixtures |
|
|
631
|
+
| Choghadiya / Hora / Gowri slots | Derived from sunrise/sunset — inherits ±2 min | — |
|
|
632
|
+
|
|
633
|
+
### Festival Detection — Documented Tradeoff
|
|
634
|
+
|
|
635
|
+
Library uses **tithi-at-sunrise** to resolve a festival to a calendar day.
|
|
636
|
+
DrikPanchang applies several other traditional rules depending on the
|
|
637
|
+
festival; where those rules pick a different day, our output can drift
|
|
638
|
+
±1 day vs Drik. This is a rule-choice tradeoff, not a computation bug —
|
|
639
|
+
it is documented and deliberately surfaced rather than hidden.
|
|
640
|
+
|
|
641
|
+
| Resolution rule Drik uses | Festivals affected |
|
|
642
|
+
|---------------------------|--------------------|
|
|
643
|
+
| Tithi-at-midnight | Krishna Janmashtami, Maha Shivaratri, Diwali / Lakshmi Puja |
|
|
644
|
+
| Madhyahna-vyapini (tithi overlapping noon) | Ganesh Chaturthi on edge years, Akshaya Tritiya 2026 |
|
|
645
|
+
| Kshaya-tithi handling (tithi never at sunrise) | Ugadi 2026-03-19 (Pratipad is Kshaya) |
|
|
646
|
+
|
|
647
|
+
If exact Drik parity matters for your use case, cross-check the above
|
|
648
|
+
festival set against the Drik site for the target year. Everything else
|
|
649
|
+
— Holi, Ugadi (non-Kshaya years), Rama Navami, Raksha Bandhan, Ganesh
|
|
650
|
+
Chaturthi (normal years), Navaratri, Dussehra, Karva Chauth, Hanuman
|
|
651
|
+
Jayanti — matches Drik's canonical date across 2025 and 2026 fixtures.
|
|
607
652
|
|
|
608
653
|
---
|
|
609
654
|
|
package/dist/index.cjs
CHANGED
|
@@ -3262,28 +3262,6 @@ function computeFestivals(tithiIndex, _nakshatraIndex, chandraMasaIndex, isAdhik
|
|
|
3262
3262
|
return results;
|
|
3263
3263
|
}
|
|
3264
3264
|
|
|
3265
|
-
// src/astronomy/moonrise.ts
|
|
3266
|
-
function getMoonrise(searchFromUtc, location, limitDays = 2) {
|
|
3267
|
-
const observer = new Observer(
|
|
3268
|
-
location.latitude,
|
|
3269
|
-
location.longitude,
|
|
3270
|
-
location.elevation ?? 0
|
|
3271
|
-
);
|
|
3272
|
-
const astroTime = MakeTime(searchFromUtc);
|
|
3273
|
-
const result = SearchRiseSet(Body.Moon, observer, 1, astroTime, limitDays);
|
|
3274
|
-
return result ? result.date : null;
|
|
3275
|
-
}
|
|
3276
|
-
function getMoonset(searchFromUtc, location, limitDays = 2) {
|
|
3277
|
-
const observer = new Observer(
|
|
3278
|
-
location.latitude,
|
|
3279
|
-
location.longitude,
|
|
3280
|
-
location.elevation ?? 0
|
|
3281
|
-
);
|
|
3282
|
-
const astroTime = MakeTime(searchFromUtc);
|
|
3283
|
-
const result = SearchRiseSet(Body.Moon, observer, -1, astroTime, limitDays);
|
|
3284
|
-
return result ? result.date : null;
|
|
3285
|
-
}
|
|
3286
|
-
|
|
3287
3265
|
// src/i18n/en.ts
|
|
3288
3266
|
var en = {
|
|
3289
3267
|
tithiNames: [
|
|
@@ -3412,6 +3390,7 @@ var en = {
|
|
|
3412
3390
|
ravi_pushya: "Ravi Pushya Yoga",
|
|
3413
3391
|
guru_pushya: "Guru Pushya Yoga"
|
|
3414
3392
|
},
|
|
3393
|
+
chandraBalamNames: { shubha: "Shubha", ashubha: "Ashubha" },
|
|
3415
3394
|
festivalNames: {
|
|
3416
3395
|
ugadi: "Ugadi",
|
|
3417
3396
|
rama_navami: "Rama Navami",
|
|
@@ -3576,6 +3555,7 @@ var sa = {
|
|
|
3576
3555
|
ravi_pushya: "\u0930\u0935\u093F \u092A\u0941\u0937\u094D\u092F \u092F\u094B\u0917",
|
|
3577
3556
|
guru_pushya: "\u0917\u0941\u0930\u0941 \u092A\u0941\u0937\u094D\u092F \u092F\u094B\u0917"
|
|
3578
3557
|
},
|
|
3558
|
+
chandraBalamNames: { shubha: "\u0936\u0941\u092D", ashubha: "\u0905\u0936\u0941\u092D" },
|
|
3579
3559
|
festivalNames: {
|
|
3580
3560
|
ugadi: "\u092F\u0941\u0917\u093E\u0926\u093F",
|
|
3581
3561
|
rama_navami: "\u0930\u093E\u092E \u0928\u0935\u092E\u0940",
|
|
@@ -3740,6 +3720,7 @@ var hi = {
|
|
|
3740
3720
|
ravi_pushya: "\u0930\u0935\u093F \u092A\u0941\u0937\u094D\u092F \u092F\u094B\u0917",
|
|
3741
3721
|
guru_pushya: "\u0917\u0941\u0930\u0941 \u092A\u0941\u0937\u094D\u092F \u092F\u094B\u0917"
|
|
3742
3722
|
},
|
|
3723
|
+
chandraBalamNames: { shubha: "\u0936\u0941\u092D", ashubha: "\u0905\u0936\u0941\u092D" },
|
|
3743
3724
|
festivalNames: {
|
|
3744
3725
|
ugadi: "\u0909\u0917\u093E\u0926\u0940",
|
|
3745
3726
|
rama_navami: "\u0930\u093E\u092E \u0928\u0935\u092E\u0940",
|
|
@@ -3814,6 +3795,45 @@ function resolveChandraMasaName(index, lang, adhika = false) {
|
|
|
3814
3795
|
return adhika ? `${t.misc.adhika} ${name}` : name;
|
|
3815
3796
|
}
|
|
3816
3797
|
|
|
3798
|
+
// src/jyotish/chandraBalam.ts
|
|
3799
|
+
var STRONG_HOUSES = /* @__PURE__ */ new Set([1, 3, 6, 7, 10, 11]);
|
|
3800
|
+
function computeChandraBalam(janmaRashiIndex, transitMoonRashiIndex, lang = "en") {
|
|
3801
|
+
if (!Number.isInteger(janmaRashiIndex) || janmaRashiIndex < 0 || janmaRashiIndex > 11) {
|
|
3802
|
+
throw new RangeError(`janmaRashiIndex must be integer in [0, 11], got ${janmaRashiIndex}`);
|
|
3803
|
+
}
|
|
3804
|
+
if (!Number.isInteger(transitMoonRashiIndex) || transitMoonRashiIndex < 0 || transitMoonRashiIndex > 11) {
|
|
3805
|
+
throw new RangeError(`transitMoonRashiIndex must be integer in [0, 11], got ${transitMoonRashiIndex}`);
|
|
3806
|
+
}
|
|
3807
|
+
const house = (transitMoonRashiIndex - janmaRashiIndex + 12) % 12 + 1;
|
|
3808
|
+
const quality = STRONG_HOUSES.has(house) ? "strong" : "weak";
|
|
3809
|
+
const englishName = quality === "strong" ? "Shubha" : "Ashubha";
|
|
3810
|
+
const t = getTranslations(lang);
|
|
3811
|
+
const name = quality === "strong" ? t.chandraBalamNames.shubha : t.chandraBalamNames.ashubha;
|
|
3812
|
+
return { house, quality, englishName, name };
|
|
3813
|
+
}
|
|
3814
|
+
|
|
3815
|
+
// src/astronomy/moonrise.ts
|
|
3816
|
+
function getMoonrise(searchFromUtc, location, limitDays = 2) {
|
|
3817
|
+
const observer = new Observer(
|
|
3818
|
+
location.latitude,
|
|
3819
|
+
location.longitude,
|
|
3820
|
+
location.elevation ?? 0
|
|
3821
|
+
);
|
|
3822
|
+
const astroTime = MakeTime(searchFromUtc);
|
|
3823
|
+
const result = SearchRiseSet(Body.Moon, observer, 1, astroTime, limitDays);
|
|
3824
|
+
return result ? result.date : null;
|
|
3825
|
+
}
|
|
3826
|
+
function getMoonset(searchFromUtc, location, limitDays = 2) {
|
|
3827
|
+
const observer = new Observer(
|
|
3828
|
+
location.latitude,
|
|
3829
|
+
location.longitude,
|
|
3830
|
+
location.elevation ?? 0
|
|
3831
|
+
);
|
|
3832
|
+
const astroTime = MakeTime(searchFromUtc);
|
|
3833
|
+
const result = SearchRiseSet(Body.Moon, observer, -1, astroTime, limitDays);
|
|
3834
|
+
return result ? result.date : null;
|
|
3835
|
+
}
|
|
3836
|
+
|
|
3817
3837
|
// src/core/panchang.ts
|
|
3818
3838
|
function getInstantPanchang(date, location, options) {
|
|
3819
3839
|
validateDate(date);
|
|
@@ -3917,6 +3937,7 @@ function getInstantPanchang(date, location, options) {
|
|
|
3917
3937
|
(key) => t.festivalNames[key] ?? t.misc[key] ?? key,
|
|
3918
3938
|
(idx) => resolveMasaName(idx, lang)
|
|
3919
3939
|
);
|
|
3940
|
+
const chandraBalam = options?.janmaRashi !== void 0 ? computeChandraBalam(options.janmaRashi, chandraRashi.index, lang) : void 0;
|
|
3920
3941
|
return {
|
|
3921
3942
|
timestamp: date,
|
|
3922
3943
|
location,
|
|
@@ -3934,7 +3955,8 @@ function getInstantPanchang(date, location, options) {
|
|
|
3934
3955
|
suryaNakshatra,
|
|
3935
3956
|
panchaka: computePanchaka(siderealMoon),
|
|
3936
3957
|
specialYogas,
|
|
3937
|
-
festivals
|
|
3958
|
+
festivals,
|
|
3959
|
+
...chandraBalam !== void 0 ? { chandraBalam } : {}
|
|
3938
3960
|
};
|
|
3939
3961
|
}
|
|
3940
3962
|
function getDailyPanchang(date, location, options) {
|
|
@@ -4136,6 +4158,7 @@ function getDailyPanchang(date, location, options) {
|
|
|
4136
4158
|
k.endTime = toLocalOrNull(k.endTime);
|
|
4137
4159
|
k.startTime = toLocalOrNull(k.startTime);
|
|
4138
4160
|
}
|
|
4161
|
+
const chandraBalam = options.janmaRashi !== void 0 ? computeChandraBalam(options.janmaRashi, chandraRashi.index, lang) : void 0;
|
|
4139
4162
|
return {
|
|
4140
4163
|
date,
|
|
4141
4164
|
location,
|
|
@@ -4180,7 +4203,8 @@ function getDailyPanchang(date, location, options) {
|
|
|
4180
4203
|
gowriPanchangam: {
|
|
4181
4204
|
day: gowriPanchangam.day.map((s) => ({ ...s, ...convertTimePeriod(s) })),
|
|
4182
4205
|
night: gowriPanchangam.night.map((s) => ({ ...s, ...convertTimePeriod(s) }))
|
|
4183
|
-
}
|
|
4206
|
+
},
|
|
4207
|
+
...chandraBalam !== void 0 ? { chandraBalam } : {}
|
|
4184
4208
|
};
|
|
4185
4209
|
}
|
|
4186
4210
|
|
|
@@ -4209,15 +4233,11 @@ function isRetrograde(body, date) {
|
|
|
4209
4233
|
if (delta < -180) delta += 360;
|
|
4210
4234
|
return delta < 0;
|
|
4211
4235
|
}
|
|
4212
|
-
function
|
|
4236
|
+
function getMeanRahuLongitudeTropical(date) {
|
|
4213
4237
|
const T = (dateToJulianDay(date) - 2451545) / 36525;
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
93.27191028 + 483202.0175233 * T - 36825e-7 * T * T + 3083e-9 * T * T * T
|
|
4238
|
+
return normalize360(
|
|
4239
|
+
125.0445479 - 1934.1362891 * T + 20754e-7 * T * T + T * T * T / 467441 - T * T * T * T / 60616e3
|
|
4217
4240
|
);
|
|
4218
|
-
const F_rad = F * Math.PI / 180;
|
|
4219
|
-
const correction = -1.4979 * Math.sin(2 * F_rad) - 0.15 * Math.sin(0 * F_rad + Math.PI * 2 * (357.5 / 360)) - 0.1226 * Math.sin(2 * (omega * Math.PI / 180)) + 0.1176 * Math.sin(2 * F_rad - 2 * (omega * Math.PI / 180));
|
|
4220
|
-
return normalize360(omega + correction / 60);
|
|
4221
4241
|
}
|
|
4222
4242
|
function buildGrahaPosition(planet, siderealLon, isRetro, nakshatraNameFn, rashiNameFn) {
|
|
4223
4243
|
const rashiIndex = Math.floor(siderealLon / 30);
|
|
@@ -4243,7 +4263,7 @@ function computePlanetaryPositions(date, ayanamsaType, nakshatraName = identity,
|
|
|
4243
4263
|
const jupTrop = getTropicalPlanetLongitude(Body.Jupiter, date);
|
|
4244
4264
|
const venTrop = getTropicalPlanetLongitude(Body.Venus, date);
|
|
4245
4265
|
const satTrop = getTropicalPlanetLongitude(Body.Saturn, date);
|
|
4246
|
-
const rahuTrop =
|
|
4266
|
+
const rahuTrop = getMeanRahuLongitudeTropical(date);
|
|
4247
4267
|
const ketuTrop = normalize360(rahuTrop + 180);
|
|
4248
4268
|
const marsRetro = isRetrograde(Body.Mars, date);
|
|
4249
4269
|
const mercRetro = isRetrograde(Body.Mercury, date);
|
|
@@ -4349,6 +4369,10 @@ function computeVimshottariDasha(birthDate, moonSiderealLon) {
|
|
|
4349
4369
|
mahaDashas
|
|
4350
4370
|
};
|
|
4351
4371
|
}
|
|
4372
|
+
function computeVimshottariDashaFromBirth(birthDate, ayanamsaType = "lahiri") {
|
|
4373
|
+
const moonSid = getSiderealMoonLongitude(birthDate, ayanamsaType);
|
|
4374
|
+
return computeVimshottariDasha(birthDate, moonSid);
|
|
4375
|
+
}
|
|
4352
4376
|
function buildAntarDashas(mahaLord, mahaStart, mahaDurationMs) {
|
|
4353
4377
|
const mahaIdx = DASHA_ORDER.indexOf(mahaLord);
|
|
4354
4378
|
const antarDashas = [];
|
|
@@ -4407,11 +4431,13 @@ exports.GRAHA_ABBR = GRAHA_ABBR;
|
|
|
4407
4431
|
exports.PanchangError = PanchangError;
|
|
4408
4432
|
exports.computeAbhijitMuhurta = computeAbhijitMuhurta;
|
|
4409
4433
|
exports.computeBrahmaMuhurta = computeBrahmaMuhurta;
|
|
4434
|
+
exports.computeChandraBalam = computeChandraBalam;
|
|
4410
4435
|
exports.computeGowriPanchangam = computeGowriPanchangam;
|
|
4411
4436
|
exports.computeGulikaKalam = computeGulikaKalam;
|
|
4412
4437
|
exports.computePlanetaryPositions = computePlanetaryPositions;
|
|
4413
4438
|
exports.computeRahuKalam = computeRahuKalam;
|
|
4414
4439
|
exports.computeVimshottariDasha = computeVimshottariDasha;
|
|
4440
|
+
exports.computeVimshottariDashaFromBirth = computeVimshottariDashaFromBirth;
|
|
4415
4441
|
exports.computeYamaganda = computeYamaganda;
|
|
4416
4442
|
exports.getAyanamsa = computeAyanamsa;
|
|
4417
4443
|
exports.getDailyPanchang = getDailyPanchang;
|