class HijriDate { final int year; final int month; final int day; const HijriDate({ required this.year, required this.month, required this.day, }); } class HijriDateFormatter { HijriDateFormatter._(); static const List _monthNames = [ 'Muharram', 'Safar', 'Rabiul Awal', 'Rabiul Akhir', 'Jumadil Awal', 'Jumadil Akhir', 'Rajab', 'Syaban', 'Ramadan', 'Syawal', 'Zulkaidah', 'Zulhijah', ]; static String format(DateTime date) { final hijri = fromGregorian(date); final monthName = _monthNames[hijri.month - 1]; return '${hijri.day} $monthName ${hijri.year} H'; } // Tabular Islamic calendar conversion. This is deterministic and avoids // adding a new dependency just to replace the hardcoded placeholder dates. static HijriDate fromGregorian(DateTime date) { final jd = _gregorianToJulianDay(date.year, date.month, date.day); var l = jd - 1948440 + 10632; final n = ((l - 1) ~/ 10631); l = l - 10631 * n + 354; final j = (((10985 - l) ~/ 5316) * ((50 * l) ~/ 17719)) + ((l ~/ 5670) * ((43 * l) ~/ 15238)); l = l - (((30 - j) ~/ 15) * ((17719 * j) ~/ 50)) - ((j ~/ 16) * ((15238 * j) ~/ 43)) + 29; final month = (24 * l) ~/ 709; final day = l - ((709 * month) ~/ 24); final year = 30 * n + j - 30; return HijriDate(year: year, month: month, day: day); } static int _gregorianToJulianDay(int year, int month, int day) { final a = (14 - month) ~/ 12; final y = year + 4800 - a; final m = month + 12 * a - 3; return day + ((153 * m + 2) ~/ 5) + 365 * y + (y ~/ 4) - (y ~/ 100) + (y ~/ 400) - 32045; } }