panchanga 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,132 @@
1
+ /**
2
+ * src/eclipses.ts — grahaṇa (solar & lunar eclipses).
3
+ *
4
+ * Wraps astronomy-engine's eclipse search to enumerate the eclipses of a given
5
+ * year, with their contact timings, type, local visibility, and sūtak window.
6
+ *
7
+ * Conventions:
8
+ * • A grahaṇa "counts" for a location only when it is VISIBLE there — a lunar
9
+ * eclipse when the Moon is above the horizon during the umbral/penumbral
10
+ * phase, a solar eclipse when the Sun is above the horizon and the disc is
11
+ * obscured. Sūtak (the abstention period) applies only to a visible eclipse.
12
+ * • Sūtak begins before first contact: 9 hours (3 prahara) for a Chandra
13
+ * Grahaṇa, 12 hours (4 prahara) for a Sūrya Grahaṇa, and runs to mokṣa (last
14
+ * contact). This is the widely-used Smārta convention.
15
+ *
16
+ * Timings are UTC instants. Lunar contact times are derived from the eclipse
17
+ * peak and astronomy-engine's semi-durations (sd_*, in minutes).
18
+ */
19
+ import { SearchLunarEclipse, NextLunarEclipse, SearchGlobalSolarEclipse, NextGlobalSolarEclipse, SearchLocalSolarEclipse, Equator, Horizon, Observer, Body, MakeTime, } from "astronomy-engine";
20
+ import { validateLocation } from "./time.js";
21
+ const MIN_MS = 60_000;
22
+ const HOUR_MS = 3_600_000;
23
+ const iso = (d) => d.toISOString();
24
+ const isoWin = (start, end) => ({ start: iso(start), end: iso(end) });
25
+ /** Altitude (degrees) of `body` at instant `when` as seen from `loc`. */
26
+ function altitude(body, when, loc) {
27
+ const t = MakeTime(when);
28
+ const obs = new Observer(loc.latitude, loc.longitude, loc.elevationMeters ?? 0);
29
+ const eq = Equator(body, t, obs, true, true);
30
+ return Horizon(t, obs, eq.ra, eq.dec, "normal").altitude;
31
+ }
32
+ /**
33
+ * True if the Moon is above the horizon at ANY of `samples` evenly-spaced
34
+ * instants across `[start, end]` (inclusive) as seen from `loc`. A lunar
35
+ * grahaṇa is reckoned visible when the Moon is up during the eclipse — sampling
36
+ * across the whole phase (not just greatest eclipse) catches a moonrise/moonset
37
+ * eclipse, where the Moon is below the horizon at peak yet the eclipse is in
38
+ * progress as it rises or sets.
39
+ */
40
+ function moonUpDuring(start, end, loc, samples = 9) {
41
+ const a = new Date(start).getTime();
42
+ const b = new Date(end).getTime();
43
+ for (let i = 0; i < samples; i++) {
44
+ const when = new Date(a + ((b - a) * i) / (samples - 1));
45
+ if (altitude(Body.Moon, when, loc) > 0)
46
+ return true;
47
+ }
48
+ return false;
49
+ }
50
+ /** All lunar eclipses whose peak falls in calendar `year` (UTC). */
51
+ export function lunarEclipses(year, loc) {
52
+ if (loc)
53
+ validateLocation(loc);
54
+ const out = [];
55
+ const yearStart = Date.UTC(year, 0, 1);
56
+ const yearEnd = Date.UTC(year + 1, 0, 1);
57
+ let e = SearchLunarEclipse(new Date(yearStart));
58
+ // Guard against an eclipse found just before the year boundary.
59
+ for (let i = 0; i < 30 && e.peak.date.getTime() < yearStart; i++)
60
+ e = NextLunarEclipse(e.peak);
61
+ for (let i = 0; i < 30 && e.peak.date.getTime() < yearEnd; i++) {
62
+ const peak = e.peak.date;
63
+ const span = (sdMin) => isoWin(new Date(peak.getTime() - sdMin * MIN_MS), new Date(peak.getTime() + sdMin * MIN_MS));
64
+ const penumbral = span(e.sd_penum);
65
+ const partial = e.sd_partial > 0 ? span(e.sd_partial) : null;
66
+ const total = e.sd_total > 0 ? span(e.sd_total) : null;
67
+ // Reckon visibility across the whole eclipse, not just greatest eclipse:
68
+ // the umbral (partial) window for an umbral eclipse, else the penumbral
69
+ // window. This way a moonrise/moonset eclipse — Moon below the horizon at
70
+ // peak but up during the umbral phase — is correctly counted as visible.
71
+ const reckonWindow = partial ?? penumbral;
72
+ const visible = loc ? moonUpDuring(reckonWindow.start, reckonWindow.end, loc) : null;
73
+ // Sūtak applies only to a grahaṇa with an UMBRAL phase. A purely penumbral
74
+ // (māndya / upacchāyā) lunar eclipse is not reckoned as a grahaṇa in the
75
+ // Smārta convention, so it carries no sūtak; and for umbral eclipses the
76
+ // window is reckoned from the umbral (partial) contacts, not the penumbral.
77
+ const sutak = visible && partial
78
+ ? isoWin(new Date(new Date(partial.start).getTime() - 9 * HOUR_MS), new Date(partial.end))
79
+ : null;
80
+ out.push({
81
+ kind: e.kind,
82
+ peak: iso(peak),
83
+ penumbral,
84
+ partial,
85
+ total,
86
+ visible,
87
+ sutak,
88
+ });
89
+ e = NextLunarEclipse(e.peak);
90
+ }
91
+ return out;
92
+ }
93
+ /** All solar eclipses whose greatest-eclipse instant falls in calendar `year`. */
94
+ export function solarEclipses(year, loc) {
95
+ if (loc)
96
+ validateLocation(loc);
97
+ const out = [];
98
+ const yearStart = Date.UTC(year, 0, 1);
99
+ const yearEnd = Date.UTC(year + 1, 0, 1);
100
+ let e = SearchGlobalSolarEclipse(new Date(yearStart));
101
+ for (let i = 0; i < 30 && e.peak.date.getTime() < yearStart; i++)
102
+ e = NextGlobalSolarEclipse(e.peak);
103
+ for (let i = 0; i < 30 && e.peak.date.getTime() < yearEnd; i++) {
104
+ const peak = e.peak.date;
105
+ let local = null;
106
+ let visible = loc ? false : null;
107
+ let sutak = null;
108
+ if (loc) {
109
+ const obs = new Observer(loc.latitude, loc.longitude, loc.elevationMeters ?? 0);
110
+ // Search a local eclipse around the global peak; accept it only if it is
111
+ // the SAME event (its peak is within a day) and the Sun is up & obscured.
112
+ const lse = SearchLocalSolarEclipse(new Date(peak.getTime() - 24 * HOUR_MS), obs);
113
+ const within = Math.abs(lse.peak.time.date.getTime() - peak.getTime()) < 24 * HOUR_MS;
114
+ if (within && lse.partial_begin && lse.peak.altitude > 0 && lse.obscuration > 0) {
115
+ const partialStart = lse.partial_begin.time.date;
116
+ const partialEnd = lse.partial_end.time.date;
117
+ local = {
118
+ partialStart: iso(partialStart),
119
+ peak: iso(lse.peak.time.date),
120
+ partialEnd: iso(partialEnd),
121
+ obscuration: lse.obscuration,
122
+ };
123
+ visible = true;
124
+ sutak = isoWin(new Date(partialStart.getTime() - 12 * HOUR_MS), partialEnd);
125
+ }
126
+ }
127
+ out.push({ kind: e.kind, peak: iso(peak), local, visible, sutak });
128
+ e = NextGlobalSolarEclipse(e.peak);
129
+ }
130
+ return out;
131
+ }
132
+ //# sourceMappingURL=eclipses.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eclipses.js","sourceRoot":"","sources":["../src/eclipses.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,230 @@
1
+ /**
2
+ * src/elements.ts — calendar-elements core: tithi, nakshatra, karaṇa/Bhadra,
3
+ * new moons, solar ingress (saṅkrānti), and amānta/pūrṇimānta lunar months.
4
+ *
5
+ * SOURCING (the two fiddly conventions are pinned to authorities, not guessed):
6
+ *
7
+ * • KARAṆA SEQUENCE — Wikipedia "Karaṇa (pañcāṅga)"
8
+ * https://en.wikipedia.org/wiki/Karana_(pancanga)
9
+ * A karaṇa is half a tithi: the span over which Moon−Sun elongation grows 6°.
10
+ * A lunar month (0°…360° elongation) has 60 half-tithis, indexed h = 0..59:
11
+ * h = 0 → Kiṁstughna (fixed)
12
+ * h = 1..56 → the 7 movable karaṇas cycling with
13
+ * ((h−1) mod 7) over
14
+ * [Bava, Bālava, Kaulava, Taitila, Gara,
15
+ * Vaṇij, Viṣṭi] (8 full cycles = 56)
16
+ * h = 57 → Śakuni, 58 → Catuṣpāda, 59 → Nāga (fixed)
17
+ * Viṣṭi ≡ Bhadra. The Mukha/Pucchā subdivision + Vāsa is `bhadraSplit`;
18
+ * `bhadraIntervals` returns the whole Viṣṭi span it operates on.
19
+ *
20
+ * • LUNAR-MONTH NAMING / ADHIKA / KṢAYA — Wikipedia "Hindu calendar" &
21
+ * "Adhika-masa" (https://en.wikipedia.org/wiki/Adhika-masa,
22
+ * https://en.wikipedia.org/wiki/Hindu_calendar), consistent with
23
+ * drikpanchang's adhika-masa definition.
24
+ * An amānta lunation (new moon → next new moon) is named after the rāśi the
25
+ * Sun ENTERS (the saṅkrānti) DURING that lunation:
26
+ * Mesha saṅkrānti → Chaitra, Vṛṣabha → Vaiśākha, Mithuna → Jyeṣṭha, …
27
+ * i.e. month-name-index (0=Chaitra) = entered-rāśi-index (0=Mesha).
28
+ * • A lunation with NO saṅkrānti is **adhika** (leap): it takes the name of
29
+ * the FOLLOWING lunation's saṅkrānti, prefixed "Adhika"; the following
30
+ * lunation is then "Nija/Śuddha". (Algorithmically: an adhika lunation
31
+ * inherits the next lunation's month name.)
32
+ * • A lunation with TWO saṅkrāntis is **kṣaya** (lost month, ~1/140 yr).
33
+ *
34
+ * • PŪRṆIMĀNTA label — derived from the amānta result. A pūrṇimānta month runs
35
+ * full-moon → full-moon, so its kṛṣṇa-pakṣa (waning) half belongs to the
36
+ * amānta month one NAME EARLIER. Concretely: in the kṛṣṇa pakṣa the
37
+ * pūrṇimānta name = next amānta name; in the śukla pakṣa they coincide.
38
+ * Dates do not change — only the label.
39
+ *
40
+ * ASTRONOMY PRIMITIVES
41
+ * • Elongation = geocentric Moon−Sun ecliptic-longitude difference in [0,360):
42
+ * Astronomy.PairLongitude(Body.Moon, Body.Sun, date) (== MoonPhase(date)).
43
+ * • Tithi / karaṇa / new-moon boundaries via Astronomy.SearchMoonPhase(target,
44
+ * start, limitDays) — robust against intra-day non-monotonicity.
45
+ * • Nakshatra & saṅkrānti use the SIDEREAL longitudes from ayanamsha.ts
46
+ * (siderealLongitude / siderealSunRashi), kept consistent with Drik Panchang.
47
+ */
48
+ import { type FlexibleDateTime } from "astronomy-engine";
49
+ /** The 30 tithi names (1-based: index 0 = tithi 1 = Pratipadā). */
50
+ export declare const TITHI_NAMES: readonly ["Pratipada", "Dvitiya", "Tritiya", "Chaturthi", "Panchami", "Shashthi", "Saptami", "Ashtami", "Navami", "Dashami", "Ekadashi", "Dvadashi", "Trayodashi", "Chaturdashi", "Purnima", "Pratipada", "Dvitiya", "Tritiya", "Chaturthi", "Panchami", "Shashthi", "Saptami", "Ashtami", "Navami", "Dashami", "Ekadashi", "Dvadashi", "Trayodashi", "Chaturdashi", "Amavasya"];
51
+ /** The 27 nakshatra names (index 0 = Ashwini; Rohini = 3). */
52
+ export declare const NAKSHATRA_NAMES: readonly ["Ashwini", "Bharani", "Krittika", "Rohini", "Mrigashira", "Ardra", "Punarvasu", "Pushya", "Ashlesha", "Magha", "Purva Phalguni", "Uttara Phalguni", "Hasta", "Chitra", "Swati", "Vishakha", "Anuradha", "Jyeshtha", "Mula", "Purva Ashadha", "Uttara Ashadha", "Shravana", "Dhanishta", "Shatabhisha", "Purva Bhadrapada", "Uttara Bhadrapada", "Revati"];
53
+ /** The 7 movable (cara) karaṇas, in cyclic order. Viṣṭi (index 6) ≡ Bhadra. */
54
+ export declare const MOVABLE_KARANAS: readonly ["Bava", "Balava", "Kaulava", "Taitila", "Gara", "Vanij", "Vishti"];
55
+ /** Karaṇa name for a half-tithi index h ∈ 0..59 (see file header for sourcing). */
56
+ export declare function karanaName(h: number): string;
57
+ /**
58
+ * The 12 amānta lunar-month names, indexed by the rāśi the Sun enters:
59
+ * index 0 = Mesha → Chaitra, … index 11 = Mīna → Phalguna.
60
+ */
61
+ export declare const LUNAR_MONTH_NAMES: readonly ["Chaitra", "Vaishakha", "Jyeshtha", "Ashadha", "Shravana", "Bhadrapada", "Ashwina", "Kartika", "Margashirsha", "Pausha", "Magha", "Phalguna"];
62
+ /**
63
+ * Geocentric Moon−Sun ecliptic-longitude elongation in [0,360).
64
+ * 0 = new moon (conjunction), 180 = full moon.
65
+ */
66
+ export declare function elongation(date: FlexibleDateTime): number;
67
+ /**
68
+ * Tithi number 1..30 containing `date`.
69
+ * Tithi n spans elongation [(n−1)·12°, n·12°). 1 = Śukla Pratipadā … 30 = Amāvāsyā.
70
+ */
71
+ export declare function tithiAt(date: FlexibleDateTime): number;
72
+ export interface TithiBoundaries {
73
+ /** Tithi number 1..30. */
74
+ number: number;
75
+ /** UTC instant the tithi begins (elongation = (n−1)·12°). */
76
+ start: Date;
77
+ /** UTC instant the tithi ends (elongation = n·12°). */
78
+ end: Date;
79
+ }
80
+ /**
81
+ * Boundaries of the tithi containing `around`.
82
+ *
83
+ * Tithi n occupies elongation [(n−1)·12°, n·12°). We locate the start by
84
+ * searching backward for the (n−1)·12° phase and the end by searching forward
85
+ * for the n·12° phase (mod 360). The new-moon wrap is handled because phase
86
+ * 0° ≡ 360°: tithi 30 ends at phase 0 (the next new moon) and tithi 1 starts
87
+ * at phase 0 (the same new moon), so the SearchMoonPhase target is taken mod
88
+ * 360 and the wrap is seamless.
89
+ */
90
+ export declare function tithiBoundaries(around: FlexibleDateTime): TithiBoundaries;
91
+ /**
92
+ * Nakshatra index 0..26 of the Moon at `date` (0 = Ashwini; Rohini = 3).
93
+ * Each nakshatra spans 360/27 = 13°20′ of the Moon's sidereal longitude.
94
+ */
95
+ export declare function nakshatraAt(date: FlexibleDateTime): number;
96
+ export interface NakshatraBoundaries {
97
+ /** Nakshatra index 0..26 (0 = Ashwini). */
98
+ index: number;
99
+ /** UTC instant the Moon enters this nakshatra. */
100
+ start: Date;
101
+ /** UTC instant the Moon leaves this nakshatra. */
102
+ end: Date;
103
+ }
104
+ /**
105
+ * Boundaries of the nakshatra the Moon occupies at `around`.
106
+ *
107
+ * The Moon's sidereal longitude advances ~13.2°/day and is monotonic within a
108
+ * nakshatra, so each 13°20′ boundary is a clean single crossing. We bracket
109
+ * the start-edge by stepping back ~1.5 days and the end-edge forward ~1.5 days
110
+ * (a nakshatra lasts ~24 h) and bisect each crossing.
111
+ */
112
+ export declare function nakshatraBoundaries(around: FlexibleDateTime): NakshatraBoundaries;
113
+ /** The 27 nitya-yoga names (index 0 = Vishkambha … 26 = Vaidhriti). */
114
+ export declare const YOGA_NAMES: readonly ["Vishkambha", "Priti", "Ayushman", "Saubhagya", "Shobhana", "Atiganda", "Sukarman", "Dhriti", "Shula", "Ganda", "Vriddhi", "Dhruva", "Vyaghata", "Harshana", "Vajra", "Siddhi", "Vyatipata", "Variyan", "Parigha", "Shiva", "Siddha", "Sadhya", "Shubha", "Shukla", "Brahma", "Indra", "Vaidhriti"];
115
+ /**
116
+ * Yoga index 0..26 at `date` (0 = Vishkambha; 26 = Vaidhriti).
117
+ * Each nitya-yoga spans 360/27 = 13°20′ of (Sun + Moon) sidereal longitude.
118
+ */
119
+ export declare function yogaAt(date: FlexibleDateTime): number;
120
+ export interface YogaBoundaries {
121
+ /** Yoga index 0..26 (0 = Vishkambha). */
122
+ index: number;
123
+ /** UTC instant this yoga begins. */
124
+ start: Date;
125
+ /** UTC instant this yoga ends. */
126
+ end: Date;
127
+ }
128
+ /**
129
+ * Boundaries of the yoga at `around`. The (Sun+Moon) sidereal sum advances
130
+ * monotonically (~14.2°/day), so a yoga lasts ~22–25 h; ±2 days brackets the
131
+ * adjacent boundaries safely and we bisect each crossing (the 360°→0° wrap for
132
+ * Vaidhriti→Vishkambha is handled by `bisectLongitudeCrossing`, exactly as for
133
+ * the Revati→Ashwini nakshatra wrap).
134
+ */
135
+ export declare function yogaBoundaries(around: FlexibleDateTime): YogaBoundaries;
136
+ /**
137
+ * Half-tithi index h ∈ 0..59 at `date` (h = floor(elongation/6°)), i.e. the
138
+ * karaṇa slot within the current lunation.
139
+ */
140
+ export declare function karanaIndexAt(date: FlexibleDateTime): number;
141
+ /** Karaṇa name at `date` (see karanaName / file header for the sequence). */
142
+ export declare function karanaAt(date: FlexibleDateTime): string;
143
+ export interface KaranaBoundaries {
144
+ /** Half-tithi index 0..59 within the lunation. */
145
+ index: number;
146
+ /** Karaṇa name (Bava … Naga). */
147
+ name: string;
148
+ /** UTC instant this karaṇa begins (elongation = h·6°). */
149
+ start: Date;
150
+ /** UTC instant this karaṇa ends (elongation = (h+1)·6°). */
151
+ end: Date;
152
+ }
153
+ /**
154
+ * Boundaries of the karaṇa (half-tithi) containing `around`. Mirrors
155
+ * `tithiBoundaries` on a 6° grid: a karaṇa spans elongation [h·6°, (h+1)·6°),
156
+ * so we locate the start at h·6° (backward) and the end at (h+1)·6° (forward).
157
+ * The new-moon wrap (h=59 ends at phase 0°) is seamless because the target is
158
+ * taken mod 360.
159
+ */
160
+ export declare function karanaBoundaries(around: FlexibleDateTime): KaranaBoundaries;
161
+ export interface KaranaInterval {
162
+ start: Date;
163
+ end: Date;
164
+ }
165
+ /**
166
+ * Viṣṭi (Bhadra) karaṇa interval(s) near `around`.
167
+ *
168
+ * Viṣṭi is the 7th movable karaṇa, so it falls at half-tithi indices h where
169
+ * ((h−1) mod 7) === 6 and h ∈ 1..56, i.e. h ∈ {7, 14, 21, 28, 35, 42, 49, 56}.
170
+ * Each such karaṇa is the elongation span [h·6°, (h+1)·6°). Within a lunar
171
+ * month Bhadra therefore occurs once per pakṣa-ish (8 times across a lunation).
172
+ *
173
+ * This scans a window of ±SYNODIC_MONTH_DAYS around `around`, locates every
174
+ * Viṣṭi slot via SearchMoonPhase on the 6° multiples, and returns each
175
+ * {start,end} (UTC) that overlaps the window. Adjacent to a date this yields
176
+ * the Bhadra window(s) on/near that date.
177
+ *
178
+ * NOTE: this returns the whole Viṣṭi karaṇa span. The Mukha/Pucchā "face/tail"
179
+ * subdivision and the Vāsa (loka) used for Holikā Dahan muhūrta are computed by
180
+ * `bhadraSplit`, which takes one of these intervals.
181
+ */
182
+ export declare function bhadraIntervals(around: FlexibleDateTime): KaranaInterval[];
183
+ /** Where Bhadra resides — its loka, from the Moon's rāśi during Bhadra. */
184
+ export type BhadraVasa = "svarga" | "prithvi" | "patala";
185
+ export interface BhadraDetails {
186
+ /** Loka: svarga (heaven), prithvi (earth/bhūmi, the harmful one), patala. */
187
+ vasa: BhadraVasa;
188
+ /**
189
+ * The Moon's sidereal rāśi (0 = Mesha … 11 = Mīna) during Bhadra, sampled at
190
+ * the interval MIDPOINT. The vāsa is reckoned from the rāśi the Moon occupies
191
+ * *during* Bhadra; the midpoint is the representative instant (an endpoint can
192
+ * fall on the wrong side of a rāśi change that occurs within the span).
193
+ */
194
+ moonRashi: number;
195
+ /** Bhadra Mukha — inauspicious leading 1/6 (5 ghaṭī of a 30-ghaṭī karaṇa). */
196
+ mukha: KaranaInterval;
197
+ /** Bhadra Pucchā — auspicious trailing 1/10 (3 ghaṭī of a 30-ghaṭī karaṇa). */
198
+ puccha: KaranaInterval;
199
+ }
200
+ /**
201
+ * Split a Bhadra (Viṣṭi karaṇa) `interval` into its Mukha (face) and Pucchā
202
+ * (tail) sub-windows and resolve its Vāsa from the Moon's rāśi at Bhadra's
203
+ * start. See the sourcing note above. PURE w.r.t. its argument + ephemeris.
204
+ */
205
+ export declare function bhadraSplit(interval: KaranaInterval): BhadraDetails;
206
+ export declare function newMoons(year: number): Date[];
207
+ export declare function solarIngress(year: number, rashi: number): Date;
208
+ export type MonthSystem = "amanta" | "purnimanta";
209
+ export interface LunarMonth {
210
+ /** Month name index 0..11 (0 = Chaitra). The label for the chosen system. */
211
+ month: number;
212
+ /** Month name (label for `system`). */
213
+ monthName: string;
214
+ /** "shukla" (waxing) or "krishna" (waning). */
215
+ paksha: "shukla" | "krishna";
216
+ /** True if this lunation is an adhika (leap) month. */
217
+ adhika: boolean;
218
+ /** True if this lunation is a kṣaya (lost) month (two saṅkrāntis). */
219
+ kshaya: boolean;
220
+ /** Amānta month name index 0..11 (independent of the chosen system). */
221
+ amantaMonth: number;
222
+ /** Amānta label (with "Adhika"/"Nija" prefix where applicable). */
223
+ amantaLabel: string;
224
+ /** Pūrṇimānta label (with prefix where applicable). */
225
+ purnimantaLabel: string;
226
+ }
227
+ export declare function lunarMonth(at: FlexibleDateTime, options?: {
228
+ system?: MonthSystem;
229
+ }): LunarMonth;
230
+ //# sourceMappingURL=elements.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elements.d.ts","sourceRoot":"","sources":["../src/elements.ts"],"names":[],"mappings":"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"}