Ascendant
Developer guides

Dashas

Calculate Vimshottari, Chara, and Sthira dasha timelines from shared placements and query the period active on any date.

A dasha is a timeline of periods. Each period has a lord, a start, and an end, and each Mahadasha is divided into Antardashas. Ascendant calculates three systems from the same Placements you already have from Chart.generate:

SystemPeriods are ruled byMahadashasAntardashas in eachSchool
VimshottariPlanets, in a fixed cycle99Used with both KP and Parashari
CharaSigns1212Jaimini
SthiraSigns1212Jaimini

This guide builds each one, reads it, and asks which period is running on a given date.

Start from placements

Every dasha function takes the birth Moment and the Placements. Calculate the placements once and reuse them:

import { Chart, Dasha, Runtime } from "astro-ascendant";
import { DateTime, ManagedRuntime } from "effect";

const runtime = ManagedRuntime.make(Runtime.MainLayer);

const located = Chart.LocatedMoment.make({
  moment: Chart.Moment.make({ date: DateTime.makeUnsafe("2000-01-01T12:00:00Z") }),
  latitude: 12.9716,
  longitude: 77.5946,
});

const { placements } = await runtime.runPromise(Chart.generate(located));

The dasha is anchored to the birth moment, so pass the same located.moment you used for the chart.

Vimshottari

Dasha.calculate builds the Vimshottari timeline. It starts from the Moon's star and the portion of that star's period still left at birth.

const timeline = await runtime.runPromise(
  Dasha.calculate(located.moment, placements),
);

The result is an array of nine Mahadashas covering the full 120-year cycle. Each has a mahadasha lord, a start, an end, and nine antardashas:

const day = (date: DateTime.Utc) => DateTime.formatIso(date).slice(0, 10);

for (const period of timeline) {
  console.log(`${period.mahadasha}: ${day(period.start)} to ${day(period.end)}`);
}

For the birth above this prints:

MahadashaStartEnd
Rahu1982-08-122000-08-12
Jupiter2000-08-122016-08-12
Saturn2016-08-122035-08-12
Mercury2035-08-122052-08-12
Ketu2052-08-122059-08-12
Venus2059-08-122079-08-12
Sun2079-08-122085-08-12
Moon2085-08-122095-08-12
Mars2095-08-122102-08-12

The first period starts before birth

The first Mahadasha begins before the birth date, here in 1982, because the person is born part-way through the period of the Moon's star lord. The timeline shows the whole Rahu period, and the birth falls inside it. Use the query below to find what is running on a given date.

Each Mahadasha holds its own Antardashas. The first three of the Rahu Mahadasha are Rahu to 1985-04-24, Jupiter to 1987-09-18, and Saturn to 1990-07-24.

const first = timeline[0];
for (const sub of first.antardashas) {
  console.log(`${sub.mahadasha}-${sub.antardasha}: ${day(sub.start)} to ${day(sub.end)}`);
}

Find the running period

Dasha.at returns the Mahadasha and Antardasha active at a moment. It uses the current time when you pass none:

const when = DateTime.makeUnsafe("2026-11-01T00:00:00Z");
const current = await runtime.runPromise(Dasha.at(timeline, when));

if (current) {
  console.log(current.mahadasha.mahadasha); // "Saturn"
  console.log(current.antardasha.antardasha); // "Sun"
  console.log(day(current.antardasha.start), day(current.antardasha.end));
  // 2026-08-02 2027-07-15
}

It returns null when the date falls outside the timeline, for example in 1900 or 2500, so always check before reading the result.

Chara and Sthira

The Jaimini systems are sign-based. Call them with the same arguments:

const chara = await runtime.runPromise(
  Dasha.calculateChara(located.moment, placements),
);
const sthira = await runtime.runPromise(
  Dasha.calculateSthira(located.moment, placements),
);

Both return an object with a system tag, a provenance, and twelve mahadashas, each with twelve antardashas. Their lords are signs, not planets. For the birth above, both begin at the birth moment:

SystemFirst four Mahadashas
CharaGemini 2000-01-01 to 2006-01-01, Taurus to 2012-01-01, Aries to 2022-01-01, Pisces to 2033-01-01
SthiraLibra 2000-01-01 to 2007-01-01, Scorpio to 2015-01-01, Sagittarius to 2024-01-01, Capricorn to 2031-01-01

Because the result is tagged by system, you can tell the two apart in your own types:

const describe = (dasha: Dasha.RashiDasha) =>
  dasha.system === "Sthira" ? `Brahma: ${dasha.brahma.planet} in ${dasha.brahma.sign}` : "Chara";

Sthira also returns the data behind its Brahma selection: the winning planet and sign, the Atmakaraka used as the reference, the sign strengths for the two candidate signs, and a score for each eligible planet. Here the Brahma is the Moon in Libra. Show or log sthira.brahma.selection if you need to explain the choice.

Query them with Dasha.atRashi, which works for both:

const running = await runtime.runPromise(Dasha.atRashi(chara, when));

if (running) {
  console.log(running.system); // "Chara"
  console.log(running.mahadasha.mahadasha, running.antardasha.antardasha);
  // Pisces Virgo
}

For the same date, the Chara period is Pisces-Virgo, from 2026-08-01 to 2027-07-01, and the Sthira period is Capricorn-Taurus.

Use the matching query

Dasha.at takes a Vimshottari timeline and Dasha.atRashi takes a Chara or Sthira one. Each result carries the types of its own system, so TypeScript stops you from mixing them.

How dates are counted

The systems measure time differently, and you can see it in the boundaries:

  • Vimshottari periods are decimal years converted into calendar months, days, hours, and minutes. Their boundaries fall at any time of day. In the example, Saturn begins at 12:48 UTC on 2016-08-12.
  • Chara and Sthira periods are whole calendar months. Their boundaries fall on the first of a month, such as 2026-08-01.

Treat the exact instants as part of the result. Do not round them to a day if you compare periods across systems.

Which method was used

Every dasha records its method in provenance. Chara reports the Jaimini method kn-rao-co-lord-strength and Sthira reports bv-raman-koch-brahma-strength. Vimshottari returns a plain array, so its provenance sits on each Mahadasha, as the Parashari method moon-nakshatra-balance. The version of each is a date, currently 2026-11-01. Store these with the timeline if you will show it later. See Provenance and verification.

When it fails

Dasha functions fail with typed errors. DashaCalculationError covers a calculation that cannot complete, and DashaEvidenceError means the placements did not contain exactly one entry for a required planet or the Lagna. It points to placements that were built or edited by hand instead of coming from Chart.generate. See Errors and typed failures.

On this page