misri_hijri 0.1.2
misri_hijri: ^0.1.2 copied to clipboard
Hijri calendar dates for Dart/Flutter with a choice of calculation system — Misri (fixed tabular, 30-year cycle) or Umm al-Qura (Saudi official, astronomical lookup table) — behind one shared API.
misri_hijri #
Hijri (Islamic) calendar dates for Dart and Flutter. Pick a calculation system; use it through one shared API.
| Engine | Type | How it works | Range |
|---|---|---|---|
MisriHijriCalendar |
HijriCalendarType.misri |
Fixed tabular calendar: a 30-year cycle with a set leap-year pattern. No lookup table, no moon-sighting. | Any year |
UmmAlQuraCalendar |
HijriCalendarType.ummAlQura |
Saudi Arabia's official calendar, backed by an astronomical lookup table. Supports regional adjustments. | ~1356–1500 AH (14 Mar 1937 – 16 Nov 2077 CE) |
Pure Dart, no Flutter dependency: works in Flutter apps, server-side Dart, and CLI tools.
Install #
dependencies:
misri_hijri: ^0.1.2
Quick start #
import 'package:misri_hijri/misri_hijri.dart';
void main() {
// Pick an engine with a single parameter.
final today = Hijri.now(type: HijriCalendarType.ummAlQura);
print(today.format('DDDD, dd MMMM yyyy'));
// Convert from Gregorian.
final d = Hijri.fromDate(
DateTime(2025, 3, 20),
type: HijriCalendarType.misri,
);
print('${d.year}-${d.month}-${d.day}');
// Build from a Hijri date, then go back to Gregorian.
final eid = Hijri.fromHijri(1446, 10, 1, type: HijriCalendarType.ummAlQura);
print(eid.toDateTime());
}
Or use an engine directly when you always know which calendar you need:
final m = MisriHijriCalendar.fromDate(DateTime(2025, 3, 20));
final u = UmmAlQuraCalendar.fromHijri(1446, 9, 1);
The shared interface #
Both engines implement HijriCalendarBase, so your code can take either one:
void printDate(HijriCalendarBase date) {
print(date.format('DDDD, dd MMMM yyyy'));
}
printDate(MisriHijriCalendar.now());
printDate(UmmAlQuraCalendar.now());
HijriCalendarBase gives you the same surface for both engines:
year,month,day,weekday,daysInMonth,isLeapYearmonthName,monthNameShort,weekdayName,weekdayNameShorttoDateTime()— the Gregorian equivalenthijriToGregorian(year, month, day)— convert any Hijri dategetDaysInMonth(year, month),lengthOfYear({year})getMonthDays(month, year)— day-of-month → weekday-name maptoList()→[year, month, day],isoFormat→yyyy-mm-dd,isValid()format(pattern)/formatDate(year, month, day, pattern)/toFormat/fullDate()— see FormattingaddDays(int),addMonths(int)— return a new instance of the same engine;addMonthsclamps the day to the target month's lengthisBefore,isAfter,isAtSameMomentAs,compareTo— compare chronologically, even across engine types (viatoDateTime)
Each engine adds only its constructors (now, yesterday, tomorrow,
fromDate, fromHijri), plus setAdjustments on UmmAlQuraCalendar.
Worked examples #
Conversions produced by this package, for checking against another source. Weekdays are included so you can confirm the exact day.
Misri leap years: the 30-year cycle treats years 2, 5, 8, 10, 13, 16, 19, 21, 24, 27, 29 (year mod 30) as leap, and anchors 1 Muharram 1 AH to 16 July 622 CE. Other tabular converters use the set 2, 5, 7, 10, 13, 16, 18, 21, 24, 26, 29, which can differ by a day or two — compare against one that uses the same rule.
Gregorian → Misri
| Gregorian | Misri Hijri |
|---|---|
| Sun 1 January 1950 | 13 Rabiul Awwal 1369 AH |
| Fri 31 December 1999 | 24 Ramazanul Moazzam 1420 AH |
| Wed 10 April 2024 | 2 Shawwalul Mukarram 1445 AH |
| Fri 6 June 2025 | 10 Zilhijjatil Haram 1446 AH |
| Mon 5 November 2040 | 1 Zilqadatil Haram 1462 AH |
Misri → Gregorian
| Misri Hijri | Gregorian |
|---|---|
| 1 Moharramul Haram 1350 AH | Mon 18 May 1931 |
| 27 Ramazanul Moazzam 1420 AH | Mon 3 January 2000 |
| 10 Zilhijjatil Haram 1446 AH | Fri 6 June 2025 |
| 1 Rabiul Awwal 1447 AH | Sun 24 August 2025 |
| 1 Moharramul Haram 1460 AH | Fri 5 February 2038 |
Gregorian → Umm al-Qura
| Gregorian | Umm al-Qura Hijri |
|---|---|
| Mon 20 May 1940 | 12 Rabi' Al-Akhir 1359 AH |
| Thu 14 August 1980 | 3 Shawwal 1400 AH |
| Mon 15 February 2010 | 1 Rabi' Al-Awwal 1431 AH |
| Sat 1 March 2025 | 1 Ramadan 1446 AH |
| Wed 30 September 2065 | 29 Jumada Al-Akhirah 1488 AH |
Umm al-Qura → Gregorian
| Umm al-Qura Hijri | Gregorian |
|---|---|
| 1 Muharram 1356 AH | Sun 14 March 1937 |
| 1 Muharram 1400 AH | Tue 20 November 1979 |
| 1 Ramadan 1446 AH | Sat 1 March 2025 |
| 1 Shawwal 1446 AH | Sun 30 March 2025 |
| 29 Dhu Al-Hijjah 1500 AH | Mon 15 November 2077 |
The first and last Umm al-Qura rows are the limits of the bundled lookup
table (1 Muharram 1356 AH – 29 Dhu al-Hijja 1500 AH). Dates outside it
throw an ArgumentError.
Formatting #
format(pattern) replaces these tokens. Longest match wins, so DDDD
beats DD and yyyy beats yy.
| Token | Meaning | Example (1446-09-05, en) |
|---|---|---|
d |
Day of month (not zero-padded) | 5 |
dd |
Day of month (zero-padded to 2 digits) | 05 |
m |
Month number (not zero-padded) | 9 |
mm |
Month number (zero-padded to 2 digits) | 09 |
MM |
Short month name | Ram |
MMMM |
Long month name | Ramadan |
yy |
Last two digits of the year | 46 |
yyyy |
Full year | 1446 |
DD |
Short weekday name | Wed |
DDDD |
Long weekday name | Wednesday |
final d = UmmAlQuraCalendar.fromHijri(1446, 9, 5);
d.format('yyyy/mm/dd'); // 1446/09/05
d.format('yyyy/m/d'); // 1446/9/5
d.format('DDDD, dd MMMM yyyy'); // Wednesday, 05 Ramadan 1446
Note: replacement is a single pass over the pattern, so literal text containing
d,m, oryis also substituted. Stick to the tokens above and separators like/,-,,, and spaces.
Locales #
Built-in: en and ar for both engines, plus tr for Umm al-Qura.
UmmAlQuraCalendar.setLocal('ar'); // global default for new instances
final d = UmmAlQuraCalendar.fromHijri(1446, 9, 1, locale: 'ar');
d.format('dd MMMM yyyy'); // ٠١ رمضان ١٤٤٦ (Arabic-Indic digits, zero-padded)
UmmAlQuraCalendar.addLocale('fr', HijriLocale(
longMonths: {1: 'Mouharram', /* ... */},
shortMonths: {/* ... */},
days: {1: 'Lundi', /* ... 7: 'Dimanche' */},
shortDays: {/* ... */},
));
Each instance keeps its own locale, so changing the global default does not affect instances that already exist.
Weekday maps follow Dart's DateTime.weekday convention:
1 = Monday … 6 = Saturday, 7 = Sunday.
Umm al-Qura adjustments #
Regional moon-sighting can shift a month's start by a day. Override
specific month-start indices (same convention as the internal table,
hijriYearMonthIndex + 16260):
final cal = UmmAlQuraCalendar.now();
cal.setAdjustments({/* index: mcjdn */});
Attribution #
The Umm al-Qura lookup table and JDN conversion approach come from the
hijri package (BSD-2-Clause,
Copyright 2018 AHMED ALJOAID). See NOTICE for details.
License #
BSD-2-Clause. See LICENSE.