panchang-ts 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -44,7 +44,7 @@ import { getDailyPanchang } from 'panchang-ts';
44
44
 
45
45
  const result = getDailyPanchang(
46
46
  new Date(2025, 0, 14), // January 14, 2025
47
- { latitude: 18.5204, longitude: 73.8567 }, // Pune, India
47
+ { latitude: 23.1765, longitude: 75.7885 }, // Ujjain, India
48
48
  { timezone: 330 }, // IST = UTC+5:30 = 330 minutes
49
49
  );
50
50
 
@@ -239,7 +239,7 @@ console.log(result.panchaka); // false
239
239
  |--------|------|---------|-------------|
240
240
  | `timezone` | `number \| string` | **required** | UTC offset in minutes (330 for IST). Use a number on Hermes — IANA strings require `Intl`. |
241
241
  | `ayanamsa` | `'lahiri' \| 'raman' \| 'krishnamurti'` | `'lahiri'` | Ayanamsa system |
242
- | `language` | `'en' \| 'sa' \| 'hi'` | `'en'` | Language for element names. `'hi'` currently uses the same Devanagari names as `'sa'`. |
242
+ | `language` | `'en' \| 'sa' \| 'hi'` | `'en'` | Language for all element names (tithi, paksha, masa, etc.). `'sa'` = classical Sanskrit Devanagari, `'hi'` = modern Hindi Devanagari. |
243
243
  | `computeEndTimes` | `boolean` | `true` | Set `false` for ~5× faster, names-only output |
244
244
  | `precision` | `'standard' \| 'high'` | `'standard'` | Binary-search iterations (15 vs 25). High precision is rarely needed. |
245
245
 
@@ -331,7 +331,7 @@ interface TimePeriod {
331
331
  interface TithiInfo {
332
332
  index: number; // 0–29
333
333
  name: string; // e.g. "Shukla Pratipada"
334
- paksha: 'Shukla' | 'Krishna';
334
+ paksha: string; // "Shukla"/"Krishna" (en), "शुक्ल"/"कृष्ण" (sa/hi) — localized
335
335
  number: number; // 1–15 within the paksha
336
336
  completionPercentage: number;
337
337
  endTime: Date | null;
package/dist/index.cjs CHANGED
@@ -2789,12 +2789,11 @@ function validateOffset(offset) {
2789
2789
  }
2790
2790
 
2791
2791
  // src/core/tithi.ts
2792
- function computeTithiFromLongitudes(siderealMoon, siderealSun, name) {
2792
+ function computeTithiFromLongitudes(siderealMoon, siderealSun, name, paksha) {
2793
2793
  const angle = normalize360(siderealMoon - siderealSun);
2794
2794
  const index = Math.floor(angle / TITHI_SPAN);
2795
2795
  const elapsed = angle - index * TITHI_SPAN;
2796
2796
  const completionPercentage = elapsed / TITHI_SPAN * 100;
2797
- const paksha = index < 15 ? "Shukla" : "Krishna";
2798
2797
  const number = index < 15 ? index + 1 : index - 14;
2799
2798
  return {
2800
2799
  index,
@@ -2974,25 +2973,11 @@ function computeGowriPanchangam(sunrise, sunset, nextSunrise, varaIndex, nameFn)
2974
2973
  }
2975
2974
 
2976
2975
  // src/core/masa.ts
2977
- var MASA_NAMES_EN = [
2978
- "Mesha",
2979
- "Vrishabha",
2980
- "Mithuna",
2981
- "Karka",
2982
- "Simha",
2983
- "Kanya",
2984
- "Tula",
2985
- "Vrischika",
2986
- "Dhanus",
2987
- "Makara",
2988
- "Kumbha",
2989
- "Meena"
2990
- ];
2991
- function computeMasa(siderealSunLon) {
2976
+ function computeMasa(siderealSunLon, nameResolver) {
2992
2977
  const index = Math.floor(siderealSunLon / 30);
2993
2978
  return {
2994
2979
  index,
2995
- name: MASA_NAMES_EN[index]
2980
+ name: nameResolver(index)
2996
2981
  };
2997
2982
  }
2998
2983
 
@@ -3619,13 +3604,177 @@ var sa = {
3619
3604
  };
3620
3605
 
3621
3606
  // src/i18n/hi.ts
3622
- var hi = { ...sa };
3607
+ var hi = {
3608
+ tithiNames: [
3609
+ "\u092A\u094D\u0930\u0924\u093F\u092A\u0926\u093E",
3610
+ "\u0926\u094D\u0935\u093F\u0924\u0940\u092F\u093E",
3611
+ "\u0924\u0943\u0924\u0940\u092F\u093E",
3612
+ "\u091A\u0924\u0941\u0930\u094D\u0925\u0940",
3613
+ "\u092A\u0902\u091A\u092E\u0940",
3614
+ "\u0937\u0937\u094D\u0920\u0940",
3615
+ "\u0938\u092A\u094D\u0924\u092E\u0940",
3616
+ "\u0905\u0937\u094D\u091F\u092E\u0940",
3617
+ "\u0928\u0935\u092E\u0940",
3618
+ "\u0926\u0936\u092E\u0940",
3619
+ "\u090F\u0915\u093E\u0926\u0936\u0940",
3620
+ "\u0926\u094D\u0935\u093E\u0926\u0936\u0940",
3621
+ "\u0924\u094D\u0930\u092F\u094B\u0926\u0936\u0940",
3622
+ "\u091A\u0924\u0941\u0930\u094D\u0926\u0936\u0940"
3623
+ ],
3624
+ nakshatraNames: [
3625
+ "\u0905\u0936\u094D\u0935\u093F\u0928\u0940",
3626
+ "\u092D\u0930\u0923\u0940",
3627
+ "\u0915\u0943\u0924\u094D\u0924\u093F\u0915\u093E",
3628
+ "\u0930\u094B\u0939\u093F\u0923\u0940",
3629
+ "\u092E\u0943\u0917\u0936\u093F\u0930\u093E",
3630
+ "\u0906\u0930\u094D\u0926\u094D\u0930\u093E",
3631
+ "\u092A\u0941\u0928\u0930\u094D\u0935\u0938\u0941",
3632
+ "\u092A\u0941\u0937\u094D\u092F",
3633
+ "\u0906\u0936\u094D\u0932\u0947\u0937\u093E",
3634
+ "\u092E\u0918\u093E",
3635
+ "\u092A\u0942\u0930\u094D\u0935\u093E \u092B\u093E\u0932\u094D\u0917\u0941\u0928\u0940",
3636
+ "\u0909\u0924\u094D\u0924\u0930\u093E \u092B\u093E\u0932\u094D\u0917\u0941\u0928\u0940",
3637
+ "\u0939\u0938\u094D\u0924",
3638
+ "\u091A\u093F\u0924\u094D\u0930\u093E",
3639
+ "\u0938\u094D\u0935\u093E\u0924\u093F",
3640
+ "\u0935\u093F\u0936\u093E\u0916\u093E",
3641
+ "\u0905\u0928\u0941\u0930\u093E\u0927\u093E",
3642
+ "\u091C\u094D\u092F\u0947\u0937\u094D\u0920\u093E",
3643
+ "\u092E\u0942\u0932",
3644
+ "\u092A\u0942\u0930\u094D\u0935\u093E\u0937\u093E\u0922\u093C\u093E",
3645
+ "\u0909\u0924\u094D\u0924\u0930\u093E\u0937\u093E\u0922\u093C\u093E",
3646
+ "\u0936\u094D\u0930\u0935\u0923",
3647
+ "\u0927\u0928\u093F\u0937\u094D\u0920\u093E",
3648
+ "\u0936\u0924\u092D\u093F\u0937\u093E",
3649
+ "\u092A\u0942\u0930\u094D\u0935\u093E \u092D\u093E\u0926\u094D\u0930\u092A\u0926",
3650
+ "\u0909\u0924\u094D\u0924\u0930\u093E \u092D\u093E\u0926\u094D\u0930\u092A\u0926",
3651
+ "\u0930\u0947\u0935\u0924\u0940"
3652
+ ],
3653
+ yogaNames: [
3654
+ "\u0935\u093F\u0937\u094D\u0915\u092E\u094D\u092D",
3655
+ "\u092A\u094D\u0930\u0940\u0924\u093F",
3656
+ "\u0906\u092F\u0941\u0937\u094D\u092E\u093E\u0928",
3657
+ "\u0938\u094C\u092D\u093E\u0917\u094D\u092F",
3658
+ "\u0936\u094B\u092D\u0928",
3659
+ "\u0905\u0924\u093F\u0917\u0902\u0921",
3660
+ "\u0938\u0941\u0915\u0930\u094D\u092E\u093E",
3661
+ "\u0927\u0943\u0924\u093F",
3662
+ "\u0936\u0942\u0932",
3663
+ "\u0917\u0902\u0921",
3664
+ "\u0935\u0943\u0926\u094D\u0927\u093F",
3665
+ "\u0927\u094D\u0930\u0941\u0935",
3666
+ "\u0935\u094D\u092F\u093E\u0918\u093E\u0924",
3667
+ "\u0939\u0930\u094D\u0937\u0923",
3668
+ "\u0935\u091C\u094D\u0930",
3669
+ "\u0938\u093F\u0926\u094D\u0927\u093F",
3670
+ "\u0935\u094D\u092F\u0924\u0940\u092A\u093E\u0924",
3671
+ "\u0935\u0930\u0940\u092F\u093E\u0928",
3672
+ "\u092A\u0930\u093F\u0918",
3673
+ "\u0936\u093F\u0935",
3674
+ "\u0938\u093F\u0926\u094D\u0927",
3675
+ "\u0938\u093E\u0927\u094D\u092F",
3676
+ "\u0936\u0941\u092D",
3677
+ "\u0936\u0941\u0915\u094D\u0932",
3678
+ "\u092C\u094D\u0930\u0939\u094D\u092E",
3679
+ "\u0907\u0902\u0926\u094D\u0930",
3680
+ "\u0935\u0948\u0927\u0943\u0924\u093F"
3681
+ ],
3682
+ karanaNames: {
3683
+ movable: ["\u092C\u0935", "\u092C\u093E\u0932\u0935", "\u0915\u094C\u0932\u0935", "\u0924\u0948\u0924\u093F\u0932", "\u0917\u0930", "\u0935\u0923\u093F\u091C", "\u0935\u093F\u0937\u094D\u091F\u093F"],
3684
+ fixed: ["\u0915\u093F\u0902\u0938\u094D\u0924\u0941\u0918\u094D\u0928", "\u0936\u0915\u0941\u0928\u093F", "\u091A\u0924\u0941\u0937\u094D\u092A\u0926", "\u0928\u093E\u0917"]
3685
+ },
3686
+ varaNames: [
3687
+ { name: "\u0930\u0935\u093F\u0935\u093E\u0930", short: "\u0930\u0935\u093F" },
3688
+ { name: "\u0938\u094B\u092E\u0935\u093E\u0930", short: "\u0938\u094B\u092E" },
3689
+ { name: "\u092E\u0902\u0917\u0932\u0935\u093E\u0930", short: "\u092E\u0902\u0917\u0932" },
3690
+ { name: "\u092C\u0941\u0927\u0935\u093E\u0930", short: "\u092C\u0941\u0927" },
3691
+ { name: "\u0917\u0941\u0930\u0941\u0935\u093E\u0930", short: "\u0917\u0941\u0930\u0941" },
3692
+ { name: "\u0936\u0941\u0915\u094D\u0930\u0935\u093E\u0930", short: "\u0936\u0941\u0915\u094D\u0930" },
3693
+ { name: "\u0936\u0928\u093F\u0935\u093E\u0930", short: "\u0936\u0928\u093F" }
3694
+ ],
3695
+ pakshaNames: { shukla: "\u0936\u0941\u0915\u094D\u0932", krishna: "\u0915\u0943\u0937\u094D\u0923" },
3696
+ masaNames: [
3697
+ "\u092E\u0947\u0937",
3698
+ "\u0935\u0943\u0937\u092D",
3699
+ "\u092E\u093F\u0925\u0941\u0928",
3700
+ "\u0915\u0930\u094D\u0915",
3701
+ "\u0938\u093F\u0902\u0939",
3702
+ "\u0915\u0928\u094D\u092F\u093E",
3703
+ "\u0924\u0941\u0932\u093E",
3704
+ "\u0935\u0943\u0936\u094D\u091A\u093F\u0915",
3705
+ "\u0927\u0928\u0941",
3706
+ "\u092E\u0915\u0930",
3707
+ "\u0915\u0941\u0902\u092D",
3708
+ "\u092E\u0940\u0928"
3709
+ ],
3710
+ chandraMasaNames: [
3711
+ "\u091A\u0948\u0924\u094D\u0930",
3712
+ "\u0935\u0948\u0936\u093E\u0916",
3713
+ "\u091C\u094D\u092F\u0947\u0937\u094D\u0920",
3714
+ "\u0906\u0937\u093E\u0922\u093C",
3715
+ "\u0936\u094D\u0930\u093E\u0935\u0923",
3716
+ "\u092D\u093E\u0926\u094D\u0930\u092A\u0926",
3717
+ "\u0906\u0936\u094D\u0935\u093F\u0928",
3718
+ "\u0915\u093E\u0930\u094D\u0924\u093F\u0915",
3719
+ "\u092E\u093E\u0930\u094D\u0917\u0936\u0940\u0930\u094D\u0937",
3720
+ "\u092A\u094C\u0937",
3721
+ "\u092E\u093E\u0918",
3722
+ "\u092B\u093E\u0932\u094D\u0917\u0941\u0928"
3723
+ ],
3724
+ choghadiyaNames: ["\u0909\u0926\u094D\u0935\u0947\u0917", "\u091A\u0930", "\u0932\u093E\u092D", "\u0905\u092E\u0943\u0924", "\u0915\u093E\u0932", "\u0936\u0941\u092D", "\u0930\u094B\u0917"],
3725
+ gowriNames: ["\u0909\u0926\u094D\u092F\u094B\u0917", "\u0905\u092E\u0943\u0924", "\u0930\u094B\u0917", "\u0932\u093E\u092D", "\u0936\u0941\u092D", "\u0915\u093E\u0932", "\u0927\u0928", "\u091A\u0932"],
3726
+ grahaNames: ["\u0938\u0942\u0930\u094D\u092F", "\u0936\u0941\u0915\u094D\u0930", "\u092C\u0941\u0927", "\u091A\u0902\u0926\u094D\u0930", "\u0936\u0928\u093F", "\u0917\u0941\u0930\u0941", "\u092E\u0902\u0917\u0932"],
3727
+ specialYogaNames: {
3728
+ amrit_siddhi: "\u0905\u092E\u0943\u0924 \u0938\u093F\u0926\u094D\u0927\u093F \u092F\u094B\u0917",
3729
+ sarvartha_siddhi: "\u0938\u0930\u094D\u0935\u093E\u0930\u094D\u0925 \u0938\u093F\u0926\u094D\u0927\u093F \u092F\u094B\u0917",
3730
+ ravi_pushya: "\u0930\u0935\u093F \u092A\u0941\u0937\u094D\u092F \u092F\u094B\u0917",
3731
+ guru_pushya: "\u0917\u0941\u0930\u0941 \u092A\u0941\u0937\u094D\u092F \u092F\u094B\u0917"
3732
+ },
3733
+ festivalNames: {
3734
+ ugadi: "\u0909\u0917\u093E\u0926\u0940",
3735
+ rama_navami: "\u0930\u093E\u092E \u0928\u0935\u092E\u0940",
3736
+ hanuman_jayanti: "\u0939\u0928\u0941\u092E\u093E\u0928 \u091C\u092F\u0902\u0924\u0940",
3737
+ akshaya_tritiya: "\u0905\u0915\u094D\u0937\u092F \u0924\u0943\u0924\u0940\u092F\u093E",
3738
+ guru_purnima: "\u0917\u0941\u0930\u0941 \u092A\u0942\u0930\u094D\u0923\u093F\u092E\u093E",
3739
+ nag_panchami: "\u0928\u093E\u0917 \u092A\u0902\u091A\u092E\u0940",
3740
+ raksha_bandhan: "\u0930\u0915\u094D\u0937\u093E \u092C\u0902\u0927\u0928",
3741
+ krishna_janmashtami: "\u0915\u0943\u0937\u094D\u0923 \u091C\u0928\u094D\u092E\u093E\u0937\u094D\u091F\u092E\u0940",
3742
+ ganesh_chaturthi: "\u0917\u0923\u0947\u0936 \u091A\u0924\u0941\u0930\u094D\u0925\u0940",
3743
+ anant_chaturdashi: "\u0905\u0928\u0902\u0924 \u091A\u0924\u0941\u0930\u094D\u0926\u0936\u0940",
3744
+ navaratri: "\u0936\u0930\u0926 \u0928\u0935\u0930\u093E\u0924\u094D\u0930\u093F",
3745
+ durga_ashtami: "\u0926\u0941\u0930\u094D\u0917\u093E \u0905\u0937\u094D\u091F\u092E\u0940",
3746
+ maha_navami: "\u092E\u0939\u093E \u0928\u0935\u092E\u0940",
3747
+ dussehra: "\u0926\u0936\u0939\u0930\u093E",
3748
+ sharad_purnima: "\u0936\u0930\u0926 \u092A\u0942\u0930\u094D\u0923\u093F\u092E\u093E",
3749
+ karva_chauth: "\u0915\u0930\u0935\u093E \u091A\u094C\u0925",
3750
+ dhanteras: "\u0927\u0928\u0924\u0947\u0930\u0938",
3751
+ narak_chaturdashi: "\u0928\u0930\u0915 \u091A\u0924\u0941\u0930\u094D\u0926\u0936\u0940",
3752
+ diwali: "\u0926\u093F\u0935\u093E\u0932\u0940",
3753
+ vasant_panchami: "\u0935\u0938\u0902\u0924 \u092A\u0902\u091A\u092E\u0940",
3754
+ maha_shivaratri: "\u092E\u0939\u093E \u0936\u093F\u0935\u0930\u093E\u0924\u094D\u0930\u093F",
3755
+ holi: "\u0939\u094B\u0932\u0940",
3756
+ mahalaya_amavasya: "\u092E\u0939\u093E\u0932\u092F \u0905\u092E\u093E\u0935\u0938\u094D\u092F\u093E",
3757
+ kartika_purnima: "\u0915\u093E\u0930\u094D\u0924\u093F\u0915 \u092A\u0942\u0930\u094D\u0923\u093F\u092E\u093E"
3758
+ },
3759
+ misc: {
3760
+ purnima: "\u092A\u0942\u0930\u094D\u0923\u093F\u092E\u093E",
3761
+ amavasya: "\u0905\u092E\u093E\u0935\u0938\u094D\u092F\u093E",
3762
+ adhika: "\u0905\u0927\u093F\u0915",
3763
+ ekadashi: "\u090F\u0915\u093E\u0926\u0936\u0940",
3764
+ pradosha: "\u092A\u094D\u0930\u0926\u094B\u0937 \u0935\u094D\u0930\u0924",
3765
+ sankranti: "\u0938\u0902\u0915\u094D\u0930\u093E\u0902\u0924\u093F"
3766
+ }
3767
+ };
3623
3768
 
3624
3769
  // src/i18n/resolver.ts
3625
3770
  var TRANSLATIONS = { en, sa, hi };
3626
3771
  function getTranslations(lang) {
3627
3772
  return TRANSLATIONS[lang] ?? en;
3628
3773
  }
3774
+ function resolvePakshaName(index, lang) {
3775
+ const t = getTranslations(lang);
3776
+ return index < 15 ? t.pakshaNames.shukla : t.pakshaNames.krishna;
3777
+ }
3629
3778
  function resolveTithiName(index, lang) {
3630
3779
  const t = getTranslations(lang);
3631
3780
  if (index === 14) return t.misc.purnima;
@@ -3669,10 +3818,12 @@ function getInstantPanchang(date, location, options) {
3669
3818
  const siderealMoon = getMoon(date);
3670
3819
  const siderealSun = getSun(date);
3671
3820
  const ayanamsaValue = computeAyanamsa(date, ayanamsaType);
3821
+ const tithiIdx = getTithiIndexFromLons(siderealMoon, siderealSun);
3672
3822
  const tithi = computeTithiFromLongitudes(
3673
3823
  siderealMoon,
3674
3824
  siderealSun,
3675
- resolveTithiName(getTithiIndexFromLons(siderealMoon, siderealSun), lang)
3825
+ resolveTithiName(tithiIdx, lang),
3826
+ resolvePakshaName(tithiIdx, lang)
3676
3827
  );
3677
3828
  const nakshatra = computeNakshatraFromLongitude(
3678
3829
  siderealMoon,
@@ -3791,10 +3942,12 @@ function getDailyPanchang(date, location, options) {
3791
3942
  const siderealMoonAtSunrise = getMoon(sunriseUtc);
3792
3943
  const siderealSunAtSunrise = getSun(sunriseUtc);
3793
3944
  const ayanamsaValue = computeAyanamsa(sunriseUtc, ayanamsaType);
3945
+ const tithiIdxAtSunrise = getTithiIndexFromLons(siderealMoonAtSunrise, siderealSunAtSunrise);
3794
3946
  const tithiAtSunrise = computeTithiFromLongitudes(
3795
3947
  siderealMoonAtSunrise,
3796
3948
  siderealSunAtSunrise,
3797
- resolveTithiName(getTithiIndexFromLons(siderealMoonAtSunrise, siderealSunAtSunrise), lang)
3949
+ resolveTithiName(tithiIdxAtSunrise, lang),
3950
+ resolvePakshaName(tithiIdxAtSunrise, lang)
3798
3951
  );
3799
3952
  const nakshatraAtSunrise = computeNakshatraFromLongitude(
3800
3953
  siderealMoonAtSunrise,
@@ -3811,7 +3964,7 @@ function getDailyPanchang(date, location, options) {
3811
3964
  resolveKaranaName(getKaranaIndex(siderealMoonAtSunrise, siderealSunAtSunrise), lang)
3812
3965
  );
3813
3966
  const vara = computeVara(sunriseUtc, sunriseUtc, getTranslations(lang).varaNames);
3814
- const masa = computeMasa(siderealSunAtSunrise);
3967
+ const masa = computeMasa(siderealSunAtSunrise, (idx) => resolveMasaName(idx, lang));
3815
3968
  const chandramasa = computeChandraMasa(
3816
3969
  siderealSunAtSunrise,
3817
3970
  siderealMoonAtSunrise,
@@ -3880,7 +4033,8 @@ function getDailyPanchang(date, location, options) {
3880
4033
  (d) => getTithiIndexAtTime(d, getMoon, getSun),
3881
4034
  (d) => {
3882
4035
  const moon = getMoon(d), sun = getSun(d);
3883
- return computeTithiFromLongitudes(moon, sun, resolveTithiName(getTithiIndexFromLons(moon, sun), lang));
4036
+ const idx = getTithiIndexFromLons(moon, sun);
4037
+ return computeTithiFromLongitudes(moon, sun, resolveTithiName(idx, lang), resolvePakshaName(idx, lang));
3884
4038
  },
3885
4039
  30,
3886
4040
  36,
package/dist/index.d.cts CHANGED
@@ -35,7 +35,7 @@ interface ElementBase {
35
35
  endTime: Date | null;
36
36
  }
37
37
  interface TithiInfo extends ElementBase {
38
- paksha: 'Shukla' | 'Krishna';
38
+ paksha: string;
39
39
  number: number;
40
40
  }
41
41
  interface NakshatraInfo extends ElementBase {
@@ -224,7 +224,7 @@ interface InstantPanchangResult {
224
224
  *
225
225
  * const p = getInstantPanchang(
226
226
  * new Date('2025-01-14T03:00:00Z'),
227
- * { latitude: 18.5204, longitude: 73.8567 },
227
+ * { latitude: 23.1765, longitude: 75.7885 }, // Ujjain, India
228
228
  * { language: 'sa' },
229
229
  * );
230
230
  * console.log(p.tithi.name); // "कृष्ण चतुर्दशी"
@@ -263,7 +263,7 @@ declare function getInstantPanchang(date: Date, location: GeoLocation, options?:
263
263
  *
264
264
  * const result = getDailyPanchang(
265
265
  * new Date(2025, 0, 14), // Jan 14, 2025
266
- * { latitude: 18.5204, longitude: 73.8567 }, // Pune, India
266
+ * { latitude: 23.1765, longitude: 75.7885 }, // Ujjain, India
267
267
  * { timezone: 330 }, // IST = UTC+5:30
268
268
  * );
269
269
  *
package/dist/index.d.ts CHANGED
@@ -35,7 +35,7 @@ interface ElementBase {
35
35
  endTime: Date | null;
36
36
  }
37
37
  interface TithiInfo extends ElementBase {
38
- paksha: 'Shukla' | 'Krishna';
38
+ paksha: string;
39
39
  number: number;
40
40
  }
41
41
  interface NakshatraInfo extends ElementBase {
@@ -224,7 +224,7 @@ interface InstantPanchangResult {
224
224
  *
225
225
  * const p = getInstantPanchang(
226
226
  * new Date('2025-01-14T03:00:00Z'),
227
- * { latitude: 18.5204, longitude: 73.8567 },
227
+ * { latitude: 23.1765, longitude: 75.7885 }, // Ujjain, India
228
228
  * { language: 'sa' },
229
229
  * );
230
230
  * console.log(p.tithi.name); // "कृष्ण चतुर्दशी"
@@ -263,7 +263,7 @@ declare function getInstantPanchang(date: Date, location: GeoLocation, options?:
263
263
  *
264
264
  * const result = getDailyPanchang(
265
265
  * new Date(2025, 0, 14), // Jan 14, 2025
266
- * { latitude: 18.5204, longitude: 73.8567 }, // Pune, India
266
+ * { latitude: 23.1765, longitude: 75.7885 }, // Ujjain, India
267
267
  * { timezone: 330 }, // IST = UTC+5:30
268
268
  * );
269
269
  *
package/dist/index.js CHANGED
@@ -2787,12 +2787,11 @@ function validateOffset(offset) {
2787
2787
  }
2788
2788
 
2789
2789
  // src/core/tithi.ts
2790
- function computeTithiFromLongitudes(siderealMoon, siderealSun, name) {
2790
+ function computeTithiFromLongitudes(siderealMoon, siderealSun, name, paksha) {
2791
2791
  const angle = normalize360(siderealMoon - siderealSun);
2792
2792
  const index = Math.floor(angle / TITHI_SPAN);
2793
2793
  const elapsed = angle - index * TITHI_SPAN;
2794
2794
  const completionPercentage = elapsed / TITHI_SPAN * 100;
2795
- const paksha = index < 15 ? "Shukla" : "Krishna";
2796
2795
  const number = index < 15 ? index + 1 : index - 14;
2797
2796
  return {
2798
2797
  index,
@@ -2972,25 +2971,11 @@ function computeGowriPanchangam(sunrise, sunset, nextSunrise, varaIndex, nameFn)
2972
2971
  }
2973
2972
 
2974
2973
  // src/core/masa.ts
2975
- var MASA_NAMES_EN = [
2976
- "Mesha",
2977
- "Vrishabha",
2978
- "Mithuna",
2979
- "Karka",
2980
- "Simha",
2981
- "Kanya",
2982
- "Tula",
2983
- "Vrischika",
2984
- "Dhanus",
2985
- "Makara",
2986
- "Kumbha",
2987
- "Meena"
2988
- ];
2989
- function computeMasa(siderealSunLon) {
2974
+ function computeMasa(siderealSunLon, nameResolver) {
2990
2975
  const index = Math.floor(siderealSunLon / 30);
2991
2976
  return {
2992
2977
  index,
2993
- name: MASA_NAMES_EN[index]
2978
+ name: nameResolver(index)
2994
2979
  };
2995
2980
  }
2996
2981
 
@@ -3617,13 +3602,177 @@ var sa = {
3617
3602
  };
3618
3603
 
3619
3604
  // src/i18n/hi.ts
3620
- var hi = { ...sa };
3605
+ var hi = {
3606
+ tithiNames: [
3607
+ "\u092A\u094D\u0930\u0924\u093F\u092A\u0926\u093E",
3608
+ "\u0926\u094D\u0935\u093F\u0924\u0940\u092F\u093E",
3609
+ "\u0924\u0943\u0924\u0940\u092F\u093E",
3610
+ "\u091A\u0924\u0941\u0930\u094D\u0925\u0940",
3611
+ "\u092A\u0902\u091A\u092E\u0940",
3612
+ "\u0937\u0937\u094D\u0920\u0940",
3613
+ "\u0938\u092A\u094D\u0924\u092E\u0940",
3614
+ "\u0905\u0937\u094D\u091F\u092E\u0940",
3615
+ "\u0928\u0935\u092E\u0940",
3616
+ "\u0926\u0936\u092E\u0940",
3617
+ "\u090F\u0915\u093E\u0926\u0936\u0940",
3618
+ "\u0926\u094D\u0935\u093E\u0926\u0936\u0940",
3619
+ "\u0924\u094D\u0930\u092F\u094B\u0926\u0936\u0940",
3620
+ "\u091A\u0924\u0941\u0930\u094D\u0926\u0936\u0940"
3621
+ ],
3622
+ nakshatraNames: [
3623
+ "\u0905\u0936\u094D\u0935\u093F\u0928\u0940",
3624
+ "\u092D\u0930\u0923\u0940",
3625
+ "\u0915\u0943\u0924\u094D\u0924\u093F\u0915\u093E",
3626
+ "\u0930\u094B\u0939\u093F\u0923\u0940",
3627
+ "\u092E\u0943\u0917\u0936\u093F\u0930\u093E",
3628
+ "\u0906\u0930\u094D\u0926\u094D\u0930\u093E",
3629
+ "\u092A\u0941\u0928\u0930\u094D\u0935\u0938\u0941",
3630
+ "\u092A\u0941\u0937\u094D\u092F",
3631
+ "\u0906\u0936\u094D\u0932\u0947\u0937\u093E",
3632
+ "\u092E\u0918\u093E",
3633
+ "\u092A\u0942\u0930\u094D\u0935\u093E \u092B\u093E\u0932\u094D\u0917\u0941\u0928\u0940",
3634
+ "\u0909\u0924\u094D\u0924\u0930\u093E \u092B\u093E\u0932\u094D\u0917\u0941\u0928\u0940",
3635
+ "\u0939\u0938\u094D\u0924",
3636
+ "\u091A\u093F\u0924\u094D\u0930\u093E",
3637
+ "\u0938\u094D\u0935\u093E\u0924\u093F",
3638
+ "\u0935\u093F\u0936\u093E\u0916\u093E",
3639
+ "\u0905\u0928\u0941\u0930\u093E\u0927\u093E",
3640
+ "\u091C\u094D\u092F\u0947\u0937\u094D\u0920\u093E",
3641
+ "\u092E\u0942\u0932",
3642
+ "\u092A\u0942\u0930\u094D\u0935\u093E\u0937\u093E\u0922\u093C\u093E",
3643
+ "\u0909\u0924\u094D\u0924\u0930\u093E\u0937\u093E\u0922\u093C\u093E",
3644
+ "\u0936\u094D\u0930\u0935\u0923",
3645
+ "\u0927\u0928\u093F\u0937\u094D\u0920\u093E",
3646
+ "\u0936\u0924\u092D\u093F\u0937\u093E",
3647
+ "\u092A\u0942\u0930\u094D\u0935\u093E \u092D\u093E\u0926\u094D\u0930\u092A\u0926",
3648
+ "\u0909\u0924\u094D\u0924\u0930\u093E \u092D\u093E\u0926\u094D\u0930\u092A\u0926",
3649
+ "\u0930\u0947\u0935\u0924\u0940"
3650
+ ],
3651
+ yogaNames: [
3652
+ "\u0935\u093F\u0937\u094D\u0915\u092E\u094D\u092D",
3653
+ "\u092A\u094D\u0930\u0940\u0924\u093F",
3654
+ "\u0906\u092F\u0941\u0937\u094D\u092E\u093E\u0928",
3655
+ "\u0938\u094C\u092D\u093E\u0917\u094D\u092F",
3656
+ "\u0936\u094B\u092D\u0928",
3657
+ "\u0905\u0924\u093F\u0917\u0902\u0921",
3658
+ "\u0938\u0941\u0915\u0930\u094D\u092E\u093E",
3659
+ "\u0927\u0943\u0924\u093F",
3660
+ "\u0936\u0942\u0932",
3661
+ "\u0917\u0902\u0921",
3662
+ "\u0935\u0943\u0926\u094D\u0927\u093F",
3663
+ "\u0927\u094D\u0930\u0941\u0935",
3664
+ "\u0935\u094D\u092F\u093E\u0918\u093E\u0924",
3665
+ "\u0939\u0930\u094D\u0937\u0923",
3666
+ "\u0935\u091C\u094D\u0930",
3667
+ "\u0938\u093F\u0926\u094D\u0927\u093F",
3668
+ "\u0935\u094D\u092F\u0924\u0940\u092A\u093E\u0924",
3669
+ "\u0935\u0930\u0940\u092F\u093E\u0928",
3670
+ "\u092A\u0930\u093F\u0918",
3671
+ "\u0936\u093F\u0935",
3672
+ "\u0938\u093F\u0926\u094D\u0927",
3673
+ "\u0938\u093E\u0927\u094D\u092F",
3674
+ "\u0936\u0941\u092D",
3675
+ "\u0936\u0941\u0915\u094D\u0932",
3676
+ "\u092C\u094D\u0930\u0939\u094D\u092E",
3677
+ "\u0907\u0902\u0926\u094D\u0930",
3678
+ "\u0935\u0948\u0927\u0943\u0924\u093F"
3679
+ ],
3680
+ karanaNames: {
3681
+ movable: ["\u092C\u0935", "\u092C\u093E\u0932\u0935", "\u0915\u094C\u0932\u0935", "\u0924\u0948\u0924\u093F\u0932", "\u0917\u0930", "\u0935\u0923\u093F\u091C", "\u0935\u093F\u0937\u094D\u091F\u093F"],
3682
+ fixed: ["\u0915\u093F\u0902\u0938\u094D\u0924\u0941\u0918\u094D\u0928", "\u0936\u0915\u0941\u0928\u093F", "\u091A\u0924\u0941\u0937\u094D\u092A\u0926", "\u0928\u093E\u0917"]
3683
+ },
3684
+ varaNames: [
3685
+ { name: "\u0930\u0935\u093F\u0935\u093E\u0930", short: "\u0930\u0935\u093F" },
3686
+ { name: "\u0938\u094B\u092E\u0935\u093E\u0930", short: "\u0938\u094B\u092E" },
3687
+ { name: "\u092E\u0902\u0917\u0932\u0935\u093E\u0930", short: "\u092E\u0902\u0917\u0932" },
3688
+ { name: "\u092C\u0941\u0927\u0935\u093E\u0930", short: "\u092C\u0941\u0927" },
3689
+ { name: "\u0917\u0941\u0930\u0941\u0935\u093E\u0930", short: "\u0917\u0941\u0930\u0941" },
3690
+ { name: "\u0936\u0941\u0915\u094D\u0930\u0935\u093E\u0930", short: "\u0936\u0941\u0915\u094D\u0930" },
3691
+ { name: "\u0936\u0928\u093F\u0935\u093E\u0930", short: "\u0936\u0928\u093F" }
3692
+ ],
3693
+ pakshaNames: { shukla: "\u0936\u0941\u0915\u094D\u0932", krishna: "\u0915\u0943\u0937\u094D\u0923" },
3694
+ masaNames: [
3695
+ "\u092E\u0947\u0937",
3696
+ "\u0935\u0943\u0937\u092D",
3697
+ "\u092E\u093F\u0925\u0941\u0928",
3698
+ "\u0915\u0930\u094D\u0915",
3699
+ "\u0938\u093F\u0902\u0939",
3700
+ "\u0915\u0928\u094D\u092F\u093E",
3701
+ "\u0924\u0941\u0932\u093E",
3702
+ "\u0935\u0943\u0936\u094D\u091A\u093F\u0915",
3703
+ "\u0927\u0928\u0941",
3704
+ "\u092E\u0915\u0930",
3705
+ "\u0915\u0941\u0902\u092D",
3706
+ "\u092E\u0940\u0928"
3707
+ ],
3708
+ chandraMasaNames: [
3709
+ "\u091A\u0948\u0924\u094D\u0930",
3710
+ "\u0935\u0948\u0936\u093E\u0916",
3711
+ "\u091C\u094D\u092F\u0947\u0937\u094D\u0920",
3712
+ "\u0906\u0937\u093E\u0922\u093C",
3713
+ "\u0936\u094D\u0930\u093E\u0935\u0923",
3714
+ "\u092D\u093E\u0926\u094D\u0930\u092A\u0926",
3715
+ "\u0906\u0936\u094D\u0935\u093F\u0928",
3716
+ "\u0915\u093E\u0930\u094D\u0924\u093F\u0915",
3717
+ "\u092E\u093E\u0930\u094D\u0917\u0936\u0940\u0930\u094D\u0937",
3718
+ "\u092A\u094C\u0937",
3719
+ "\u092E\u093E\u0918",
3720
+ "\u092B\u093E\u0932\u094D\u0917\u0941\u0928"
3721
+ ],
3722
+ choghadiyaNames: ["\u0909\u0926\u094D\u0935\u0947\u0917", "\u091A\u0930", "\u0932\u093E\u092D", "\u0905\u092E\u0943\u0924", "\u0915\u093E\u0932", "\u0936\u0941\u092D", "\u0930\u094B\u0917"],
3723
+ gowriNames: ["\u0909\u0926\u094D\u092F\u094B\u0917", "\u0905\u092E\u0943\u0924", "\u0930\u094B\u0917", "\u0932\u093E\u092D", "\u0936\u0941\u092D", "\u0915\u093E\u0932", "\u0927\u0928", "\u091A\u0932"],
3724
+ grahaNames: ["\u0938\u0942\u0930\u094D\u092F", "\u0936\u0941\u0915\u094D\u0930", "\u092C\u0941\u0927", "\u091A\u0902\u0926\u094D\u0930", "\u0936\u0928\u093F", "\u0917\u0941\u0930\u0941", "\u092E\u0902\u0917\u0932"],
3725
+ specialYogaNames: {
3726
+ amrit_siddhi: "\u0905\u092E\u0943\u0924 \u0938\u093F\u0926\u094D\u0927\u093F \u092F\u094B\u0917",
3727
+ sarvartha_siddhi: "\u0938\u0930\u094D\u0935\u093E\u0930\u094D\u0925 \u0938\u093F\u0926\u094D\u0927\u093F \u092F\u094B\u0917",
3728
+ ravi_pushya: "\u0930\u0935\u093F \u092A\u0941\u0937\u094D\u092F \u092F\u094B\u0917",
3729
+ guru_pushya: "\u0917\u0941\u0930\u0941 \u092A\u0941\u0937\u094D\u092F \u092F\u094B\u0917"
3730
+ },
3731
+ festivalNames: {
3732
+ ugadi: "\u0909\u0917\u093E\u0926\u0940",
3733
+ rama_navami: "\u0930\u093E\u092E \u0928\u0935\u092E\u0940",
3734
+ hanuman_jayanti: "\u0939\u0928\u0941\u092E\u093E\u0928 \u091C\u092F\u0902\u0924\u0940",
3735
+ akshaya_tritiya: "\u0905\u0915\u094D\u0937\u092F \u0924\u0943\u0924\u0940\u092F\u093E",
3736
+ guru_purnima: "\u0917\u0941\u0930\u0941 \u092A\u0942\u0930\u094D\u0923\u093F\u092E\u093E",
3737
+ nag_panchami: "\u0928\u093E\u0917 \u092A\u0902\u091A\u092E\u0940",
3738
+ raksha_bandhan: "\u0930\u0915\u094D\u0937\u093E \u092C\u0902\u0927\u0928",
3739
+ krishna_janmashtami: "\u0915\u0943\u0937\u094D\u0923 \u091C\u0928\u094D\u092E\u093E\u0937\u094D\u091F\u092E\u0940",
3740
+ ganesh_chaturthi: "\u0917\u0923\u0947\u0936 \u091A\u0924\u0941\u0930\u094D\u0925\u0940",
3741
+ anant_chaturdashi: "\u0905\u0928\u0902\u0924 \u091A\u0924\u0941\u0930\u094D\u0926\u0936\u0940",
3742
+ navaratri: "\u0936\u0930\u0926 \u0928\u0935\u0930\u093E\u0924\u094D\u0930\u093F",
3743
+ durga_ashtami: "\u0926\u0941\u0930\u094D\u0917\u093E \u0905\u0937\u094D\u091F\u092E\u0940",
3744
+ maha_navami: "\u092E\u0939\u093E \u0928\u0935\u092E\u0940",
3745
+ dussehra: "\u0926\u0936\u0939\u0930\u093E",
3746
+ sharad_purnima: "\u0936\u0930\u0926 \u092A\u0942\u0930\u094D\u0923\u093F\u092E\u093E",
3747
+ karva_chauth: "\u0915\u0930\u0935\u093E \u091A\u094C\u0925",
3748
+ dhanteras: "\u0927\u0928\u0924\u0947\u0930\u0938",
3749
+ narak_chaturdashi: "\u0928\u0930\u0915 \u091A\u0924\u0941\u0930\u094D\u0926\u0936\u0940",
3750
+ diwali: "\u0926\u093F\u0935\u093E\u0932\u0940",
3751
+ vasant_panchami: "\u0935\u0938\u0902\u0924 \u092A\u0902\u091A\u092E\u0940",
3752
+ maha_shivaratri: "\u092E\u0939\u093E \u0936\u093F\u0935\u0930\u093E\u0924\u094D\u0930\u093F",
3753
+ holi: "\u0939\u094B\u0932\u0940",
3754
+ mahalaya_amavasya: "\u092E\u0939\u093E\u0932\u092F \u0905\u092E\u093E\u0935\u0938\u094D\u092F\u093E",
3755
+ kartika_purnima: "\u0915\u093E\u0930\u094D\u0924\u093F\u0915 \u092A\u0942\u0930\u094D\u0923\u093F\u092E\u093E"
3756
+ },
3757
+ misc: {
3758
+ purnima: "\u092A\u0942\u0930\u094D\u0923\u093F\u092E\u093E",
3759
+ amavasya: "\u0905\u092E\u093E\u0935\u0938\u094D\u092F\u093E",
3760
+ adhika: "\u0905\u0927\u093F\u0915",
3761
+ ekadashi: "\u090F\u0915\u093E\u0926\u0936\u0940",
3762
+ pradosha: "\u092A\u094D\u0930\u0926\u094B\u0937 \u0935\u094D\u0930\u0924",
3763
+ sankranti: "\u0938\u0902\u0915\u094D\u0930\u093E\u0902\u0924\u093F"
3764
+ }
3765
+ };
3621
3766
 
3622
3767
  // src/i18n/resolver.ts
3623
3768
  var TRANSLATIONS = { en, sa, hi };
3624
3769
  function getTranslations(lang) {
3625
3770
  return TRANSLATIONS[lang] ?? en;
3626
3771
  }
3772
+ function resolvePakshaName(index, lang) {
3773
+ const t = getTranslations(lang);
3774
+ return index < 15 ? t.pakshaNames.shukla : t.pakshaNames.krishna;
3775
+ }
3627
3776
  function resolveTithiName(index, lang) {
3628
3777
  const t = getTranslations(lang);
3629
3778
  if (index === 14) return t.misc.purnima;
@@ -3667,10 +3816,12 @@ function getInstantPanchang(date, location, options) {
3667
3816
  const siderealMoon = getMoon(date);
3668
3817
  const siderealSun = getSun(date);
3669
3818
  const ayanamsaValue = computeAyanamsa(date, ayanamsaType);
3819
+ const tithiIdx = getTithiIndexFromLons(siderealMoon, siderealSun);
3670
3820
  const tithi = computeTithiFromLongitudes(
3671
3821
  siderealMoon,
3672
3822
  siderealSun,
3673
- resolveTithiName(getTithiIndexFromLons(siderealMoon, siderealSun), lang)
3823
+ resolveTithiName(tithiIdx, lang),
3824
+ resolvePakshaName(tithiIdx, lang)
3674
3825
  );
3675
3826
  const nakshatra = computeNakshatraFromLongitude(
3676
3827
  siderealMoon,
@@ -3789,10 +3940,12 @@ function getDailyPanchang(date, location, options) {
3789
3940
  const siderealMoonAtSunrise = getMoon(sunriseUtc);
3790
3941
  const siderealSunAtSunrise = getSun(sunriseUtc);
3791
3942
  const ayanamsaValue = computeAyanamsa(sunriseUtc, ayanamsaType);
3943
+ const tithiIdxAtSunrise = getTithiIndexFromLons(siderealMoonAtSunrise, siderealSunAtSunrise);
3792
3944
  const tithiAtSunrise = computeTithiFromLongitudes(
3793
3945
  siderealMoonAtSunrise,
3794
3946
  siderealSunAtSunrise,
3795
- resolveTithiName(getTithiIndexFromLons(siderealMoonAtSunrise, siderealSunAtSunrise), lang)
3947
+ resolveTithiName(tithiIdxAtSunrise, lang),
3948
+ resolvePakshaName(tithiIdxAtSunrise, lang)
3796
3949
  );
3797
3950
  const nakshatraAtSunrise = computeNakshatraFromLongitude(
3798
3951
  siderealMoonAtSunrise,
@@ -3809,7 +3962,7 @@ function getDailyPanchang(date, location, options) {
3809
3962
  resolveKaranaName(getKaranaIndex(siderealMoonAtSunrise, siderealSunAtSunrise), lang)
3810
3963
  );
3811
3964
  const vara = computeVara(sunriseUtc, sunriseUtc, getTranslations(lang).varaNames);
3812
- const masa = computeMasa(siderealSunAtSunrise);
3965
+ const masa = computeMasa(siderealSunAtSunrise, (idx) => resolveMasaName(idx, lang));
3813
3966
  const chandramasa = computeChandraMasa(
3814
3967
  siderealSunAtSunrise,
3815
3968
  siderealMoonAtSunrise,
@@ -3878,7 +4031,8 @@ function getDailyPanchang(date, location, options) {
3878
4031
  (d) => getTithiIndexAtTime(d, getMoon, getSun),
3879
4032
  (d) => {
3880
4033
  const moon = getMoon(d), sun = getSun(d);
3881
- return computeTithiFromLongitudes(moon, sun, resolveTithiName(getTithiIndexFromLons(moon, sun), lang));
4034
+ const idx = getTithiIndexFromLons(moon, sun);
4035
+ return computeTithiFromLongitudes(moon, sun, resolveTithiName(idx, lang), resolvePakshaName(idx, lang));
3882
4036
  },
3883
4037
  30,
3884
4038
  36,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "panchang-ts",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Pure TypeScript Hindu Panchang calculations. Tithi, Nakshatra, Yoga, Karana, Vara, and more. Offline-first, React Native compatible.",
5
5
  "author": "Ishank",
6
6
  "license": "MIT",