jalali_date v1.2.1

Lunar Hijri dates and Shahanshahi years

Convert Jalali and Gregorian dates to the lunar Hijri calendar as Iran's official calendar counts it, and write or parse years in the Shahanshahi numbering, in Dart.

Hijri calendar

dart
final ashura = PersianDate(1405, 4, 4).toHijri();
print(ashura); // 10 محرم 1448
print(ashura.format('EEEE d MMMM yyyy')); // پنجشنبه 10 محرم 1448
print(HijriDate(1447, 10, 1).toPersianDate()); // 1405/01/01
print(DateTime(2026, 6, 25).toHijriDate().format('yyyy/MM/dd')); // 1448/01/10
print(HijriDate(1447, 12, 1).monthLength); // 29

HijriDate is the lunar Hijri (قمری) date as Iran's official calendar counts it. A month starts the day after the evening its new crescent can be seen in Iran. The start is calculated from the positions of the Sun and the Moon with Yallop's visibility criterion at eight Iranian cities, and a built-in table corrects the months where the published calendar differs. Checked against the calendar published on time.ir for every month with a holiday from Jalali 1387 to 1406, the result matches all of them.

What it cannot do:

  • A month officially starts when the crescent is actually seen, which is announced only days before. The calculation can be one day off from that announcement. Pass the announced start to an IranianHijri of your own:

    dart
    final announced = IranianHijri(
      // 1 Muharram 1448 announced for 1405/03/27.
      monthStarts: {(1448, 1): PersianDate(1405, 3, 27)},
    );
    print(announced.fromPersianDate(PersianDate(1405, 4, 5))); // 10 محرم 1448
  • Only Iran's calendar is implemented; Umm al-Qura and the tabular Islamic calendar are not.

  • Far from today the dates are a calculation only, with nothing to check them against.

MemberDescription
HijriDate(int year, int month, int day)From Hijri values; throws ArgumentError for a day that does not exist
HijriDate.fromPersianDate(PersianDate), PersianDate.toHijri()From a Jalali date
HijriDate.fromDateTime(DateTime), DateTime.toHijriDate()From the calendar day of a DateTime
year, month, dayHijri year, month (1 is Muharram), and day
monthName, monthNamesمحرم to ذوالحجه
monthLength29 or 30
weekday, weekdayName, weekdayNameShortISO weekday and Persian names, like PersianDate
toPersianDate(), toDateTime()Jalali date, and local midnight of the day
==, compareTo, <, <=, >, >=, isBefore, isAfterBy year, month, and day
format(String pattern, {persianDigits})Tokens yyyy, yy, MMMM, MM, M, dd, d, EEEE, E, quoting like PersianDate.format
toString()day monthName year, for example 10 محرم 1448
HijriDate.min, HijriDate.maxThe Hijri dates of PersianDate.min and PersianDate.max
IranianHijri.officialThe calendar every HijriDate conversion uses
IranianHijri({monthStarts})A calendar with announced month starts; fromPersianDate, fromDateTime, date, monthStart, monthLength

A HijriDate created by a calendar with announced starts keeps that calendar's day in toPersianDate, toDateTime, and weekday. Equality and ordering compare year, month, and day only.

Shahanshahi years

dart
final date = PersianDate(1405, 1, 4);
print(date.shahanshahiYear); // 2585
print(date.format('d MMMM yyyy', era: JalaliEra.shahanshahi)); // 4 فروردین 2585
print(date.toString(era: JalaliEra.shahanshahi)); // 2585/01/04
print(PersianDate.parse('2585/01/04', era: JalaliEra.shahanshahi)); // 1405/01/04

The Shahanshahi (شاهنشاهی, Imperial) numbering is the Solar Hijri year plus 1180. Pass era: JalaliEra.shahanshahi to format, toString, parse, or tryParse to write or read years that way. Only the year tokens yyyy and yy change; months, days, and names are the same in both eras. year always holds the Solar Hijri year, and toJson always writes it. No era name is printed; add one as quoted text, for example format("yyyy 'شاهنشاهی'", era: JalaliEra.shahanshahi). parse with the Shahanshahi era accepts years 1119 to 4357 and throws FormatException outside them.

Edit this page on GitHub Last updated