Skip to content
Documentation · all sections

Options & Localization

panchang · v5.4.0 · MIT

Every option accepted by getDailyPanchang, English/Hindi localization, timezone handling, and the localized vs machine-readable field convention.

getDailyPanchang takes the options object below, and only timezone is required. Everything else has a default, so you can add options one at a time as you need them. getInstantPanchang takes the same object without timezone and sections — an optional InstantPanchangOptions. Other entry points — jyotish, muhurta, calendar conversion, the yearly listings — take their own options types.

All options

const r = getDailyPanchang(date, loc, {
  timezone: 330,                       // number (UTC offset min) or IANA string — REQUIRED
  ayanamsa: 'lahiri',                  // lahiri | raman | krishnamurti | true-chitra | thirukanitham
  language: 'en',                      // en | hi
  masaSystem: 'purnimanta',            // purnimanta | amanta
  region: 'all',                       // 21 slugs + 'all'
  computeEndTimes: true,               // false → skip transition searches
  sections: ['festivals', 'eclipse'],  // omit for all
  janmaRashi: 3,                       // omit → r.chandraBalam is null
  janmaNakshatra: 12,                  // omit → r.tarabala is null
})!;

r.angas.tithis[0].name;                // 'Krishna Chaturdashi'
r.calendar.chandramasa.name;           // 'Magha'
r.angas.tithis[0].endTimeLocal;        // '2025-01-28T19:36:32.608+05:30'
r.chandraBalam!.name; r.tarabala!.name;  // 'Shubha' 'Mitra'

// computeEndTimes: false skips the transition searches
const r2 = getDailyPanchang(date, loc, { timezone: 330, computeEndTimes: false })!;
r2.angas.tithis[0].endTimeLocal;       // null
OptionType / valuesDefaultEffect
timezonenumber (whole minutes from UTC, -720 to 840) or IANA stringnone (required)the zone the Hindu day and every *Local string is rendered in
ayanamsa'lahiri' | 'raman' | 'krishnamurti' | 'true-chitra' | 'thirukanitham''lahiri'sidereal zero-point for every longitude-derived value
language'en' | 'hi''en'every user-facing string
masaSystem'purnimanta' | 'amanta''purnimanta'which system calendar.chandramasa.name resolves to, and since 5.4 the month four vratas are counted in (below)
regionFestivalRegion'all'scopes regional festival variants — see Festivals
computeEndTimesbooleantruewhether the anga transitions are solved; false keeps only the sunrise entry of each anga, with startTime and endTime null, and since 5.4 leaves specialYogas unchanged
sectionsPanchangSection[]undefinednarrow the optional blocks; the grahan entry in festivals also needs 'eclipse' (see Performance)
janmaRashi0..11 (0 = Mesha)undefinedpopulates chandraBalam; since 5.4 a null from JavaScript or JSON means the same as leaving it out (the TypeScript type still takes only a number)
janmaNakshatra0..26 (0 = Ashwini)undefinedpopulates tarabala; since 5.4 a null from JavaScript or JSON means the same as leaving it out (the TypeScript type still takes only a number)

In Go, only Timezone and the section fields sit on types.PanchangOptions — the rest live on an embedded types.InstantPanchangOptions. Every option value has a named constant: the masa system is types.Purnimanta or types.Amanta, and the Nepal, Uttar Pradesh and Madhya Pradesh regions are types.RegionNepal, types.RegionUttarPradesh and types.RegionMadhyaPradesh.

Masa system and region

masaSystem picks the name calendar.chandramasa.name carries. Since 5.4 it also picks the lunar month that Shravan Somvar, Mangala Gauri, Kartik Somvar and Magha Shanivar are counted in, on the daily result, the instant result and the festival listings. 'purnimanta', the default, gives the North Indian dates. 'amanta' gives the South Indian ones, which are what 5.3 listed whatever you passed, and region 'nepal' counts them by the solar month. A caller that never sets masaSystem therefore gets new dates for these four. The full rule is on Festivals.

import { computeFestivalsForYear, formatInZone, type YearlyListingOptions } from 'panchang-ts';

const DELHI = { latitude: 28.6139, longitude: 77.2090 };

// The Shravan Somvar dates of 2025 at Delhi, as MM-DD in IST
const mondays = (o: Partial<YearlyListingOptions>) =>
  computeFestivalsForYear(2025, DELHI, { ...o, timezone: 330 })
    .filter(f => f.festival.key === 'shravan_somvar')
    .map(f => formatInZone(f.date, 330).slice(5, 10));

mondays({});                        // ['07-14', '07-21', '07-28', '08-04']
mondays({ masaSystem: 'amanta' });  // ['07-28', '08-04', '08-11', '08-18']
mondays({ region: 'nepal' });       // ['07-21', '07-28', '08-04', '08-11']

The values region takes also pick the new-year rule in getHinduNewYear(year, region, location, options). Since 5.4 'odisha' gives Pana Sankranti, the Mesha Sankranti day, instead of Chaitra Shukla Pratipada: the civil date of the transit, or, once the transit is more than 0.315 of the way through the night after sunset, the date of the sunrise that ends that night. The cutoff is a fraction of the local night, so the date depends on the place: 2028 is 14 April at Bhubaneswar and 13 April at Delhi, while 2024 is 13 April at both. See Calendar Conversion.

Reference frames

Some callers have no coordinates of their own. Version 5.2.0 adds two fixed places to fall back on, plus helpers that pick between a frame and a real location. TRADITIONAL_REFERENCE is Ujjain, the classical madhya rekha of the Surya Siddhanta, and the default. MODERN_REFERENCE is the Central Station, the reference the 1955 Calendar Reform Committee used for the Rashtriya Panchang. The types are PanchangReference (the frame a result is in), ReferenceMode (the frame you ask for) and ResolvedLocation.

import {
  TRADITIONAL_REFERENCE, MODERN_REFERENCE,
  IST_TIMEZONE, IST_OFFSET_MINUTES,
  referenceLocation, resolveLocation,
} from 'panchang-ts';

TRADITIONAL_REFERENCE;  // { latitude: 23.1765, longitude: 75.7885, elevation: 0 }
MODERN_REFERENCE;       // { latitude: 23.1833, longitude: 82.5,    elevation: 0 }
IST_TIMEZONE;           // 'Asia/Kolkata'
IST_OFFSET_MINUTES;     // 330

referenceLocation('modern');  // { latitude: 23.1833, longitude: 82.5, elevation: 0 }

// no location → the frame you asked for; a real one passes through
resolveLocation(undefined, 'traditional');
// { location: { latitude: 23.1765, longitude: 75.7885, elevation: 0 }, reference: 'traditional' }
resolveLocation({ latitude: 18.52, longitude: 73.86 }, 'traditional');
// { location: { latitude: 18.52, longitude: 73.86 }, reference: 'practical' }

Timezone

Pass minutes from UTC (330 for IST) or an IANA zone name ('America/New_York'). A number must be whole minutes from -720 to 840, or the call throws INVALID_TIMEZONE. A zone name resolves DST for you. IANA names need Intl, which older Hermes versions lack, so pass a number on those targets. The result echoes what was resolved in result.timezone, and zone is present only when you passed a zone name.

const DELHI = { latitude: 28.6139, longitude: 77.2090 };
const date  = new Date('2025-01-28');

// minutes from UTC
getDailyPanchang(date, DELHI, { timezone: 330 })!.timezone;
// { offsetMinutes: 330 }

// IANA name: zone is echoed back, DST resolves per call
getDailyPanchang(date, DELHI, { timezone: 'Asia/Kolkata' })!.timezone;
// { offsetMinutes: 330, zone: 'Asia/Kolkata' }

const NY = { latitude: 40.7128, longitude: -74.0060 };
// 00:00 UTC on the 15th is still the 14th in New York, so these are the 14th's days
for (const d of [new Date('2025-01-15'), new Date('2025-07-15')]) {
  const r = getDailyPanchang(d, NY, { timezone: 'America/New_York' })!;
  console.log(r.timezone.offsetMinutes, r.sun.riseLocal);
}
// -300 2025-01-14T07:18:10.647-05:00
// -240 2025-07-14T05:37:13.355-04:00

The *Local strings are already in the zone. To render a Date the library returns yourself, use formatInZone(date, offsetMinutes). Since 5.4 it renders any whole number of minutes and throws INVALID_TIMEZONE for a fraction, which 5.3 printed as +00:undefined.

A Date that names a day rather than a moment reads right only in the location's zone, and there are two kinds. The festival listings return an instant inside the day: computeFestivalsForYear gives the local midnight that starts it, so Akshaya Tritiya 2020 at Delhi is 2020-04-25T18:30:00.000Z, 00:00 on 26 April in IST, and computeFestivalsInRange gives the start's local time of day on that date. computeEkadashiDatesForYear, SankrantiEvent.date, getHinduNewYear and convertHinduToGregorian return the UTC midnight that falls within the local day: Mesha Sankranti 2025 at New York is 2025-04-14T00:00:00.000Z, 20:00 on 13 April there, so 13 April. Since 5.4 SankrantiEvent.date and the solar new years of getHinduNewYear follow that rule; 5.3 returned them a day early west of UTC. Read either kind in the zone, never with toISOString() or getUTCDate().

import { formatInZone, computeSankrantisForYear } from 'panchang-ts';

const at = new Date('2025-03-20T00:00:00Z');
formatInZone(at, 330);    // '2025-03-20T05:30:00.000+05:30'
formatInZone(at, -570);   // '2025-03-19T14:30:00.000-09:30'
formatInZone(at, 5.5);    // throws PanchangError INVALID_TIMEZONE

// A day value, read in the zone it was computed for
const NY = { latitude: 40.7128, longitude: -74.0060 };
const mesha = computeSankrantisForYear(2025, NY, { timezone: 'America/New_York' })
  .find(e => e.rashi === 0)!;       // Mesha
formatInZone(mesha.date, -240);     // '2025-04-13T20:00:00.000-04:00': 13 April

Language

language switches every user-facing string between English and Hindi. englishName, where a value has one, stays English in both.

const date = new Date('2025-01-28');
const loc  = { latitude: 28.6139, longitude: 77.2090 };

const en = getDailyPanchang(date, loc, { timezone: 330, language: 'en' })!;
en.angas.tithis[0].name;            // "Krishna Chaturdashi"
en.angas.vara.name;                 // "Mangalawara"
en.calendar.chandramasa.name;       // "Magha"
en.periods.choghadiya.day[0].name;  // "Rog"

const hi = getDailyPanchang(date, loc, { timezone: 330, language: 'hi' })!;
hi.angas.tithis[0].name;            // "कृष्ण चतुर्दशी"
hi.angas.vara.name;                 // "मंगलवार"
hi.calendar.chandramasa.name;       // "माघ"
hi.periods.choghadiya.day[0].name;  // "रोग"
hi.angas.vara.englishName;          // "Tuesday" — englishName always English

Localized vs machine-readable fields

Where a value is also meaningful to code, you get two fields. Branch on the one in the left column. It never changes with language.

Machine-readableLocalized display
festival.key ('diwali')festival.name (“दिवाली”)
bhadra.location ('paatal')bhadra.locationName (“पाताल”)
eclipse.kind / eclipse.subtypeeclipse.description
muhurtaScore.factors[].codemuhurtaScore.reasons (English only)

MuhurtaScore.reasons is diagnostic English and not a stable format. Use factors for anything you show a user or branch on in code. The named yogas from computeYogas and the Jaimini karaka names are English or transliterated proper nouns, and are not translated. The daily yoga names in angas.yogas, anandadiYoga and specialYogas do follow language.