panchang-ts 4.1.1 → 4.3.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 +198 -4
- package/dist/calendar/eclipsesTable.cjs +404 -0
- package/dist/calendar/eclipsesTable.d.cts +40 -0
- package/dist/calendar/eclipsesTable.d.ts +40 -0
- package/dist/calendar/eclipsesTable.js +399 -0
- package/dist/calendar/festivalsTable.cjs +25358 -0
- package/dist/calendar/festivalsTable.d.cts +39 -0
- package/dist/calendar/festivalsTable.d.ts +39 -0
- package/dist/calendar/festivalsTable.js +25353 -0
- package/dist/calendar/moonPhasesTable.cjs +6811 -0
- package/dist/calendar/moonPhasesTable.d.cts +37 -0
- package/dist/calendar/moonPhasesTable.d.ts +37 -0
- package/dist/calendar/moonPhasesTable.js +6806 -0
- package/dist/eclipsesTableTypes-D-tSQMQd.d.cts +98 -0
- package/dist/eclipsesTableTypes-D-tSQMQd.d.ts +98 -0
- package/dist/festivalsTableTypes-GePaspwd.d.cts +52 -0
- package/dist/festivalsTableTypes-GePaspwd.d.ts +52 -0
- package/dist/index.cjs +490 -23
- package/dist/index.d.cts +211 -1
- package/dist/index.d.ts +211 -1
- package/dist/index.js +485 -24
- package/dist/moonPhasesTableTypes-TH0T5rVD.d.cts +56 -0
- package/dist/moonPhasesTableTypes-TH0T5rVD.d.ts +56 -0
- package/package.json +36 -2
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
Pure TypeScript Hindu Panchang (almanac), Jyotish, and Birth Chart calculations.
|
|
6
6
|
Zero native dependencies. Works offline in React Native (Hermes), Node.js, and browsers.
|
|
7
7
|
|
|
8
|
-
**Fast** (~0.1 ms names-only, ~0.5 ms full) · **Typed** (full TypeScript) · **Offline** (pure JS math) · **8,
|
|
8
|
+
**Fast** (~0.1 ms names-only, ~0.5 ms full) · **Typed** (full TypeScript) · **Offline** (pure JS math) · **8,164 tests across 100 files**
|
|
9
9
|
|
|
10
10
|
---
|
|
11
11
|
|
|
@@ -262,6 +262,80 @@ getDailyPanchang(jan13, amritsar, { timezone: 330, region: 'punjab' })!
|
|
|
262
262
|
legacy slugs `'tamil'`, `'bengal'`, `'north-india'` are still accepted and
|
|
263
263
|
mapped internally.
|
|
264
264
|
|
|
265
|
+
### Pre-computed table (bundled, India / IST)
|
|
266
|
+
|
|
267
|
+
If you want festival *dates* without running the engine, import the static
|
|
268
|
+
table at `panchang-ts/festivals`. It bundles a rolling **2-years-past /
|
|
269
|
+
5-years-future** window pre-computed against Varanasi (IST). Within India
|
|
270
|
+
these dates are essentially universal.
|
|
271
|
+
|
|
272
|
+
```typescript
|
|
273
|
+
import {
|
|
274
|
+
getFestivalsForYear,
|
|
275
|
+
getFestivalsForDate,
|
|
276
|
+
FESTIVALS_META,
|
|
277
|
+
FESTIVALS_YEAR_RANGE,
|
|
278
|
+
} from 'panchang-ts/festivals';
|
|
279
|
+
|
|
280
|
+
const yr = FESTIVALS_YEAR_RANGE.start; // e.g. { start: 2024, end: 2031 }
|
|
281
|
+
getFestivalsForYear(yr)!.length; // ~150 festival days
|
|
282
|
+
const diwali = getFestivalsForYear(yr)!
|
|
283
|
+
.find(d => d.festivals.some(f => f.name === 'Diwali'))!.date;
|
|
284
|
+
getFestivalsForDate(diwali); // [Narak Chaturdashi, Diwali]
|
|
285
|
+
getFestivalsForDate(diwali, 'hi'); // [नरक चतुर्दशी, दिवाली]
|
|
286
|
+
FESTIVALS_META.referenceLocation; // "Varanasi"
|
|
287
|
+
FESTIVALS_META.languages; // ["en", "hi"]
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
This entry point is engine-free — it ships only the JSON + accessors, so
|
|
291
|
+
importing it won't pull the calculation engine into your bundle. Both `en`
|
|
292
|
+
and `hi` are bundled (names *and* descriptions); pass the locale as the
|
|
293
|
+
second argument. Eclipses are excluded here (visibility is location-dependent)
|
|
294
|
+
— they ship as their own bundled table at `panchang-ts/eclipses` (see
|
|
295
|
+
[Eclipses](#eclipses)).
|
|
296
|
+
|
|
297
|
+
### Festivals outside India — build a location table and cache it
|
|
298
|
+
|
|
299
|
+
The bundled table is **IST-only**. Elsewhere (Europe, North America, rest
|
|
300
|
+
of world) festival dates can shift by ±1 day, because canonical times
|
|
301
|
+
(nishita / pradosha / chandrodaya …) are observer-dependent — and the shift
|
|
302
|
+
tracks the timezone offset, not the "region", so a single per-continent
|
|
303
|
+
table would mis-date boundary-day festivals.
|
|
304
|
+
|
|
305
|
+
For an offline app serving users worldwide, the right pattern is
|
|
306
|
+
**compute-once-then-cache for the user's actual location**. Build a
|
|
307
|
+
location-specific table with `buildFestivalsTable` (from the main entry —
|
|
308
|
+
it uses the engine), persist the returned JSON, then read it back through
|
|
309
|
+
the same accessors via their `source` argument:
|
|
310
|
+
|
|
311
|
+
```typescript
|
|
312
|
+
import { buildFestivalsTable } from 'panchang-ts';
|
|
313
|
+
import { getFestivalsForYear, getFestivalsForDate } from 'panchang-ts/festivals';
|
|
314
|
+
|
|
315
|
+
// On first use at the user's location (a few seconds on-device — run it in
|
|
316
|
+
// the background / chunk by year), then cache `table` to disk/MMKV.
|
|
317
|
+
const table = buildFestivalsTable({
|
|
318
|
+
location: { latitude: 40.7128, longitude: -74.006 },
|
|
319
|
+
timezoneOffsetMinutes: -300, // US Eastern (EST); 0 = UK, 330 = IST
|
|
320
|
+
startYear: 2024,
|
|
321
|
+
endYear: 2031,
|
|
322
|
+
languages: ['en'], // omit hi to halve the size
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
// Later reads are instant lookups against the cached table:
|
|
326
|
+
getFestivalsForYear(2026, 'en', table);
|
|
327
|
+
getFestivalsForDate('2026-11-08', 'en', table); // key is in the table's tz
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
`buildFestivalsTable` returns the same `FestivalsFile` shape as the bundled
|
|
331
|
+
data, so a cached table and the bundled India table are interchangeable as
|
|
332
|
+
the `source` argument. India-majority apps can lean on the bundled table for
|
|
333
|
+
zero first-load latency and only compute-and-cache for non-IST users.
|
|
334
|
+
|
|
335
|
+
**Other notes:** Karva Chauth / Dhanteras / Diwali emit with Purnimanta
|
|
336
|
+
paksha naming. To regenerate the bundled India table after a registry
|
|
337
|
+
change, run `npm run festivals:gen` (rolling window, no constants to edit).
|
|
338
|
+
|
|
265
339
|
## Eclipses
|
|
266
340
|
|
|
267
341
|
```typescript
|
|
@@ -280,6 +354,117 @@ import { getUpcomingSolarEclipse, getUpcomingLunarEclipse } from 'panchang-ts';
|
|
|
280
354
|
const next = getUpcomingSolarEclipse(new Date(), loc, 365 /* days */);
|
|
281
355
|
```
|
|
282
356
|
|
|
357
|
+
### Pre-computed table (bundled, India / IST)
|
|
358
|
+
|
|
359
|
+
Like the festivals table, eclipse data ships as a static, engine-free entry
|
|
360
|
+
at `panchang-ts/eclipses` — a rolling **2-years-past / 5-years-future** window
|
|
361
|
+
pre-computed against Varanasi (IST). It lists every eclipse **visible from
|
|
362
|
+
there during any phase** (so an eclipse already in progress at moon/sunrise or
|
|
363
|
+
moon/sunset is included); the `visibleAtPeak` flag tells you whether greatest
|
|
364
|
+
eclipse itself is observable. Within India visibility is essentially uniform.
|
|
365
|
+
|
|
366
|
+
```typescript
|
|
367
|
+
import {
|
|
368
|
+
getEclipsesForYear,
|
|
369
|
+
getEclipsesForDate,
|
|
370
|
+
ECLIPSES_META,
|
|
371
|
+
ECLIPSES_YEAR_RANGE,
|
|
372
|
+
} from 'panchang-ts/eclipses';
|
|
373
|
+
|
|
374
|
+
const e = getEclipsesForYear(2025)![0].eclipses[0];
|
|
375
|
+
e.kind; // 'lunar'
|
|
376
|
+
e.subtype; // 'total'
|
|
377
|
+
e.start; e.peak; e.end; // ISO UTC strings
|
|
378
|
+
e.magnitude; // 0..1 obscuration at peak
|
|
379
|
+
e.visibleFromLocation; // visible during any phase? (always true in bundled table)
|
|
380
|
+
e.visibleAtPeak; // is greatest eclipse itself above the horizon?
|
|
381
|
+
e.sutak; // { start, end } — see note below
|
|
382
|
+
getEclipsesForDate('2025-09-07', 'hi'); // [पूर्ण चंद्र ग्रहण]
|
|
383
|
+
ECLIPSES_META.referenceLocation; // "Varanasi"
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
Each entry carries `en` + `hi` text. Solar eclipses report the subtype seen
|
|
387
|
+
**locally** (a globally-total eclipse may read `partial` from Varanasi). The
|
|
388
|
+
`sutak` window is present only where it applies — all visible solar eclipses
|
|
389
|
+
and visible **umbral** (partial/total) lunar eclipses; **penumbral** lunar
|
|
390
|
+
eclipses carry no `sutak` and are not religiously observed (drik / pandit
|
|
391
|
+
consensus). For full astronomical detail (e.g. eclipses *not* visible in
|
|
392
|
+
India), use `getUpcomingEclipses` / `getEclipsesInRange` from the main entry.
|
|
393
|
+
|
|
394
|
+
**Outside India:** which eclipses are visible — and thus carry `sutak` —
|
|
395
|
+
differs by location. Build and cache a location-specific table with
|
|
396
|
+
`buildEclipsesTable` (main entry, uses the engine), then read it back via the
|
|
397
|
+
same accessors' `source` argument — the same compute-once-then-cache pattern
|
|
398
|
+
as festivals:
|
|
399
|
+
|
|
400
|
+
```typescript
|
|
401
|
+
import { buildEclipsesTable } from 'panchang-ts';
|
|
402
|
+
import { getEclipsesForYear } from 'panchang-ts/eclipses';
|
|
403
|
+
|
|
404
|
+
const table = buildEclipsesTable({
|
|
405
|
+
location: { latitude: 51.5074, longitude: -0.1278 },
|
|
406
|
+
timezoneOffsetMinutes: 0, // UK / GMT
|
|
407
|
+
startYear: 2024,
|
|
408
|
+
endYear: 2031,
|
|
409
|
+
// visibleOnly: false → also include eclipses below the horizon (no sutak)
|
|
410
|
+
});
|
|
411
|
+
getEclipsesForYear(2025, 'en', table);
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
To regenerate the bundled India table, run `npm run eclipses:gen` (rolling
|
|
415
|
+
window, no constants to edit).
|
|
416
|
+
|
|
417
|
+
## Moon Phases
|
|
418
|
+
|
|
419
|
+
The four principal lunar phases — **new** (Amavasya), **first quarter**,
|
|
420
|
+
**full** (Purnima), **last quarter** — as precise instants. (These are the
|
|
421
|
+
astronomical quarter moments, distinct from the same-named *tithis*, which are
|
|
422
|
+
~24h windows.)
|
|
423
|
+
|
|
424
|
+
```typescript
|
|
425
|
+
import { getMoonPhasesInRange } from 'panchang-ts';
|
|
426
|
+
const phases = getMoonPhasesInRange(new Date('2026-01-01'), new Date('2026-12-31'));
|
|
427
|
+
phases.forEach(p => console.log(p.phase, p.time.toISOString())); // ~49 / year
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
### Pre-computed table (bundled, India / IST)
|
|
431
|
+
|
|
432
|
+
Same engine-free pattern as festivals and eclipses, at `panchang-ts/moon-phases`
|
|
433
|
+
— a rolling **2-years-past / 5-years-future** window. Phases are global
|
|
434
|
+
instants; the bundled table maps each onto its **IST** calendar date (so a new
|
|
435
|
+
moon at 19:52 UTC on Jan 18 is listed under Jan 19 in India).
|
|
436
|
+
|
|
437
|
+
```typescript
|
|
438
|
+
import {
|
|
439
|
+
getMoonPhasesForYear,
|
|
440
|
+
getMoonPhasesForDate,
|
|
441
|
+
MOON_PHASES_META,
|
|
442
|
+
MOON_PHASES_YEAR_RANGE,
|
|
443
|
+
} from 'panchang-ts/moon-phases';
|
|
444
|
+
|
|
445
|
+
getMoonPhasesForYear(2026)!.length; // ~49 phase days
|
|
446
|
+
getMoonPhasesForDate('2026-01-03'); // [{ phase: 'full', name: 'Full Moon', ... }]
|
|
447
|
+
getMoonPhasesForDate('2026-01-03', 'hi'); // [{ phase: 'full', name: 'पूर्णिमा', ... }]
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
Each entry carries `phase`, the phase `time` (ISO UTC), and `en` + `hi` text.
|
|
451
|
+
For another timezone, build and cache a table with `buildMoonPhasesTable` (main
|
|
452
|
+
entry) and pass it as the accessors' `source` argument — it takes only a
|
|
453
|
+
`timezoneOffsetMinutes` (no coordinates, since phases are location-independent):
|
|
454
|
+
|
|
455
|
+
```typescript
|
|
456
|
+
import { buildMoonPhasesTable } from 'panchang-ts';
|
|
457
|
+
import { getMoonPhasesForYear } from 'panchang-ts/moon-phases';
|
|
458
|
+
|
|
459
|
+
const table = buildMoonPhasesTable({
|
|
460
|
+
timezoneOffsetMinutes: -300, // US Eastern
|
|
461
|
+
startYear: 2024, endYear: 2031,
|
|
462
|
+
});
|
|
463
|
+
getMoonPhasesForYear(2026, 'en', table);
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
Regenerate the bundled India table with `npm run moon-phases:gen`.
|
|
467
|
+
|
|
283
468
|
## Planetary Positions
|
|
284
469
|
|
|
285
470
|
```typescript
|
|
@@ -657,7 +842,7 @@ import {
|
|
|
657
842
|
convertGregorianToHindu, convertHinduToGregorian,
|
|
658
843
|
getKaliYugaYear, getHinduNewYear,
|
|
659
844
|
getEkadashiDatesForYear, getSankrantisForYear,
|
|
660
|
-
getFestivalsInRange, getUpcomingEclipses,
|
|
845
|
+
getFestivalsInRange, getUpcomingEclipses, getEclipsesInRange,
|
|
661
846
|
} from 'panchang-ts';
|
|
662
847
|
|
|
663
848
|
// Gregorian → Hindu coords at sunrise
|
|
@@ -854,6 +1039,10 @@ computeMadhyahna, computePratahSandhya, computeSayahnaSandhya
|
|
|
854
1039
|
|
|
855
1040
|
// Eclipses
|
|
856
1041
|
getUpcomingSolarEclipse, getUpcomingLunarEclipse, getEclipseDuringDay
|
|
1042
|
+
isEclipseVisibleAnyPhase
|
|
1043
|
+
|
|
1044
|
+
// Moon phases (new / quarters / full as precise instants)
|
|
1045
|
+
getMoonPhasesInRange
|
|
857
1046
|
|
|
858
1047
|
// Jyotish — planets, dashas, transits
|
|
859
1048
|
computePlanetaryPositions, GRAHA_ABBR
|
|
@@ -888,7 +1077,12 @@ aksharabhyasamRule, seemanthamRule, shopOpeningRule, travelStartRule
|
|
|
888
1077
|
// Calendar conversion + yearly listings
|
|
889
1078
|
convertGregorianToHindu, convertHinduToGregorian
|
|
890
1079
|
getKaliYugaYear, getHinduNewYear, computeSamvat
|
|
891
|
-
getEkadashiDatesForYear, getSankrantisForYear, getFestivalsInRange
|
|
1080
|
+
getEkadashiDatesForYear, getSankrantisForYear, getFestivalsInRange
|
|
1081
|
+
getUpcomingEclipses, getEclipsesInRange
|
|
1082
|
+
|
|
1083
|
+
// Static data tables (engine-using runtime builders; bundled JSON at
|
|
1084
|
+
// panchang-ts/festivals, panchang-ts/eclipses, panchang-ts/moon-phases)
|
|
1085
|
+
buildFestivalsTable, buildEclipsesTable, buildMoonPhasesTable
|
|
892
1086
|
|
|
893
1087
|
// Errors
|
|
894
1088
|
PanchangError
|
|
@@ -926,7 +1120,7 @@ InteractionManager.runAfterInteractions(() => {
|
|
|
926
1120
|
|
|
927
1121
|
## Accuracy
|
|
928
1122
|
|
|
929
|
-
8,
|
|
1123
|
+
8,164 tests across 100 files, including fixtures cross-verified against reference
|
|
930
1124
|
panchang calculations spanning 2025–2026 across 10 Indian cities plus New York,
|
|
931
1125
|
London, Sydney, Dubai, Singapore (diaspora fixtures cover DST on
|
|
932
1126
|
`America/New_York`).
|
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/data/eclipses.json
|
|
4
|
+
var eclipses_default = {
|
|
5
|
+
_meta: {
|
|
6
|
+
referenceLocation: "Varanasi",
|
|
7
|
+
latitude: 25.3176,
|
|
8
|
+
longitude: 82.9739,
|
|
9
|
+
timezoneOffsetMinutes: 330,
|
|
10
|
+
visibleOnly: true,
|
|
11
|
+
languages: [
|
|
12
|
+
"en",
|
|
13
|
+
"hi"
|
|
14
|
+
],
|
|
15
|
+
startYear: 2024,
|
|
16
|
+
endYear: 2031,
|
|
17
|
+
generatedAt: "2026-05-30T14:11:40.371Z",
|
|
18
|
+
note: "Eclipses pre-computed for Varanasi (IST), visible from there during any phase (eclipsed body above the horizon between first and last contact \u2014 so an eclipse in progress at moon/sunrise or moon/sunset is included). visibleAtPeak flags whether greatest eclipse itself is observable. Within India visibility is essentially uniform; elsewhere it differs, so build a location-specific table at runtime with buildEclipsesTable and cache it. Solar eclipses carry the subtype seen from Varanasi (a globally-total eclipse may show as partial). Times are ISO UTC. Sutak: 4 prahara (12h) before first contact for solar, 3 prahara (9h) for umbral (partial/total) lunar, ending at moksha; penumbral lunar eclipses carry no sutak and are not religiously observed (drik / pandit consensus). Each entry carries both en and hi text."
|
|
19
|
+
},
|
|
20
|
+
years: {
|
|
21
|
+
"2024": [],
|
|
22
|
+
"2025": [
|
|
23
|
+
{
|
|
24
|
+
date: "2025-09-07",
|
|
25
|
+
eclipses: [
|
|
26
|
+
{
|
|
27
|
+
name: {
|
|
28
|
+
en: "Total Lunar Eclipse",
|
|
29
|
+
hi: "\u092A\u0942\u0930\u094D\u0923 \u091A\u0902\u0926\u094D\u0930 \u0917\u094D\u0930\u0939\u0923"
|
|
30
|
+
},
|
|
31
|
+
kind: "lunar",
|
|
32
|
+
subtype: "total",
|
|
33
|
+
start: "2025-09-07T15:28:02.515Z",
|
|
34
|
+
peak: "2025-09-07T18:11:41.501Z",
|
|
35
|
+
end: "2025-09-07T20:55:20.486Z",
|
|
36
|
+
magnitude: 1,
|
|
37
|
+
visibleFromLocation: true,
|
|
38
|
+
visibleAtPeak: true,
|
|
39
|
+
description: {
|
|
40
|
+
en: "Total Lunar Eclipse \u2014 100% obscuration.",
|
|
41
|
+
hi: "\u092A\u0942\u0930\u094D\u0923 \u091A\u0902\u0926\u094D\u0930 \u0917\u094D\u0930\u0939\u0923 \u2014 100% \u0917\u094D\u0930\u093E\u0938\u0964"
|
|
42
|
+
},
|
|
43
|
+
sutak: {
|
|
44
|
+
start: "2025-09-07T06:28:02.515Z",
|
|
45
|
+
end: "2025-09-07T20:55:20.486Z"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
],
|
|
51
|
+
"2026": [
|
|
52
|
+
{
|
|
53
|
+
date: "2026-03-03",
|
|
54
|
+
eclipses: [
|
|
55
|
+
{
|
|
56
|
+
name: {
|
|
57
|
+
en: "Total Lunar Eclipse",
|
|
58
|
+
hi: "\u092A\u0942\u0930\u094D\u0923 \u091A\u0902\u0926\u094D\u0930 \u0917\u094D\u0930\u0939\u0923"
|
|
59
|
+
},
|
|
60
|
+
kind: "lunar",
|
|
61
|
+
subtype: "total",
|
|
62
|
+
start: "2026-03-03T08:44:01.948Z",
|
|
63
|
+
peak: "2026-03-03T11:33:40.289Z",
|
|
64
|
+
end: "2026-03-03T14:23:18.629Z",
|
|
65
|
+
magnitude: 1,
|
|
66
|
+
visibleFromLocation: true,
|
|
67
|
+
visibleAtPeak: false,
|
|
68
|
+
description: {
|
|
69
|
+
en: "Total Lunar Eclipse \u2014 100% obscuration.",
|
|
70
|
+
hi: "\u092A\u0942\u0930\u094D\u0923 \u091A\u0902\u0926\u094D\u0930 \u0917\u094D\u0930\u0939\u0923 \u2014 100% \u0917\u094D\u0930\u093E\u0938\u0964"
|
|
71
|
+
},
|
|
72
|
+
sutak: {
|
|
73
|
+
start: "2026-03-02T23:44:01.948Z",
|
|
74
|
+
end: "2026-03-03T14:23:18.629Z"
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
]
|
|
78
|
+
}
|
|
79
|
+
],
|
|
80
|
+
"2027": [
|
|
81
|
+
{
|
|
82
|
+
date: "2027-02-21",
|
|
83
|
+
eclipses: [
|
|
84
|
+
{
|
|
85
|
+
name: {
|
|
86
|
+
en: "Penumbral Lunar Eclipse",
|
|
87
|
+
hi: "\u0909\u092A\u091A\u094D\u091B\u093E\u092F\u093E \u091A\u0902\u0926\u094D\u0930 \u0917\u094D\u0930\u0939\u0923"
|
|
88
|
+
},
|
|
89
|
+
kind: "lunar",
|
|
90
|
+
subtype: "penumbral",
|
|
91
|
+
start: "2027-02-20T21:11:52.109Z",
|
|
92
|
+
peak: "2027-02-20T23:12:44.142Z",
|
|
93
|
+
end: "2027-02-21T01:13:36.174Z",
|
|
94
|
+
magnitude: 0,
|
|
95
|
+
visibleFromLocation: true,
|
|
96
|
+
visibleAtPeak: true,
|
|
97
|
+
description: {
|
|
98
|
+
en: "Penumbral Lunar Eclipse \u2014 penumbral shadow only; no sutak.",
|
|
99
|
+
hi: "\u0909\u092A\u091A\u094D\u091B\u093E\u092F\u093E \u091A\u0902\u0926\u094D\u0930 \u0917\u094D\u0930\u0939\u0923 \u2014 \u0915\u0947\u0935\u0932 \u0909\u092A\u091A\u094D\u091B\u093E\u092F\u093E \u091B\u093E\u092F\u093E; \u0938\u0942\u0924\u0915 \u0928\u0939\u0940\u0902\u0964"
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
]
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
date: "2027-07-18",
|
|
106
|
+
eclipses: [
|
|
107
|
+
{
|
|
108
|
+
name: {
|
|
109
|
+
en: "Penumbral Lunar Eclipse",
|
|
110
|
+
hi: "\u0909\u092A\u091A\u094D\u091B\u093E\u092F\u093E \u091A\u0902\u0926\u094D\u0930 \u0917\u094D\u0930\u0939\u0923"
|
|
111
|
+
},
|
|
112
|
+
kind: "lunar",
|
|
113
|
+
subtype: "penumbral",
|
|
114
|
+
start: "2027-07-18T15:50:13.585Z",
|
|
115
|
+
peak: "2027-07-18T16:02:54.880Z",
|
|
116
|
+
end: "2027-07-18T16:15:36.174Z",
|
|
117
|
+
magnitude: 0,
|
|
118
|
+
visibleFromLocation: true,
|
|
119
|
+
visibleAtPeak: true,
|
|
120
|
+
description: {
|
|
121
|
+
en: "Penumbral Lunar Eclipse \u2014 penumbral shadow only; no sutak.",
|
|
122
|
+
hi: "\u0909\u092A\u091A\u094D\u091B\u093E\u092F\u093E \u091A\u0902\u0926\u094D\u0930 \u0917\u094D\u0930\u0939\u0923 \u2014 \u0915\u0947\u0935\u0932 \u0909\u092A\u091A\u094D\u091B\u093E\u092F\u093E \u091B\u093E\u092F\u093E; \u0938\u0942\u0924\u0915 \u0928\u0939\u0940\u0902\u0964"
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
]
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
date: "2027-08-02",
|
|
129
|
+
eclipses: [
|
|
130
|
+
{
|
|
131
|
+
name: {
|
|
132
|
+
en: "Partial Solar Eclipse",
|
|
133
|
+
hi: "\u0906\u0902\u0936\u093F\u0915 \u0938\u0942\u0930\u094D\u092F \u0917\u094D\u0930\u0939\u0923"
|
|
134
|
+
},
|
|
135
|
+
kind: "solar",
|
|
136
|
+
subtype: "partial",
|
|
137
|
+
start: "2027-08-02T10:35:33.763Z",
|
|
138
|
+
peak: "2027-08-02T11:07:37.251Z",
|
|
139
|
+
end: "2027-08-02T11:38:16.999Z",
|
|
140
|
+
magnitude: 0.06923317826751327,
|
|
141
|
+
visibleFromLocation: true,
|
|
142
|
+
visibleAtPeak: true,
|
|
143
|
+
description: {
|
|
144
|
+
en: "Partial Solar Eclipse \u2014 7% obscuration.",
|
|
145
|
+
hi: "\u0906\u0902\u0936\u093F\u0915 \u0938\u0942\u0930\u094D\u092F \u0917\u094D\u0930\u0939\u0923 \u2014 7% \u0917\u094D\u0930\u093E\u0938\u0964"
|
|
146
|
+
},
|
|
147
|
+
sutak: {
|
|
148
|
+
start: "2027-08-01T22:35:33.763Z",
|
|
149
|
+
end: "2027-08-02T11:38:16.999Z"
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
]
|
|
153
|
+
}
|
|
154
|
+
],
|
|
155
|
+
"2028": [
|
|
156
|
+
{
|
|
157
|
+
date: "2028-07-06",
|
|
158
|
+
eclipses: [
|
|
159
|
+
{
|
|
160
|
+
name: {
|
|
161
|
+
en: "Partial Lunar Eclipse",
|
|
162
|
+
hi: "\u0906\u0902\u0936\u093F\u0915 \u091A\u0902\u0926\u094D\u0930 \u0917\u094D\u0930\u0939\u0923"
|
|
163
|
+
},
|
|
164
|
+
kind: "lunar",
|
|
165
|
+
subtype: "partial",
|
|
166
|
+
start: "2028-07-06T15:43:55.421Z",
|
|
167
|
+
peak: "2028-07-06T18:19:38.379Z",
|
|
168
|
+
end: "2028-07-06T20:55:21.336Z",
|
|
169
|
+
magnitude: 0.3322998217792101,
|
|
170
|
+
visibleFromLocation: true,
|
|
171
|
+
visibleAtPeak: true,
|
|
172
|
+
description: {
|
|
173
|
+
en: "Partial Lunar Eclipse \u2014 33% obscuration.",
|
|
174
|
+
hi: "\u0906\u0902\u0936\u093F\u0915 \u091A\u0902\u0926\u094D\u0930 \u0917\u094D\u0930\u0939\u0923 \u2014 33% \u0917\u094D\u0930\u093E\u0938\u0964"
|
|
175
|
+
},
|
|
176
|
+
sutak: {
|
|
177
|
+
start: "2028-07-06T06:43:55.421Z",
|
|
178
|
+
end: "2028-07-06T20:55:21.336Z"
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
]
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
date: "2028-12-31",
|
|
185
|
+
eclipses: [
|
|
186
|
+
{
|
|
187
|
+
name: {
|
|
188
|
+
en: "Total Lunar Eclipse",
|
|
189
|
+
hi: "\u092A\u0942\u0930\u094D\u0923 \u091A\u0902\u0926\u094D\u0930 \u0917\u094D\u0930\u0939\u0923"
|
|
190
|
+
},
|
|
191
|
+
kind: "lunar",
|
|
192
|
+
subtype: "total",
|
|
193
|
+
start: "2028-12-31T14:03:27.574Z",
|
|
194
|
+
peak: "2028-12-31T16:51:54.549Z",
|
|
195
|
+
end: "2028-12-31T19:40:21.523Z",
|
|
196
|
+
magnitude: 1,
|
|
197
|
+
visibleFromLocation: true,
|
|
198
|
+
visibleAtPeak: true,
|
|
199
|
+
description: {
|
|
200
|
+
en: "Total Lunar Eclipse \u2014 100% obscuration.",
|
|
201
|
+
hi: "\u092A\u0942\u0930\u094D\u0923 \u091A\u0902\u0926\u094D\u0930 \u0917\u094D\u0930\u0939\u0923 \u2014 100% \u0917\u094D\u0930\u093E\u0938\u0964"
|
|
202
|
+
},
|
|
203
|
+
sutak: {
|
|
204
|
+
start: "2028-12-31T05:03:27.574Z",
|
|
205
|
+
end: "2028-12-31T19:40:21.523Z"
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
]
|
|
209
|
+
}
|
|
210
|
+
],
|
|
211
|
+
"2029": [
|
|
212
|
+
{
|
|
213
|
+
date: "2029-12-21",
|
|
214
|
+
eclipses: [
|
|
215
|
+
{
|
|
216
|
+
name: {
|
|
217
|
+
en: "Total Lunar Eclipse",
|
|
218
|
+
hi: "\u092A\u0942\u0930\u094D\u0923 \u091A\u0902\u0926\u094D\u0930 \u0917\u094D\u0930\u0939\u0923"
|
|
219
|
+
},
|
|
220
|
+
kind: "lunar",
|
|
221
|
+
subtype: "total",
|
|
222
|
+
start: "2029-12-20T19:42:34.436Z",
|
|
223
|
+
peak: "2029-12-20T22:41:54.610Z",
|
|
224
|
+
end: "2029-12-21T01:41:14.783Z",
|
|
225
|
+
magnitude: 1,
|
|
226
|
+
visibleFromLocation: true,
|
|
227
|
+
visibleAtPeak: true,
|
|
228
|
+
description: {
|
|
229
|
+
en: "Total Lunar Eclipse \u2014 100% obscuration.",
|
|
230
|
+
hi: "\u092A\u0942\u0930\u094D\u0923 \u091A\u0902\u0926\u094D\u0930 \u0917\u094D\u0930\u0939\u0923 \u2014 100% \u0917\u094D\u0930\u093E\u0938\u0964"
|
|
231
|
+
},
|
|
232
|
+
sutak: {
|
|
233
|
+
start: "2029-12-20T10:42:34.436Z",
|
|
234
|
+
end: "2029-12-21T01:41:14.783Z"
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
]
|
|
238
|
+
}
|
|
239
|
+
],
|
|
240
|
+
"2030": [
|
|
241
|
+
{
|
|
242
|
+
date: "2030-06-01",
|
|
243
|
+
eclipses: [
|
|
244
|
+
{
|
|
245
|
+
name: {
|
|
246
|
+
en: "Partial Solar Eclipse",
|
|
247
|
+
hi: "\u0906\u0902\u0936\u093F\u0915 \u0938\u0942\u0930\u094D\u092F \u0917\u094D\u0930\u0939\u0923"
|
|
248
|
+
},
|
|
249
|
+
kind: "solar",
|
|
250
|
+
subtype: "partial",
|
|
251
|
+
start: "2030-06-01T05:29:15.459Z",
|
|
252
|
+
peak: "2030-06-01T06:26:07.220Z",
|
|
253
|
+
end: "2030-06-01T07:23:32.918Z",
|
|
254
|
+
magnitude: 0.03201876826173855,
|
|
255
|
+
visibleFromLocation: true,
|
|
256
|
+
visibleAtPeak: true,
|
|
257
|
+
description: {
|
|
258
|
+
en: "Partial Solar Eclipse \u2014 3% obscuration.",
|
|
259
|
+
hi: "\u0906\u0902\u0936\u093F\u0915 \u0938\u0942\u0930\u094D\u092F \u0917\u094D\u0930\u0939\u0923 \u2014 3% \u0917\u094D\u0930\u093E\u0938\u0964"
|
|
260
|
+
},
|
|
261
|
+
sutak: {
|
|
262
|
+
start: "2030-05-31T17:29:15.459Z",
|
|
263
|
+
end: "2030-06-01T07:23:32.918Z"
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
]
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
date: "2030-06-16",
|
|
270
|
+
eclipses: [
|
|
271
|
+
{
|
|
272
|
+
name: {
|
|
273
|
+
en: "Partial Lunar Eclipse",
|
|
274
|
+
hi: "\u0906\u0902\u0936\u093F\u0915 \u091A\u0902\u0926\u094D\u0930 \u0917\u094D\u0930\u0939\u0923"
|
|
275
|
+
},
|
|
276
|
+
kind: "lunar",
|
|
277
|
+
subtype: "partial",
|
|
278
|
+
start: "2030-06-15T16:13:48.134Z",
|
|
279
|
+
peak: "2030-06-15T18:33:14.732Z",
|
|
280
|
+
end: "2030-06-15T20:52:41.329Z",
|
|
281
|
+
magnitude: 0.4708077570686115,
|
|
282
|
+
visibleFromLocation: true,
|
|
283
|
+
visibleAtPeak: true,
|
|
284
|
+
description: {
|
|
285
|
+
en: "Partial Lunar Eclipse \u2014 47% obscuration.",
|
|
286
|
+
hi: "\u0906\u0902\u0936\u093F\u0915 \u091A\u0902\u0926\u094D\u0930 \u0917\u094D\u0930\u0939\u0923 \u2014 47% \u0917\u094D\u0930\u093E\u0938\u0964"
|
|
287
|
+
},
|
|
288
|
+
sutak: {
|
|
289
|
+
start: "2030-06-15T07:13:48.134Z",
|
|
290
|
+
end: "2030-06-15T20:52:41.329Z"
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
]
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
date: "2030-12-10",
|
|
297
|
+
eclipses: [
|
|
298
|
+
{
|
|
299
|
+
name: {
|
|
300
|
+
en: "Penumbral Lunar Eclipse",
|
|
301
|
+
hi: "\u0909\u092A\u091A\u094D\u091B\u093E\u092F\u093E \u091A\u0902\u0926\u094D\u0930 \u0917\u094D\u0930\u0939\u0923"
|
|
302
|
+
},
|
|
303
|
+
kind: "lunar",
|
|
304
|
+
subtype: "penumbral",
|
|
305
|
+
start: "2030-12-09T20:07:30.214Z",
|
|
306
|
+
peak: "2030-12-09T22:27:32.805Z",
|
|
307
|
+
end: "2030-12-10T00:47:35.395Z",
|
|
308
|
+
magnitude: 0,
|
|
309
|
+
visibleFromLocation: true,
|
|
310
|
+
visibleAtPeak: true,
|
|
311
|
+
description: {
|
|
312
|
+
en: "Penumbral Lunar Eclipse \u2014 penumbral shadow only; no sutak.",
|
|
313
|
+
hi: "\u0909\u092A\u091A\u094D\u091B\u093E\u092F\u093E \u091A\u0902\u0926\u094D\u0930 \u0917\u094D\u0930\u0939\u0923 \u2014 \u0915\u0947\u0935\u0932 \u0909\u092A\u091A\u094D\u091B\u093E\u092F\u093E \u091B\u093E\u092F\u093E; \u0938\u0942\u0924\u0915 \u0928\u0939\u0940\u0902\u0964"
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
]
|
|
317
|
+
}
|
|
318
|
+
],
|
|
319
|
+
"2031": [
|
|
320
|
+
{
|
|
321
|
+
date: "2031-05-21",
|
|
322
|
+
eclipses: [
|
|
323
|
+
{
|
|
324
|
+
name: {
|
|
325
|
+
en: "Partial Solar Eclipse",
|
|
326
|
+
hi: "\u0906\u0902\u0936\u093F\u0915 \u0938\u0942\u0930\u094D\u092F \u0917\u094D\u0930\u0939\u0923"
|
|
327
|
+
},
|
|
328
|
+
kind: "solar",
|
|
329
|
+
subtype: "partial",
|
|
330
|
+
start: "2031-05-21T06:16:35.159Z",
|
|
331
|
+
peak: "2031-05-21T07:56:20.750Z",
|
|
332
|
+
end: "2031-05-21T09:26:36.965Z",
|
|
333
|
+
magnitude: 0.3939059024675881,
|
|
334
|
+
visibleFromLocation: true,
|
|
335
|
+
visibleAtPeak: true,
|
|
336
|
+
description: {
|
|
337
|
+
en: "Partial Solar Eclipse \u2014 39% obscuration.",
|
|
338
|
+
hi: "\u0906\u0902\u0936\u093F\u0915 \u0938\u0942\u0930\u094D\u092F \u0917\u094D\u0930\u0939\u0923 \u2014 39% \u0917\u094D\u0930\u093E\u0938\u0964"
|
|
339
|
+
},
|
|
340
|
+
sutak: {
|
|
341
|
+
start: "2031-05-20T18:16:35.159Z",
|
|
342
|
+
end: "2031-05-21T09:26:36.965Z"
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
]
|
|
346
|
+
}
|
|
347
|
+
]
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
// src/calendar/eclipsesTable.ts
|
|
352
|
+
var bundled = eclipses_default;
|
|
353
|
+
var ECLIPSES_META = bundled._meta;
|
|
354
|
+
var ECLIPSES_YEAR_RANGE = {
|
|
355
|
+
start: bundled._meta.startYear,
|
|
356
|
+
end: bundled._meta.endYear
|
|
357
|
+
};
|
|
358
|
+
function flatten(raw, lang) {
|
|
359
|
+
const name = raw.name[lang] ?? Object.values(raw.name)[0] ?? "";
|
|
360
|
+
const out = {
|
|
361
|
+
name,
|
|
362
|
+
kind: raw.kind,
|
|
363
|
+
subtype: raw.subtype,
|
|
364
|
+
start: raw.start,
|
|
365
|
+
peak: raw.peak,
|
|
366
|
+
end: raw.end,
|
|
367
|
+
magnitude: raw.magnitude,
|
|
368
|
+
visibleFromLocation: raw.visibleFromLocation,
|
|
369
|
+
visibleAtPeak: raw.visibleAtPeak
|
|
370
|
+
};
|
|
371
|
+
if (raw.sutak) out.sutak = raw.sutak;
|
|
372
|
+
if (raw.description) {
|
|
373
|
+
out.description = raw.description[lang] ?? Object.values(raw.description)[0] ?? "";
|
|
374
|
+
}
|
|
375
|
+
return out;
|
|
376
|
+
}
|
|
377
|
+
function getEclipsesForYear(year, lang = "en", source = bundled) {
|
|
378
|
+
const days = source.years[String(year)];
|
|
379
|
+
if (!days) return null;
|
|
380
|
+
return days.map((d) => ({
|
|
381
|
+
date: d.date,
|
|
382
|
+
eclipses: d.eclipses.map((e) => flatten(e, lang))
|
|
383
|
+
}));
|
|
384
|
+
}
|
|
385
|
+
function getEclipsesForDate(date, lang = "en", source = bundled) {
|
|
386
|
+
const key = typeof date === "string" ? date : toDateKey(date, source._meta.timezoneOffsetMinutes);
|
|
387
|
+
const yearKey = key.slice(0, 4);
|
|
388
|
+
const days = source.years[yearKey];
|
|
389
|
+
if (!days) return [];
|
|
390
|
+
const day = days.find((d) => d.date === key);
|
|
391
|
+
return day ? day.eclipses.map((e) => flatten(e, lang)) : [];
|
|
392
|
+
}
|
|
393
|
+
function toDateKey(d, offsetMinutes) {
|
|
394
|
+
const shifted = new Date(d.getTime() + offsetMinutes * 6e4);
|
|
395
|
+
const y = shifted.getUTCFullYear();
|
|
396
|
+
const m = String(shifted.getUTCMonth() + 1).padStart(2, "0");
|
|
397
|
+
const day = String(shifted.getUTCDate()).padStart(2, "0");
|
|
398
|
+
return `${y}-${m}-${day}`;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
exports.ECLIPSES_META = ECLIPSES_META;
|
|
402
|
+
exports.ECLIPSES_YEAR_RANGE = ECLIPSES_YEAR_RANGE;
|
|
403
|
+
exports.getEclipsesForDate = getEclipsesForDate;
|
|
404
|
+
exports.getEclipsesForYear = getEclipsesForYear;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { g as EclipseTableMeta, E as EclipsesTableLanguage, a as EclipsesFile, d as EclipseTableEntry, c as EclipseTableDay } from '../eclipsesTableTypes-D-tSQMQd.cjs';
|
|
2
|
+
export { b as EclipseSutak, e as EclipseTableEntryRaw, f as EclipseTableKind, h as EclipseTableSubtype, R as RawEclipseTableDay } from '../eclipsesTableTypes-D-tSQMQd.cjs';
|
|
3
|
+
|
|
4
|
+
/** Metadata describing what the bundled table was generated from. */
|
|
5
|
+
declare const ECLIPSES_META: EclipseTableMeta;
|
|
6
|
+
/** Inclusive year range covered by the bundled table. */
|
|
7
|
+
declare const ECLIPSES_YEAR_RANGE: {
|
|
8
|
+
readonly start: number;
|
|
9
|
+
readonly end: number;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Eclipse days for a Gregorian year, flattened to the requested locale.
|
|
13
|
+
*
|
|
14
|
+
* Returns `null` if `year` is outside the table's range, or an empty array if
|
|
15
|
+
* the year is in range but had no (visible) eclipses.
|
|
16
|
+
*
|
|
17
|
+
* @param year Gregorian year.
|
|
18
|
+
* @param lang `'en'` (default) or `'hi'`.
|
|
19
|
+
* @param source Table to read from. Defaults to the bundled Varanasi table;
|
|
20
|
+
* pass a {@link buildEclipsesTable} result to read a
|
|
21
|
+
* location-specific table you built and cached.
|
|
22
|
+
*/
|
|
23
|
+
declare function getEclipsesForYear(year: number, lang?: EclipsesTableLanguage, source?: EclipsesFile): EclipseTableDay[] | null;
|
|
24
|
+
/**
|
|
25
|
+
* Eclipses on a specific date, flattened to the requested locale.
|
|
26
|
+
*
|
|
27
|
+
* Returns an empty array if the date has no eclipse or is outside the table's
|
|
28
|
+
* range. The date is matched against the eclipse peak's local date.
|
|
29
|
+
*
|
|
30
|
+
* @param date Either an ISO `YYYY-MM-DD` string (interpreted in the table's
|
|
31
|
+
* reference timezone) or a `Date` (its local calendar date in the
|
|
32
|
+
* table's reference timezone is used).
|
|
33
|
+
* @param lang `'en'` (default) or `'hi'`.
|
|
34
|
+
* @param source Table to read from. Defaults to the bundled Varanasi table;
|
|
35
|
+
* pass a {@link buildEclipsesTable} result for a
|
|
36
|
+
* location-specific table.
|
|
37
|
+
*/
|
|
38
|
+
declare function getEclipsesForDate(date: string | Date, lang?: EclipsesTableLanguage, source?: EclipsesFile): EclipseTableEntry[];
|
|
39
|
+
|
|
40
|
+
export { ECLIPSES_META, ECLIPSES_YEAR_RANGE, EclipseTableDay, EclipseTableEntry, EclipseTableMeta, EclipsesFile, EclipsesTableLanguage, getEclipsesForDate, getEclipsesForYear };
|