- Dharmagya
- panchang docs
- Getting Started
Getting Started
panchang · v5.4.0 · MIT
Install the package, compute your first daily panchang, and read the times it gives you back. Every example is shown in TypeScript and Go.
Install
npm install panchang-ts
# or: pnpm add panchang-ts / yarn add panchang-tsgo get github.com/ishankgupta95/panchang/source/go/v5The npm package ships ESM and CJS builds with TypeScript types, targets ES2020 and has no runtime dependencies. It runs in Node.js, modern browsers and React Native (Hermes). See Errors & Compatibility for the version floors.
The Go module needs Go 1.22 or newer and also has no dependencies. It has two packages: github.com/ishankgupta95/panchang/source/go/v5/panchang holds the engine, and github.com/ishankgupta95/panchang/source/go/v5/types holds the data types it takes and returns. Most programs import both.
Neither build downloads an ephemeris file or makes a network call. The positions are worked out in process.
Quick start
import { getDailyPanchang } from 'panchang-ts';
const result = getDailyPanchang(
new Date('2025-01-14T00:00:00Z'), // January 14, 2025 (05:30 IST)
{ latitude: 23.1765, longitude: 75.7885 }, // Ujjain, India
{ timezone: 330 }, // IST = UTC+5:30 = 330 minutes
);
// → DailyPanchangResult | null. Null only when no sunrise-to-sunrise day starts
// on that date (polar latitudes, or an offset far from local solar time).
// Narrow with `if (!result) return;`.
console.log(result!.angas.tithis[0].name); // "Krishna Pratipada"
console.log(result!.angas.nakshatras[0].name); // "Punarvasu"
console.log(result!.angas.vara.name); // "Mangalawara"
console.log(result!.calendar.chandramasa.name); // "Magha"
console.log(result!.calendar.samvat.vikramSamvat); // 2081package main
import (
"fmt"
"time"
"github.com/ishankgupta95/panchang/source/go/v5/panchang"
"github.com/ishankgupta95/panchang/source/go/v5/types"
)
func main() {
s := panchang.New()
day, ok, err := s.GetDailyPanchang(
time.Date(2025, 1, 14, 0, 0, 0, 0, time.UTC),
types.GeoLocation{Latitude: 23.1765, Longitude: 75.7885},
types.PanchangOptions{Timezone: panchang.OffsetMinutes(330)},
)
if err != nil {
panic(err) // bad input: a *types.PanchangError with a stable Code
}
if !ok {
return // no Hindu day starts on this date (polar latitudes, or an offset far from local solar time); not an error
}
fmt.Println(day.Angas.Tithis[0].Name) // Krishna Pratipada
fmt.Println(day.Angas.Nakshatras[0].Name) // Punarvasu
fmt.Println(day.Angas.Vara.Name) // Mangalawara
fmt.Println(day.Calendar.Chandramasa.Name) // Magha
fmt.Println(day.Calendar.Samvat.VikramSamvat) // 2081
fmt.Println(day.Sun.RiseLocal) // 2025-01-14T07:10:16.566+05:30
fmt.Println(day.Date.ISOString()) // 2025-01-14T00:00:00.000Z
}You pass three things: the calendar date, the place, and options. The date is any instant inside the day you want: it is read in your timezone, and its time of day is ignored. A new Date(2025, 0, 14) is midnight in the host's zone, which on a host east of IST is still 13 January in IST. The only option you must set is timezone. Give it minutes from UTC (330 for IST) or an IANA name like 'Asia/Kolkata'. In Go, wrap the offset as panchang.OffsetMinutes(330). Everything else has a default, and Options & Localization lists the lot.
location has no default and never will. A panchang computed for the wrong place does not look wrong. You get a complete, plausible result with some dates off by a day. If you really have no coordinates, resolveLocation gives you a named reference frame and tells you which one you got, so you can label the output the way a printed panchang names the city it was computed for.
Three things to know in Go
- Create a session once with
panchang.New()and reuse it for every call. A session is not safe for concurrent use, so give each goroutine its own. - Calls return three values: the result, an
okflag, and anerr. Checkerrfirst, thenok. A falseokis not a failure. It means no sunrise-to-sunrise Hindu day starts on that date, which happens at polar latitudes and, since 5.4, on a day a fixed offset far from local solar time leaves without a sunrise. It matches thenullthat TypeScript returns there. - An error is a
*types.PanchangErrorand carries a stableCodeyou can branch on, whichpanchang.IsCode(err, types.ErrInvalidDate)matches. TheErr*constants aretypes.ErrorCodevalues rather than errors, soerrors.Iscannot take one. The codes are listed in Errors & Compatibility.
Field names are the TypeScript names in Go casing, so result.angas.tithis[0].name is day.Angas.Tithis[0].Name. The rest of this site uses the TypeScript spelling in prose and shows the Go spelling in the code.
Reading output times
Every Date in a result is a real instant, so .getTime() is the correct epoch millisecond. Next to it sits a *Local companion: an ISO 8601 string with the offset attached. That string is what you show a user.
Go publishes the same pair. The instant is a JSDate: call .Time() for a time.Time (new in 5.4), .Ms() for epoch milliseconds or .ISOString() for UTC. The *Local fields are plain strings, exactly as in TypeScript.
result!.sun.rise; // Date — 2025-01-14T01:40:16.566Z (the actual moment)
result!.sun.riseLocal; // "2025-01-14T07:10:16.566+05:30"
result!.inauspicious.rahuKalam.start; // Date
result!.inauspicious.rahuKalam.startLocal; // string
// Just the wall clock:
result!.sun.riseLocal.slice(11, 16); // "07:10"
// Anything else works too, because the Date is genuinely correct:
new Intl.DateTimeFormat('en-IN', { timeZone: 'Asia/Kolkata', timeStyle: 'short' })
.format(result!.sun.rise); // "7:10 am"// package main + imports as in Quick start.
fmt.Println(day.Sun.Rise.Ms()) // 1736818816566
fmt.Println(day.Sun.Rise.ISOString()) // 2025-01-14T01:40:16.566Z
fmt.Println(day.Sun.RiseLocal) // 2025-01-14T07:10:16.566+05:30
fmt.Println(day.Inauspicious.RahuKalam.StartLocal)
// Just the wall clock:
fmt.Println(day.Sun.RiseLocal[11:16]) // 07:10
// Or go through time.Time, because the instant is genuinely correct:
kolkata, _ := time.LoadLocation("Asia/Kolkata")
fmt.Println(day.Sun.Rise.Time().In(kolkata).Format("3:04 pm")) // 7:10 amFor an instant you worked out yourself, formatInZone renders it the same way. The offset is a whole number of minutes (an int in Go). In TypeScript a fraction throws INVALID_TIMEZONE since 5.4, where 5.3 printed a garbled offset.
import { formatInZone } from 'panchang-ts';
const noon = new Date((result!.sun.rise.getTime() + result!.sun.set.getTime()) / 2);
formatInZone(noon, result!.timezone.offsetMinutes); // "2025-01-14T12:35:59.017+05:30"noon := time.UnixMilli((day.Sun.Rise.Ms() + day.Sun.Set.Ms()) / 2)
fmt.Println(panchang.FormatInZone(noon, day.Timezone.OffsetMinutes))
// 2025-01-14T12:35:59.017+05:30moon.rise and moon.set can be null. The Moon does not rise or set on every calendar day, and that is normal. moon.riseLocal and moon.setLocal are null exactly when they are. Go models this with pointers: Moon.Rise is a *JSDate and Moon.RiseLocal is a *string, so check for nil before you read them.
The result is grouped
DailyPanchangResult has seven groups plus a few top-level fields. The group tells you where to look:
| Group | Holds |
|---|---|
sun | rise / set / nextRise (+ *Local), day and night lengths, the Sun's siderealLongitude and nakshatra |
moon | rise / set (+ *Local), the Moon's siderealLongitude and rashi |
angas | the five limbs — tithis, nakshatras, yogas, karanas, vara |
calendar | masa (solar), chandramasa (lunar), samvat |
muhurtas | abhijit, brahma, vijaya, godhuli, nishita, amritKala, madhyahna, pratahSandhya, sayahnaSandhya, doGhati |
inauspicious | rahuKalam, gulikaKalam, yamaganda, durMuhurta, varjyam, bhadra, gandaMula, panchaka, panchakaInfo, panchakaRahita |
periods | choghadiya, hora, gowri |
Top level: date, location, timezone, ayanamsa, specialYogas, anandadiYoga, festivals, eclipse, chandraBalam, tarabala.
getDailyPanchang vs getInstantPanchang
| What you want | Call |
|---|---|
| A day: calendar, festivals, muhurtas, time slots (Choghadiya, Hora, Gowri), eclipses with sutak | getDailyPanchang |
| A moment: what is running right now, or casting a birth chart | getInstantPanchang |
getInstantPanchang reuses the same group names for the part an instant can answer: sun, moon, angas, calendar and inauspicious. There is no muhurtas or periods group, because those belong to a whole Hindu day. Its results carry no *Local fields either. The call takes no timezone, so there is no zone to render a wall clock in.
When things go wrong
- Bad input throws a typed
PanchangErrorwith a stablecode. In Go it is a*types.PanchangErrorwith the sameCode. Both are listed in Errors & Compatibility, along with the few TypeScript checks that throw a plainRangeError. Since 5.4 an Invalid Date throwsINVALID_DATEinstead of hanginggetSunrise. - At polar latitudes
getDailyPanchangandgetInstantPanchangreturnnullinstead of throwing. Without a sunrise there is no Hindu day to describe. Since 5.4 that includes the last sunless day of a polar night, which used to return the next day's panchang. - On React Native with an older Hermes, pass
timezoneas a number. IANA names needIntl. Performance shows the two-pass rendering pattern.
