kollavarsham
Malayalam calendar (Kollavarsham / Malayalam Era) for Dart. It converts dates between the Gregorian and Malayalam calendars and gives month and weekday names, nakshatra, tithi and Kerala festival dates. The calculations are pure Dart, need no network access and work on every platform.
import 'package:kollavarsham/kollavarsham.dart';
final today = MalayalamDate.today();
print(today.format('EEEE, d MMMM y')); // ബുധൻ, 11 തുലാം 1202
print(today.format('d MMMM y', script: MalayalamScript.english)); // 11 Thulam 1202
final chingam1 = DateTime(2025, 8, 17).toMalayalamDate();
print(chingam1); // 1201 Chingam 1
final medam1 = MalayalamDate(1201, MalayalamMonth.medam, 1).toGregorian();
print(medam1); // 2026-04-14 (Vishu is the next day this year)
Features
- Conversion both ways between Gregorian and Kollavarsham dates, plus date arithmetic (
addDays,addMonths,daysUntil) and comparison operators. - Names of months, weekdays, nakshatras and tithis, in Malayalam script (ചിങ്ങം) or Latin transliteration (Chingam).
- Formatting and parsing with patterns, optionally using Malayalam digits (൧൨൦൧). Parsing accepts both scripts and common spelling variants.
- Panchanga: the nakshatra, tithi, yoga and karana of any day (taken at sunrise) or any moment, with their start and end times; Rahu kalam, Gulika kalam and Yamagandam; moonrise and moonset; Chandrashtamam.
- Festivals: Onam (Thiruvonam), Atham, Vishu, Sivaratri, Ashtami Rohini, Vinayaka Chathurthi, Navaratri, Deepavali, Attukal Pongala, Thrissur Pooram, Karkidaka Vavu, Guruvayur Ekadashi, Thaipooyam, the Mandala season, Mandala Pooja, Makaravilakku and more, individually or as a list for a year.
- Vrat days: Ekadashi, Pradosham, Shashti, Pournami and Amavasya for a year.
- Christian and Muslim days: Easter and the feasts around it, Christmas, and tentative dates for Ramadan, Eid ul-Fitr, Bakrid, Muharram and Milad-i-Sherif from the tabular Hijri calendar.
- Birth details: the nakshatra with pada, rashi, tithi and Malayalam date of any moment of birth.
- Recurring dates: star birthdays (pirannal), monthly nakshatram, shraddham by tithi, every Ekadashi and other vrat-style days, Malayalam and Gregorian anniversaries, with rules for doubled and missing days.
- North Malabar years:
YearStart.kanninumbers years from Kanni instead of Chingam. - Configurable location: sunrise and sunset are computed for Thiruvananthapuram in IST by default. Kochi and Kozhikode are built in, and you can supply any location.
Format tokens
| Token | Meaning | Example |
|---|---|---|
y |
year | 1201 |
M / MM |
month number | 1 / 01 |
MMM |
short month name | Chi |
MMMM |
month name | ചിങ്ങം |
d / dd |
day | 7 / 07 |
E |
short weekday | ഞാ / Sun |
EEEE |
weekday | ഞായർ |
G / GGGG |
era | കൊ.വ. / കൊല്ലവർഷം |
NNNN |
nakshatra | തിരുവോണം |
TTTT |
tithi | ഏകാദശി |
PPPP |
paksha | വെളുത്ത പക്ഷം |
Wrap literal text in single quotes, e.g. "d MMMM 'ME' y".
Parsing
MalayalamDate.parse('1 ചിങ്ങം 1201'); // 1201 Chingam 1
MalayalamDate.parse('Karkkidakam 3, 1200', pattern: 'MMMM d, y');
MalayalamDate.tryParse('൧ ചിങ്ങം ൧൨൦൧'); // Malayalam digits work too
Month names match in either script, ignoring case and accepting common variants (Karkkidakam, കർക്കിടകം, Vrishchikam…).
Panchanga and festivals
final cal = KollavarshamCalendar.standard;
cal.onam(1201); // 1201 Chingam 20 (2025-09-05)
cal.nakshatraOn(DateTime(2025, 9, 5)); // Nakshatra.thiruvonam
cal.tithiAt(DateTime.now());
cal.nakshatraSpanAt(DateTime.now()); // start and end of the current star
// Malayalam birthday: the Avittam day in Kanni 1202.
cal.daysWithNakshatra(1202, MalayalamMonth.kanni, Nakshatra.avittam);
// Every festival of a year, in order.
for (final (festival, date) in cal.festivalsIn(1201)) {
print('${festival.malayalam}: ${date.toGregorian()}');
}
| Festival | Rule | Checked against |
|---|---|---|
| Onam | Thiruvonam at sunrise in Chingam (the later one if it occurs twice) | 2009–2025 |
| Attukal Pongala | Pooram at sunset in Kumbham (later occurrence) | 2015–2025 |
| Thrissur Pooram | Pooram at midnight in Medam (later occurrence) | 2016–2025 |
| Karkidaka Vavu | Amavasya at the end of the afternoon in Karkidakam, else at sunrise | 2015–2025 |
| Sivaratri | Waning Chathurdashi at midnight, in the lunar month holding Kumbham's sankranti | 2019–2026, 2029 |
| Ashtami Rohini | Waning Ashtami at midnight in Chingam, preferring a night with Rohini | 2021–2025 |
| Vinayaka Chathurthi | Waxing Chathurthi at mid-day, in the lunar month holding Kanni's sankranti | 2019–2026 |
| Vijayadasami | Waxing Dashami at sunrise, in the lunar month holding Thulam's sankranti | 2019–2026 |
| Mahanavami, Durgashtami | One and two days before Vijayadasami | 2019, 2021–2026 |
| Deepavali | Waning Chathurdashi at dawn, in the lunar month holding Thulam's sankranti | 2019–2026 |
| Guruvayur Ekadashi | First waxing Ekadashi at sunrise from Vrischikam 1 | 2019–2025 |
| Thaipooyam | Pooyam on the day nearest the first full moon after Makaram's sankranti | 2020–2027 |
Dhanu Thiruvathira isn't included, because published dates disagree. See the accuracy notes.
Vrat days
cal.vratDays(Vrat.ekadashi, 1201); // every Ekadashi of the year
| Vrat | Lunar day | Read at |
|---|---|---|
| Ekadashi | 11th of each fortnight | sunrise |
| Pradosham | 13th of each fortnight | 72 minutes after sunset |
| Shashti | 6th of the waxing fortnight | sunset |
| Pournami | full moon | mid-day |
| Amavasya | new moon | sunrise |
Christian and Muslim days
easterSunday(2026); // 2026-04-05
christianFeastsIn(2026); // New Year, Palm Sunday ... Christmas
// Tentative: the real dates follow the sighting of the moon.
for (final (festival, date) in hijriFestivalsIn(2026)) {
print('${festival.english}: $date');
}
These take a Gregorian year. Hijri dates come from the tabular calendar and were within two days of Kerala's holiday lists for 2019–2025. Treat them as estimates until a date is announced.
Daily panchangam
final cal = KollavarshamCalendar.standard;
final day = DateTime(2025, 1, 15);
cal.yogaOn(day); // Yoga.priti
cal.karanaOn(day); // Karana.taitila
cal.yogaSpanAt(cal.sunrise(day)!).end; // when that yoga ends (UTC)
cal.kalamOn(day, Kalam.rahu); // 12:32–13:59 IST, as a span in UTC
cal.moonrise(day); // 14:21 UTC, or null if the Moon doesn't rise that day
// Chandrashtamam: the Moon in the eighth rashi from the birth rashi.
cal.chandrashtamam(
Nakshatra.karthika.rashiOf(1), // Mesha; padas 2-4 are in Vrishabha
DateTime.utc(2026),
DateTime.utc(2027),
);
The kalams are eighths of the daytime, so they need a sunrise and sunset; kalamOn returns null where there are none. Times follow the published convention: the Moon rises when its centre reaches the true horizon, without refraction.
Birth details
// A clock time at the calendar's location, whatever the device's time zone.
final birth = BirthDetails.fromLocalTime(DateTime(1950, 9, 17, 11));
birth.nakshatra; // Nakshatra.anizham
birth.pada; // 2
birth.rashi; // Rashi.vrischika
birth.date; // 1126 Kanni 1
// An exact moment.
BirthDetails.fromInstant(DateTime.utc(2025, 9, 4, 19));
date is the civil day at the calendar's location, so a birth after midnight and before sunrise has the new day's date.
Recurring dates
A Recurrence gives the occurrences in a range and the next one. Recurrences compare by value and convert to and from JSON.
// A pirannal: Pooradam in Dhanu each year.
const pirannal = NakshatraInMonth(Nakshatra.pooradam, MalayalamMonth.dhanu);
pirannal.next(DateTime.now());
// A nakshatram: every Pooradam, about every 27 days.
const NakshatraMonthly(Nakshatra.pooradam)
.occurrencesBetween(DateTime(2027), DateTime(2027, 12, 31));
// A shraddham: waning Ekadashi in Karkidakam each year.
TithiInMonth(Tithi(26), MalayalamMonth.karkidakam);
// Every Ekadashi, or every waxing Shashti.
const TithiEveryPaksha(11);
const TithiEveryPaksha(6, paksha: Paksha.shukla);
// Anniversaries.
const MalayalamDateYearly(MalayalamMonth.thulam, 12);
const MalayalamDateMonthly(1);
const GregorianYearly(2, 29);
final json = pirannal.toJson();
Recurrence.fromJson(json); // == pirannal
| Recurrence | A day counts when | Doubled | Missing |
|---|---|---|---|
NakshatraInMonth |
the star is present 6 nazhika after sunrise | later day (DuplicateRule) |
last such day of the previous month (AbsentRule) |
NakshatraMonthly |
as above | every such day | the earlier of the two days around it |
TithiInMonth |
the tithi covers more of that day's afternoon | later day (DuplicateRule) |
last such day of the previous month (AbsentRule) |
TithiEveryPaksha |
the tithi is present at sunrise | the first day | the earlier of the two days around it |
These rules differ between families and almanacs. They are drafts, explained with their sources in docs/pirannal-rules.md, and pirannal dates haven't been checked against a printed almanac yet.
How it works
The Malayalam calendar is sidereal and solar. A month begins at the sankranti, the moment the Sun's sidereal longitude (Lahiri ayanamsa) crosses a multiple of 30°. Kerala applies this rule:
If the sankranti falls within the first three-fifths of the daytime (sunrise to sunset), that day is day 1 of the new month. Otherwise the month starts the next day.
As a result, months run 29 to 32 days, and their lengths differ from year to year. The package computes everything from astronomy rather than lookup tables:
- Sun: the truncated VSOP87 theory (Meeus, Astronomical Algorithms, ch. 32), accurate to about 1″.
- Moon: ELP-2000/82 (Meeus ch. 47), accurate to about 10″.
- Ayanamsa: Lahiri, calibrated so that computed sankranti moments match published panchangams to within a minute (checked against all 2024–2025 sankrantis).
- ΔT (Earth's rotation): yearly IERS values, then the Stephenson–Morrison–Hohenkerk (2016) extrapolation, for 1900–2100.
- Sunrise and sunset: apparent upper limb, with refraction.
All 2,412 sankrantis from 1900 to 2100 agree with the Swiss Ephemeris to within one minute (after allowing for the known difference between its Lahiri mode and the panchang convention). Month starts for that range ship as a 3 KB precomputed table, so a conversion takes well under a microsecond.
Supported years are KollavarshamCalendar.minYear to maxYear (ME 1–2000). Accuracy is best between 1900 and 2100.
Borderline months
If a sankranti falls within a few minutes of the cut-off, almanacs can disagree about which day starts the month. Between 1900 and 2100 there are 31 such months (within 10 minutes), listed in test/fixtures/borderline_months.csv. monthStartMargin(year, month) tells you how close any month came. Month starts already confirmed against Kerala sources are listed in KollavarshamCalendar.verifiedMonthStarts, and you can add your own:
final cal = KollavarshamCalendar(monthStartOverrides: {
(1210, MalayalamMonth.kanni): DateTime(2034, 9, 17),
});
Conventions and limits
- The nakshatra and tithi of a day are the ones in effect at sunrise.
- Onam is the day in Chingam whose sunrise nakshatra is Thiruvonam. If that star falls on two days in Chingam, Onam is the later one. This matches every year from 2009 to 2025 except 2016, where sources themselves disagree (13 or 14 September); the package gives the 14th.
- The year starts with Chingam, as in Travancore and Kochi, unless you pass
yearStart: YearStart.kanni. - Two
MalayalamDates are equal when they denote the same day in equivalent calendars (same location, year convention and overrides).isAtSameDayAscompares days only. - In both verified borderline cases so far (2021 and 2023), almanacs started the month on the sankranti day even though it fell a few minutes after the computed cut-off. If you find another, please open an issue with the source.
Flutter
For calendar widgets and a date picker, see kollavarsham_flutter.
License
MIT
Libraries
- kollavarsham
- Malayalam calendar (Kollavarsham / Malayalam Era) for Dart.