Introduction
I needed a panchanga (five-limbed Vedic almanac) that could compute tithi, vara, nakshatra, yoga and karana for any date and location. The available Python implementations either wrapped PyEphem or used pre-computed lookup tables covering a limited date range. I ended up writing drikganit: two CLI tools that compute everything from the input date using Swiss Ephemeris and Skyfield, with no external API calls or pre-built almanac files.
The immediate need was cross-checking festival dates across calendar systems. I was already tracking astronomical events through sdrmon and the ham radio logs. Adding a panchanga that I could run offline and verify against the Rashtriya Panchang completed a different kind of observational record: what the sky was doing in terms the traditional calendar actually names.
The toolkit has two main commands: panchanga for daily calculations and panjika for monthly calendar generation.
$ panchanga --help
usage: panchanga [-h] [--when WHEN] [--repeat REPEAT] [--where WHERE]
[--lat LAT] [--lon LON] [--alt ALT] [--table | --csv]
[--events FILE [FILE ...]] [--force] [--generate]
[--list-locations] [--cache] [--clear-cache]
[--update-events] [--theme {rudra,shiva}] [-v]
Twenty locations are built in, from Ujjain to San Francisco:
$ panchanga --list-locations
ahmedabad Ahmedabad, Gujarat, IN
bangalore Bangalore, Karnataka, IN
chennai Chennai, Tamil Nadu, IN
danville Danville, CA, USA
delhi Delhi, IN
mumbai Mumbai, Maharashtra, IN
ujjain Ujjain, Madhya Pradesh, IN
varanasi Varanasi, UP, IN
...
The five elements
| Element | Description |
|---|---|
| Tithi | Lunar day (1-30), based on sun-moon angular separation |
| Vara | Day of the week, with associated deity |
| Nakshatra | The 27 lunar mansions; which one the moon occupies |
| Yoga | Sum of sun and moon longitudes, divided into 27 yogas |
| Karana | Half a tithi, 11 karanas repeating through the month |
Let's have a look at running it for a specific date. The --table flag gives a human-readable output with all the panchanga elements, graha positions, muhurta windows and transition times within the vedic day (sunrise to sunrise):
$ panchanga --when 2026-03-02 --where ujjain --table
Ujjain, Madhya Pradesh, IN @ 2026-Mar-02
Sūrya: ↑06:49 ↓18:29 ↑06:47 / Candra: ↑17:34 ↓05:56
d:11h41m19s / m:12:38:33 / r:12h17m48s
Gocara:
Rāhu 11/Kumbha 24/Śatabhiṣā/3 06:42/18:17 ↑Udit ←Vakri
Ketu 5/Siṃha 11/P.Phālgunī/1 18:12/06:47 ↓Asta ←Vakri
Candra 4/Karkaṭa 9/Āśleṣā/4 17:34/05:56 ↓Asta →Mārgi
Sūrya 11/Kumbha/17 24/Śatabhiṣā/4 06:49/18:29 ↑Udit →Mārgi
...
Pañcāṅga:
Tithi: 14/Caturdaśī (Śukla) → 15/Pūrṇimā @ 17:56
Nakṣatra: 9/Āśleṣā/4 → 10/Maghā/1 @ 07:52
Vāra: 2/Somavāra
Yoga: 6/Atigaṇḍa → 7/Sukarman @ 12:19
Karaṇa: 28/Vaṇija → 29/Viṣṭi @ 17:56 → 30/Bava @ Mar-03/05:29
Māsa: Saura:11/Māgha / Amānta:12/Phālguna / Pūrṇimānta:12/Phālguna
Saṃvatsara: v:2082/52/Kālayukta / s:1947/39/Viśvāvasu
Muhūrta:
Śubha: Abhijit:12:15/13:01 (46m) / Brahma:05:09/06:47 (1h38m)
Aśubha: Rāhu:08:15/09:43 (1h27m) / Yama:11:10/12:38 (1h27m)
Parva:
Māsik Śivarātri / Holikā Dahana
The default output is JSON, which goes to stdout and a cache file. The JSON structure has four top-level keys: config, graha, panchanga and transitions. This feeds into panjika for calendar rendering.
panjika calendar
panjika reads from the panchanga cache and generates monthly calendar views. Let's have a look at the table output for a full month:
$ panjika --when 2026-03 --where ujjain --table
Ujjain, Madhya Pradesh, IN March 2026
Daily:
Day Vara Paksha/Tithi Nakshatra
1 Ravivāra Ś.13/Trayodaśī 8/Puṣya
2 Somavāra Ś.14/Caturdaśī 9/Āśleṣā
3 Maṅgalavāra Ś.15/Pūrṇimā 10/Maghā
4 Budhavāra K.16/Pratipadā 11/Pūrvaphālgunī
5 Guruvāra K.17/Dvitīyā 12/Uttaraphālgunī
...
19 Guruvāra K.30/Amāvāsyā 26/Uttarabhādrapadā
20 Śukravāra Ś.2/Dvitīyā 27/Revatī
21 Śanivāra Ś.3/Tṛtīyā 1/Aśvinī
...
Vrata/Parva:
Mar-02 Māsik Śivarātri · Holikā Dahana
Mar-03 Pūrṇimā · Holī · Dola Pūrṇimā · Phālguna Pūrṇimā
Mar-07 Saṅkaṣṭī Caturthī
Mar-14 Mīna Saṅkrānti
Mar-19 Amāvasyā · Phālguna Amāvasyā
Mar-27 Rāma Navamī
Mar-29 Kāmadā Ekādaśī
The Shukla/Krishna paksha cycle is visible in the table: Shukla (Ś) tithis run from Pratipadā to Pūrṇimā, then Krishna (K) tithis from Pratipadā back to Amāvāsyā. The panjika tool also generates SVG/PNG calendar pages with color-coded paksha cells, moon phase symbols and festival markers.
Astronomical accuracy
drikganit uses Swiss Ephemeris (via swisseph) for planetary positions and Skyfield for rise/set calculations, with the Lahiri ayanamsha as the sidereal reference: the Indian government's official standard. Let's have a look at the actual tithi calculation from the source:
def calculate_tithi(sun_lon, moon_lon):
"""calculate tithi from sun and moon longitudes"""
# elongation (moon - sun)
delta = (moon_lon - sun_lon) % 360
# tithi index (1-30)
index = int(delta / 12) + 1
# progress within tithi
progress = (delta % 12) / 12 * 100
# paksha
paksha = "Śukla" if index <= 15 else "Kṛṣṇa"
return {
'index': index,
'name_iast': tithi_names[index - 1],
'paksha': paksha,
'progress': round(progress, 1),
}
Each tithi spans 12 degrees of sun-moon angular separation. The progress percentage tells you how far into the current tithi the moment falls, which matters for muhurta calculations.
Accuracy against Drik Panchang (which uses Swiss Ephemeris) is within 2 minutes for tithi transitions. For practical use: knowing today's tithi, checking whether a festival falls on the expected day, computing muhurta windows. This is sufficient.
Design considerations
The --csv output mode produces one row per astronomical event (graha rise/set, tithi transition, nakshatra transition, muhurta boundary). This is useful for downstream tools:
$ panchanga --when 2026-03-02 --where ujjain --csv | head -5
datetime,event,vara,paksha,tithi,nakshatra,yoga,karana,lagna,muhurta,masa_am,masa_pm
2026-03-02T06:47:53+05:30,sunrise,Somavāra,Śukla,Caturdaśī,Āśleṣā,Atigaṇḍa,Vaṇija,Kumbha,Rudra,Phālguna,Phālguna
2026-03-02T07:52:15+05:30,nakshatra,Somavāra,Śukla,Caturdaśī,Maghā,Atigaṇḍa,Vaṇija,Mīna,Āhi,Phālguna,Phālguna
2026-03-02T12:19:22+05:30,yoga,Somavāra,Śukla,Caturdaśī,Maghā,Sukarman,Vaṇija,Mithuna,Vidhi,Phālguna,Phālguna
The full year can be pre-generated with --generate --repeat year, which caches all 365/366 days and enriches masa (lunar month) labels using full-month context for correct adhik/nija masa handling.
The calculation functions are self-contained and readable against the astronomical formulae they implement. You can trace a tithi computation back to the sun-moon angular separation, or a nakshatra to the moon's sidereal longitude divided into 27 segments of 13.333 degrees each. No black boxes.
Writing this clarified how much information the five elements actually encode. A single panchanga entry is not just a date annotation — it is the state of four independent astronomical cycles sampled at a point in time. The tool is in daily use.
GitHub: drikganit