- Dharmagya
- panchang docs
- Options & Localization
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; // nullpackage main
import (
"fmt"
"time"
"github.com/ishankgupta95/panchang/source/go/v5/panchang"
"github.com/ishankgupta95/panchang/source/go/v5/types"
)
func ptr[T any](v T) *T { return &v }
func main() {
s := panchang.New()
loc := types.GeoLocation{Latitude: 28.6139, Longitude: 77.2090}
date := time.Date(2025, 1, 28, 0, 0, 0, 0, time.UTC)
o := types.PanchangOptions{Timezone: panchang.OffsetMinutes(330)} // required
o.Ayanamsa = panchang.Lahiri // "" -> lahiri
o.Language = panchang.English // "" -> en
o.MasaSystem = types.Purnimanta // "" -> purnimanta
o.Region = panchang.RegionAll // "" -> all
o.ComputeEndTimes = ptr(true) // nil -> true
o.JanmaRashi = ptr(3) // nil -> ChandraBalam nil
o.JanmaNakshatra = ptr(12) // nil -> Tarabala nil
o.SectionsGiven = true // false -> all sections
o.Sections = panchang.Sections(types.SectionFestivals, types.SectionEclipse)
r, ok, err := s.GetDailyPanchang(date, loc, o)
if err != nil || !ok {
panic(err)
}
fmt.Println(r.Angas.Tithis[0].Name, "|", r.Calendar.Chandramasa.Name)
// Krishna Chaturdashi | Magha
fmt.Println(*r.Angas.Tithis[0].EndTimeLocal)
// 2025-01-28T19:36:32.608+05:30
fmt.Println(r.ChandraBalam.Name, r.Tarabala.Name) // Shubha Mitra
// computeEndTimes: false skips the transition searches
o.ComputeEndTimes = ptr(false)
r2, _, _ := s.GetDailyPanchang(date, loc, o)
fmt.Println(r2.Angas.Tithis[0].EndTimeLocal == nil) // true
}| Option | Type / values | Default | Effect |
|---|---|---|---|
timezone | number (whole minutes from UTC, -720 to 840) or IANA string | none (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) |
region | FestivalRegion | 'all' | scopes regional festival variants — see Festivals |
computeEndTimes | boolean | true | whether 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 |
sections | PanchangSection[] | undefined | narrow the optional blocks; the grahan entry in festivals also needs 'eclipse' (see Performance) |
janmaRashi | 0..11 (0 = Mesha) | undefined | populates 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) |
janmaNakshatra | 0..26 (0 = Ashwini) | undefined | populates 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']s := panchang.New()
delhi := types.GeoLocation{Latitude: 28.6139, Longitude: 77.2090}
// The Shravan Somvar dates of 2025 at Delhi, as MM-DD in IST
mondays := func(o types.YearlyListingOptions) []string {
o.Timezone = panchang.OffsetMinutes(330)
days, err := s.ComputeFestivalsForYear(2025, delhi, o)
if err != nil {
panic(err)
}
out := []string{}
for _, d := range days {
if d.Festival.Key == "shravan_somvar" {
out = append(out, panchang.FormatInZone(d.Date.Time(), 330)[5:10])
}
}
return out
}
fmt.Println(mondays(types.YearlyListingOptions{})) // [07-14 07-21 07-28 08-04]
fmt.Println(mondays(types.YearlyListingOptions{MasaSystem: types.Amanta})) // [07-28 08-04 08-11 08-18]
fmt.Println(mondays(types.YearlyListingOptions{Region: types.RegionNepal})) // [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' }fmt.Println(panchang.TraditionalReference()) // {23.1765 75.7885 0}
fmt.Println(panchang.ModernReference()) // {23.1833 82.5 0}
fmt.Println(panchang.ISTTimezone, panchang.ISTOffsetMinutes)
// Asia/Kolkata 330
loc, err := panchang.ReferenceLocation(panchang.ReferenceModern)
fmt.Println(loc, err) // {23.1833 82.5 0} <nil>
// nil location -> the frame you asked for; a real one passes through
got, mode, _ := panchang.ResolveLocation(nil, panchang.ReferenceTraditional)
fmt.Println(got, mode) // {23.1765 75.7885 0} traditional
pune := types.GeoLocation{Latitude: 18.52, Longitude: 73.86}
got2, mode2, _ := panchang.ResolveLocation(&pune, panchang.ReferenceTraditional)
fmt.Println(got2, mode2) // {18.52 73.86 0} practicalTimezone
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:00s := panchang.New()
delhi := types.GeoLocation{Latitude: 28.6139, Longitude: 77.2090}
date := time.Date(2025, 1, 28, 0, 0, 0, 0, time.UTC)
// minutes from UTC
a, _, _ := s.GetDailyPanchang(date, delhi,
types.PanchangOptions{Timezone: panchang.OffsetMinutes(330)})
fmt.Println(a.Timezone.OffsetMinutes, a.Timezone.Zone == "") // 330 true
// IANA name: Zone is echoed back, DST resolves per call
b, _, _ := s.GetDailyPanchang(date, delhi,
types.PanchangOptions{Timezone: panchang.Zone("Asia/Kolkata")})
fmt.Println(b.Timezone.OffsetMinutes, b.Timezone.Zone) // 330 Asia/Kolkata
ny := types.GeoLocation{Latitude: 40.7128, Longitude: -74.0060}
tz := panchang.Zone("America/New_York")
// 00:00 UTC on the 15th is still the 14th in New York, so these are the 14th's days
for _, d := range []time.Time{
time.Date(2025, 1, 15, 0, 0, 0, 0, time.UTC),
time.Date(2025, 7, 15, 0, 0, 0, 0, time.UTC),
} {
r, _, _ := s.GetDailyPanchang(d, ny, types.PanchangOptions{Timezone: tz})
fmt.Println(r.Timezone.OffsetMinutes, r.Sun.RiseLocal)
}
// -300 2025-01-14T07:18:10.647-05:00
// -240 2025-07-14T05:37:13.355-04:00
// an unset Timezone is a coded error, never a silent default
_, _, err := s.GetDailyPanchang(date, delhi, types.PanchangOptions{})
fmt.Println(panchang.IsCode(err, types.ErrInvalidTimezone)) // true
// "" reads as UTC in Go, and "Local" as the host's zone; TypeScript rejects both
u, _, _ := s.GetDailyPanchang(date, delhi, types.PanchangOptions{Timezone: panchang.Zone("")})
fmt.Println(u.Timezone.OffsetMinutes) // 0The *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 Aprils := panchang.New()
at := time.Date(2025, 3, 20, 0, 0, 0, 0, time.UTC)
fmt.Println(panchang.FormatInZone(at, 330)) // 2025-03-20T05:30:00.000+05:30
fmt.Println(panchang.FormatInZone(at, -570)) // 2025-03-19T14:30:00.000-09:30
// The offset is an int, so a fractional one cannot be passed
// A day value, read in the zone it was computed for
ny := types.GeoLocation{Latitude: 40.7128, Longitude: -74.0060}
events, err := s.ComputeSankrantisForYear(2025, ny,
types.YearlyListingOptions{Timezone: panchang.Zone("America/New_York")})
if err != nil {
panic(err)
}
for _, e := range events {
if e.Rashi == 0 { // Mesha
fmt.Println(panchang.FormatInZone(e.Date.Time(), -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 Englishfunc opts(lang types.Language) types.PanchangOptions {
return types.PanchangOptions{
InstantPanchangOptions: types.InstantPanchangOptions{Language: lang},
Timezone: panchang.OffsetMinutes(330),
}
}
func main() {
s := panchang.New()
loc := types.GeoLocation{Latitude: 28.6139, Longitude: 77.2090}
date := time.Date(2025, 1, 28, 0, 0, 0, 0, time.UTC)
en, _, _ := s.GetDailyPanchang(date, loc, opts(panchang.English))
fmt.Println(en.Angas.Tithis[0].Name) // Krishna Chaturdashi
fmt.Println(en.Angas.Vara.Name) // Mangalawara
fmt.Println(en.Calendar.Chandramasa.Name) // Magha
fmt.Println(en.Periods.Choghadiya.Day[0].Name) // Rog
hi, _, _ := s.GetDailyPanchang(date, loc, opts(panchang.Hindi))
fmt.Println(hi.Angas.Tithis[0].Name) // कृष्ण चतुर्दशी
fmt.Println(hi.Angas.Vara.Name) // मंगलवार
fmt.Println(hi.Calendar.Chandramasa.Name) // माघ
fmt.Println(hi.Periods.Choghadiya.Day[0].Name) // रोग
fmt.Println(hi.Angas.Vara.EnglishName) // Tuesday
}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-readable | Localized display |
|---|---|
festival.key ('diwali') | festival.name (“दिवाली”) |
bhadra.location ('paatal') | bhadra.locationName (“पाताल”) |
eclipse.kind / eclipse.subtype | eclipse.description |
muhurtaScore.factors[].code | muhurtaScore.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.
