vedic-panchanga
v0.2.0
Published
Hindu Panchangam engine in pure TypeScript, zero dependencies — tithi, nakshatra, yoga, karana, vara, sunrise/sunset, masa, ritu, Rahu Kaal and the day's muhurtas.
Maintainers
Readme
vedic-panchanga
Compute the Hindu Panchāṅga (panchangam) — the five "limbs" of the Vedic almanac — in pure TypeScript, with no runtime dependencies. Give it an instant and a location and it returns the tithi, nakṣatra, yoga, karaṇa and vāra (each with its start and end time), plus sunrise/sunset, the lunar month, the season, the samvat years, the sidereal sun & moon signs, and the day's auspicious / inauspicious windows (Rāhu Kāla, Yamaganda, Gulika, Abhijit).
- All five aṅgas — tithi, nakṣatra (with pada & lord), yoga, karaṇa, vāra, each with exact start/end instants
- Sun & Moon — sunrise, sunset, solar noon, moonrise, moonset
- Calendar — pakṣa, māsa (amānta + pūrṇimānta), ṛtu, Vikram & Śaka samvat, sidereal rāśi of Sun & Moon
- Muhūrta — Rāhu Kāla, Yamaganda, Gulika Kāla, Abhijit, Brahma Muhūrta
- Any time of day — pass a
timeand every aṅga is measured at that instant, not sunrise, with the windows it falls inside - Zero runtime dependencies, ESM + CJS, full TypeScript types
The astronomy is a self-contained implementation of the algorithms in Jean Meeus's Astronomical Algorithms (2nd ed.). It ships ESM + CJS builds and full type declarations, and runs anywhere modern JavaScript does (Node ≥ 18, Deno, Bun, edge runtimes, the browser).
npm install vedic-panchangaQuick start
import { computePanchanga } from "vedic-panchanga";
const p = computePanchanga({
date: new Date(), // any instant; defaults to now
latitude: 28.6139, // north positive
longitude: 77.209, // east positive
timezone: "Asia/Kolkata", // IANA id; defaults to "Asia/Kolkata"
});
console.log(p.date); // "2026-09-01"
console.log(`${p.vara.name.iast} — ${p.vara.name.english}`); // "Somavara — Monday"
console.log(
`${p.paksha.iast} ${p.tithi.name.iast}, ends ${p.tithi.end.toLocaleString()}`,
);
console.log(`Nakṣatra: ${p.nakshatra.name.iast} (pada ${p.nakshatra.pada})`);
console.log(`Rāhu Kāla: ${p.inauspiciousPeriods[0].start.toLocaleTimeString()}`);Every timestamp in the result is a JavaScript Date (a UTC instant) — format it
in whatever zone you need. The Panchāṅga is reported for the civil day that
date falls on in timezone, measured at that day's sunrise, which is the
convention printed in almanacs.
A specific time of day
Pass time (a "HH:MM" or "HH:MM:SS" wall-clock string, read in timezone)
to measure everything at that instant instead of at sunrise — the tithi,
nakṣatra, yoga, karaṇa, both sidereal signs and the fractionElapsed figures all
follow. reference tells you which instant was used, and currentPeriods lists
the day windows (Rāhu Kāla, Abhijit…) that contain it. Handy for a birth time or
a "what's running right now" lookup.
const p = computePanchanga({
date: new Date("2024-06-15"),
time: "14:30", // 2:30 pm in `timezone`, on 2024-06-15
latitude: 28.6139,
longitude: 77.209,
timezone: "Asia/Kolkata",
});
console.log(p.reference); // { kind: "time", instant: 2024-06-15T09:00:00.000Z }
console.log(p.tithi.name.iast, p.tithi.fractionElapsed); // the tithi live at 2:30 pm
console.log(p.currentPeriods.map((k) => k.name.iast)); // e.g. ["Rahu Kala"]Omit time and the output is exactly as before — reference.kind is
"sunrise" and currentPeriods is normally empty.
What you get
type Panchanga = {
date: string; // "yyyy-mm-dd" in `timezone`
timezone: string;
location: { latitude: number; longitude: number };
ayanamsaSystem: "lahiri" | "raman" | "kp" | "fagan_bradley";
ayanamsa: number; // degrees
// Which instant the aṅgas below were evaluated at.
reference: { kind: "sunrise" | "time"; instant: Date };
sunrise: Date;
sunset: Date;
nextSunrise: Date; // end of the vāra
solarNoon: Date | null;
moonrise: Date | null; // null when the Moon does not rise that day
moonset: Date | null;
// The five aṅgas, as they stand at `reference.instant`. Each carries
// { index, name, start, end, fractionElapsed }. `name` is { iast, devanagari, english? }.
vara: Anga; // index 1–7
tithi: Anga; // index 1–30 (15 = Pūrṇimā, 30 = Amāvasyā)
nakshatra: Anga & { pada: 1 | 2 | 3 | 4; lord: string }; // index 1–27
yoga: Anga; // index 1–27
karana: Anga; // index 1–11
paksha: Name; // Śukla / Kṛṣṇa
masa: Name; // per `monthSystem`
masaAmanta: Name;
masaPurnimanta: Name;
ritu: Name; // season
vikramSamvat: number;
shakaSamvat: number;
sunSign: Name; // sidereal rāśi of the Sun at `reference`
moonSign: Name; // sidereal rāśi of the Moon at `reference` (janma rāśi)
auspiciousPeriods: Kaala[]; // Brahma Muhūrta, Abhijit Muhūrta
inauspiciousPeriods: Kaala[]; // Rāhu Kāla, Yamaganda, Gulika Kāla
currentPeriods: Kaala[]; // the two lists above, filtered to `reference.instant`
};Options
| Option | Type | Default |
| ------------- | ------------------------------------------------- | ---------------- |
| date | Date | new Date() |
| time | "HH:MM" / "HH:MM:SS" wall-clock in timezone | — (use sunrise) |
| latitude | number (−90…90, north positive) — required | — |
| longitude | number (−180…180, east positive) — required | — |
| timezone | IANA id, e.g. "America/New_York" | "Asia/Kolkata" |
| ayanamsa | "lahiri" \| "raman" \| "kp" \| "fagan_bradley" | "lahiri" |
| monthSystem | "amanta" \| "purnimanta" (drives masa) | "amanta" |
Lower-level exports
For callers who want the raw astronomy:
import {
sunPosition, sunLongitude,
moonPosition, moonLongitude,
nutation, apparentSiderealTime, meanSiderealTime,
riseSetForWindow, findCrossings,
dateToJD, jdToDate, jdToJDE, deltaT,
ayanamsa,
NAKSHATRAS, YOGAS, KARANAS, VARAS, MASAS, RITUS, RASHIS, TITHI_ORDINALS,
} from "vedic-panchanga";Accuracy & limitations
This package aims for almanac-grade accuracy — good enough to print a daily Panchāṅga and to drive muhūrta decisions — not observatory precision.
- Positions. Solar longitude follows Meeus ch. 25 (~0.01°); lunar longitude and latitude follow the truncated ELP-2000/82 series of Meeus ch. 47 (~10″ and ~4″). Nutation is the leading ~30 terms of IAU 1980 (~0.5″). It is not the Swiss Ephemeris / full ELP; expect aṅga boundary times within roughly a minute of a published almanac, and rise/set times within a minute or two.
- Ayanāṁśa. Modelled as
ayanāṁśa(J2000) + accumulated precession (IAU 2006)— a mean value, accurate to about an arc-minute over 1900–2100. Because the ecliptic longitudes already include nutation, the resulting sidereal positions match published (true) Lahiri values closely. - Rise / set. Geometric horizon with standard refraction (−0°50′ for the Sun,
Meeus's
0.7275π − 0°34′for the Moon). No observer elevation, local horizon profile, or non-standard atmospheric conditions. Polar day / night raisesNoSunriseError. - Māsa. Named by the solar sign at the bounding new moon. Adhika / kṣaya (leap / skipped) months are not modelled, so month names can disagree with a full luni-solar calendar in those years.
- Samvat. Civil approximation of the new-year rollover; can be off by one within ~a fortnight of mid-March. Regional variants (Kārtika new year, etc.) are not modelled.
- Not yet produced: Varjyam, Amṛta Kāla, Durmuhūrtam.
If you need certified values for a specific tradition, cross-check against your reference almanac.
References
- Jean Meeus, Astronomical Algorithms, 2nd ed., Willmann-Bell, 1998 — chapters 7, 10, 12, 15, 22, 25, 47.
- N. Capitaine et al., "Expressions for IAU 2000 precession quantities", Astronomy & Astrophysics 412 (2003) — precession polynomial.
- F. Espenak & J. Meeus, "Polynomial Expressions for Delta T" (NASA) — ΔT.
