panchang-ts 5.0.1 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,12 +6,12 @@
6
6
  Pure TypeScript Hindu Panchang (almanac), Jyotish, and Birth Chart calculations.
7
7
  Zero runtime dependencies. Works offline in React Native (Hermes), Node.js, and browsers.
8
8
 
9
- **Fast** (~0.25 ms trimmed, ~0.41 ms full) · **Typed** (full TypeScript) · **Offline** (pure JS math) · **8,368 tests across 121 files**
9
+ **Fast** (~0.25 ms trimmed, ~0.41 ms full) · **Typed** (full TypeScript) · **Offline** (pure JS math) · **8,737 tests across 136 files**
10
10
 
11
11
  > 📖 **Full documentation: [dharmagya.app/docs/panchang-ts](https://dharmagya.app/docs/panchang-ts)**
12
- > This README covers install, quick start, and the 4.x → 5 migration in full, plus a per-feature
13
- > quick reference. The complete reference — every option, result field, table format, accuracy
14
- > bound and performance note — lives on the docs site.
12
+ > This README covers install, quick start, and the 5.0 → 5.1 and 4.x → 5 migrations in full,
13
+ > plus a per-feature quick reference. The complete reference — every option, result field,
14
+ > table format, accuracy bound and performance note — lives on the docs site.
15
15
 
16
16
  ---
17
17
 
@@ -130,6 +130,142 @@ Ekadashi split. For reliable festival dating, use `getDailyPanchang`.
130
130
 
131
131
  ---
132
132
 
133
+ ## Upgrading from 5.1 (unreleased)
134
+
135
+ Two deliberate type breaks, both correcting fields that did not match
136
+ DrikPanchang (the project's parity oracle), in the same style as 5.1's
137
+ `varjyam` break.
138
+
139
+ ### `inauspicious.durMuhurta` is now `DurMuhurtaPeriod[]`
140
+
141
+ ```diff
142
+ - const [dm1, dm2] = r.inauspicious.durMuhurta;
143
+ + r.inauspicious.durMuhurta.forEach((dm) => show(dm)); // 1–2 windows
144
+ + // dm.segment is 'day' or 'night' (only Tuesday carries a night window)
145
+ ```
146
+
147
+ The old table emitted two day windows every day and matched drik on none of
148
+ the seven weekdays. The corrected classical Muhurta-Chintamani table gives
149
+ one window on Sunday and Wednesday, two elsewhere — and Tuesday's second
150
+ window falls at **night** (the 7th of the 15 sunset→sunrise muhurtas), so
151
+ the exactly-two-day-windows tuple could not survive. Verified against 58
152
+ consecutive drik day-pages across two cities; a full drik week is pinned.
153
+
154
+ ### `muhurtas.amritKala` is now `TimePeriod[]`
155
+
156
+ ```diff
157
+ - if (r.muhurtas.amritKala) show(r.muhurtas.amritKala);
158
+ + r.muhurtas.amritKala.forEach(show); // [] when the day has none
159
+ ```
160
+
161
+ Amrit Kala shares Varjyam's architecture (drik prints them from the same
162
+ frame): each window anchors at its nakshatra's own start, offset by a
163
+ per-nakshatra count of nakshatra-elastic ghatikas, spans exactly 4 such
164
+ ghatikas, and belongs to the Hindu day its **start** falls in — 0–2 windows
165
+ per day. The old sunrise-anchored single window disagreed with drik by up
166
+ to ~16 h. `computeAmritKala` is replaced by
167
+ `computeAmritKalaWindows(sunriseUtc, nextSunriseUtc, getMoon)`.
168
+
169
+ ### Ekadashi splits: Smarta first, Vaishnava second
170
+
171
+ On the days drik prints an Ekadashi twice, the **earlier** day is the Smarta
172
+ fast and the **later** one the Vaishnava fast — drik says so in prose on every
173
+ Ekadashi date-time page. Two corrections bring the library in line:
174
+
175
+ ```diff
176
+ // Dashami-viddha day (e.g. Rama Ekadashi, 2027-10-25)
177
+ - ['vaishnava_ekadashi', 'smarta_ekadashi' /* deferred */, 'ekadashi']
178
+ + ['smarta_ekadashi', 'ekadashi'] // vaishnava_ekadashi is tomorrow
179
+
180
+ // First day of a vriddha Dwadashi (e.g. 2026-08-24)
181
+ - []
182
+ + ['vaishnava_ekadashi']
183
+ ```
184
+
185
+ Both the Dashami-viddha and the vriddha-Dwadashi (Pakshavardhini) splits now
186
+ match drik across every pair it publishes in 2024–2028. `getDailyPanchang`
187
+ callers that keyed off `smarta_ekadashi` / `vaishnava_ekadashi` on split days
188
+ will see the two swap places; `computeEkadashiDatesForYear` is unchanged.
189
+ Custom locale packs need the renamed viddha description keys — see the
190
+ CHANGELOG.
191
+
192
+ ### Regional solar new years land on their own days
193
+
194
+ `vishu`, `baisakhi` and `pohela_boishakh` no longer share Puthandu's day.
195
+ Each keys off the Mesha transit moment its own way, so in 2027 Vishu and
196
+ Pohela Boishakh fall on April 15 while Puthandu falls on April 14, and in
197
+ 2028 Vaisakhi falls on April 13 while the rest fall on April 14.
198
+ `getHinduNewYear(year, region, …)` follows the same per-region rules.
199
+
200
+ Several other **value-level** corrections ride along without shape changes:
201
+ dur muhurta ordinals, night choghadiya names, Bhadra vasa (now Moon-rashi
202
+ keyed, with a piecewise `vasa` segment list on `BhadraInfo`), night-transit
203
+ Sankranti dates (+ a new `moment` field on `SankrantiEvent`), kshaya-Dwadashi
204
+ Ekadashi advance, Vijayadashami/Karva Chauth/Janmashtami kala rules, the
205
+ Kali Yuga year boundary, `scoreMuhurta` special-yoga parity, eastern-
206
+ longitude Gulika/Mandi, and the opt-in Ashtakavarga reductions. See the
207
+ CHANGELOG for each rule and its drik evidence.
208
+
209
+ ---
210
+
211
+ ## Upgrading from 5.0
212
+
213
+ One deliberate type break, two corrected dasha tables, and one opt-in flag.
214
+
215
+ ### `inauspicious.varjyam` is now `TimePeriod[]`
216
+
217
+ ```diff
218
+ - if (r.inauspicious.varjyam) show(r.inauspicious.varjyam);
219
+ + r.inauspicious.varjyam.forEach(show); // [] when the day has none
220
+ ```
221
+
222
+ 5.0 evaluated only the nakshatra active at sunrise and dropped the second
223
+ Varjyam window printed panchangs show on transition days. 5.1 publishes every
224
+ window, in start order, under DrikPanchang's attribution rule: a window belongs
225
+ to the Hindu day its **start** falls in (one that begins before sunrise and
226
+ runs past it is yesterday's), and window instants are unclamped — an end can
227
+ land after next sunrise. Validated window-for-window against a 61-day
228
+ DrikPanchang sweep (Aug–Sep 2026, two full nakshatra cycles): 62/62 match.
229
+
230
+ Two value-level corrections ride along: **Mula carries a second tyajya spell**
231
+ (elapsed ghatikas 20 *and* 56 — DrikPanchang, ProKerala and B.V. Raman's
232
+ *Muhurta* concur), so Mula days now emit the window 5.0 missed; and the
233
+ standalone `computeVarjyam` primitive returns the *earliest* of a nakshatra's
234
+ spells overlapping the day. New export: `computeVarjyamWindows(sunriseUtc,
235
+ nextSunriseUtc, getMoon)`.
236
+
237
+ ### Yogini and Ashtottari starting lords were wrong — now classical
238
+
239
+ - **Yogini** used `nakshatraIndex % 8`, off by three Yoginis for every birth.
240
+ Now the classical Devi-Bhagavata formula — (1-based janma nakshatra + 3) mod
241
+ 8; remainder 1 = Mangala … 0 = Sankata — so Ashwini → Bhramari, Pushya →
242
+ Dhanya. Verified against published worked examples and PyJHora.
243
+ - **Ashtottari** used a years-proportional split of the zodiac from a Krittika
244
+ anchor, matching no source. Now the classical Ardradi **group table**
245
+ (malefics rule four nakshatras each, benefics three; Sun = Ardra…Ashlesha,
246
+ Venus = Krittika…Mrigashira; exported as `ASHTOTTARI_NAKSHATRA_GROUPS`),
247
+ with the balance from the elapsed fraction of the group. Verified against
248
+ PyJHora and Maitreya 8, which agree on every output.
249
+
250
+ Both functions keep their signatures; recorded outputs from 5.0 will differ
251
+ and should be discarded.
252
+
253
+ ### Opt-in Gana-dosha cancellation in `computeAshtakoot`
254
+
255
+ ```typescript
256
+ computeAshtakoot(boy, girl, { ganaCancellation: true });
257
+ ```
258
+
259
+ Default output is byte-identical to 5.0 (DrikPanchang's published 36-guna
260
+ table applies no Gana cancellation, and drik parity stays the default
261
+ standard). With the flag raised, a doshic Gana score (≤ 1) is restored to the
262
+ full 6 when the two Moons' sign lords are the same graha or mutual naisargika
263
+ friends, recorded in `cancellations` — the condition set attested across
264
+ independent pandit corpora; weaker ones are documented on `AshtakootOptions`
265
+ and deliberately not encoded.
266
+
267
+ ---
268
+
133
269
  ## Upgrading from 4.x
134
270
 
135
271
  Three changes move numbers that 4.x produced, and one option is gone.
@@ -395,7 +531,8 @@ For `getInstantPanchang`: `tithi` / `nakshatra` / `yoga` / `karana` / `vara` →
395
531
  `| null` for `bhadra` / `varjyam` / `eclipse`, `?`-optional for `chandraBalam` /
396
532
  `tarabala`, and an empty array for `panchakaRahita` / `festivals`. v5 has one
397
533
  rule: **every field is always present**, a value that does not apply is `null`,
398
- and a collection that does not apply is `[]`.
534
+ and a collection that does not apply is `[]`. (Since 5.1, `varjyam` is a
535
+ collection and follows the `[]` arm — see [Upgrading from 5.0](#upgrading-from-50).)
399
536
 
400
537
  ```diff
401
538
  - if ('chandraBalam' in r) … // 4.x: field absent without janmaRashi
@@ -637,6 +774,8 @@ import {
637
774
 
638
775
  computeAshtakoot({ rashi: 4, nakshatra: 9 }, { rashi: 0, nakshatra: 1 });
639
776
  // → { totalScore: 0..36, koots: KootScore[8], cancellations: string[] }
777
+ // Opt-in Gana-dosha cancellation (default off — preserves drik 36-guna parity):
778
+ computeAshtakoot(boy, girl, { ganaCancellation: true });
640
779
 
641
780
  computeMangalCompatibility(boyChart, girlChart); // Manglik is a PAIRWISE verdict
642
781
  computeKaalSarp(d1); // 12 subtypes by Rahu's house
@@ -738,7 +877,7 @@ InteractionManager.runAfterInteractions(() => {
738
877
 
739
878
  📖 [Full accuracy notes →](https://dharmagya.app/docs/panchang-ts/accuracy)
740
879
 
741
- 8,368 tests across 121 files, including fixtures cross-verified against reference
880
+ 8,737 tests across 136 files, including fixtures cross-verified against reference
742
881
  panchang calculations spanning 2025–2026 across 10 Indian cities plus New York,
743
882
  London, Sydney, Dubai, Singapore (diaspora fixtures cover DST on
744
883
  `America/New_York`).
@@ -755,6 +894,7 @@ London, Sydney, Dubai, Singapore (diaspora fixtures cover DST on
755
894
  | Lagna sidereal longitude | Cross-checked against Jagannath Hora reference charts |
756
895
  | D1 / D9 house placement | Exact match vs reference for 9-graha placement |
757
896
  | Ashtakoot total | ±1 point per pair across 30+ matched pairs |
897
+ | Varjyam windows | count + position vs DrikPanchang over a 61-day / two-nakshatra-cycle sweep, ≤2 min (62/62 windows) |
758
898
  | Sade Sati arc start/end | ±1–2 days vs authoritative ephemerides |
759
899
 
760
900
  **Festival dating** uses tithi-at-sunrise; a few festivals have authorities on
@@ -764,8 +904,9 @@ madhyahna-vyapini for Ganesh Chaturthi edge years) where output can drift
764
904
  [documented](https://dharmagya.app/docs/panchang-ts/accuracy#festival-tradeoff).
765
905
 
766
906
  **Detection conventions:** Aadal / Vidaal follow the classical Moon-from-Sun
767
- nakshatra-distance rule, not the Tamil-Vakya weekday rule. Varjyam emits the
768
- sunrise-anchored nakshatra's window only. Do Ghati does not rotate by weekday.
907
+ nakshatra-distance rule, not the Tamil-Vakya weekday rule. Varjyam lists every
908
+ window whose start falls in the Hindu day (Drik's attribution; Mula carries two
909
+ tyajya spells). Do Ghati does not rotate by weekday.
769
910
 
770
911
  ---
771
912