jalali_date v1.2.1

Iranian holidays with iranian_holidays

Iran's official holidays for jalali_date dates in Dart: calculated offline including the lunar Hijri ones, or from holidayapi.ir, Calendarific or Google Calendar.

Iranian holidays and events for jalali_date dates. تعطیلات و مناسبت‌های تقویم رسمی ایران برای تاریخ‌های jalali_date.

Two ways to get holidays, and you choose one explicitly:

  • Offline: OfflineHolidaySource calculates the official holidays on the device, with no network and no third party. Religious holidays follow the lunar Hijri calendar; their dates come from the predicted first sighting of the new crescent in Iran.
  • Online: a holiday service such as holidayapi.ir, Calendarific, or Google Calendar, or one of your own. It follows announcements and lists every event of the calendar, not only days off.

FallbackHolidaySource combines both: online first, offline when the request fails.

Choosing a source

SourceCost and keyClassKnow before using
Offline calculationFree, no networkOfflineHolidaySourceThe 26 official holidays plus Fridays. Hijri dates are calculated and can be one day off from an announcement made later; such changes never reach it. No other events.
holidayapi.irFree, no keyHolidayApiIrSourceCommunity service, no service level agreement or published terms. Data is extracted from time.ir. One request per day. No CORS headers, so it does not work in browsers or Flutter web. Fridays count as holidays.
CalendarificFree tier with an API key and a monthly request limit; paid plans above itCalendarificSourceCommercial service with Iran coverage; one request per Gregorian year. Shipping the key inside an app exposes it; use a proxy of your own through baseUri. Names are English unless your plan supports language. Fridays are added by this package.
Google Calendar API public holiday calendarFree quota with a Google Cloud API keyGoogleCalendarSourceReads Google's public Iranian holiday calendar, one request per Jalali month. Needs a Google Cloud project with the Calendar API enabled; restrict the key or use a proxy through baseUri. Days off are detected from the event description (Public holiday on the English calendar); pass isHolidayEvent for the Persian calendar. Fridays are added by this package.
Your own tableFreeNo, implement HolidaySourceWorks offline and needs no third party. You update it yourself each year from the official announcement.

Not usable today: Nager.Date is free but has no Iranian data, and time.ir is a website without a public API.

Tell your users where holiday data comes from, for example on an about or settings screen; HolidaySource.name, website, and notice hold that text.

Installation

sh
dart pub add iranian_holidays

Offline holidays

dart
import 'package:jalali_date/jalali_date.dart';
import 'package:iranian_holidays/iranian_holidays.dart';

void main() {
  final offline = OfflineHolidaySource();

  final ashura = offline.dayOf(PersianDate(1405, 4, 4));
  print(ashura.isHoliday); // true
  print(ashura.holidays.first.description); // عاشورای حسینی
  print(ashura.holidays.first.additionalDescription); // 10 محرم 1448

  for (final day in offline.holidaysOf(1406)) {
    print('${day.date} ${day.holidays.map((e) => e.description).join(', ')}');
  }

  print(offline.hijriDate(PersianDate(1405, 1, 1))); // 1 شوال 1447
}

dayOf, holidaysOf, and hijriDate are synchronous; day and month implement HolidaySource like the online sources. holidaysOf lists the official holidays of a Jalali year without Fridays; dayOf and day count Fridays unless you pass fridaysAreHolidays: false.

How Hijri holidays are calculated

A Hijri month starts the day after the evening its new crescent is first seen in Iran. The package computes the new moon and the positions of the Sun and the Moon at sunset (Meeus, Astronomical Algorithms), and checks Yallop's visibility criterion at eight cities across Iran, counting a crescent visible with optical aid (q >= -0.232). Months where the calendar published by the Iranian calendar authority differs are corrected from a table. Checked against the published calendar for every month with a holiday from 1387 to 1406, the result matches all of them. Without the table, the calculation alone matches 174 of these 186 months, and 109 of the 112 from 1395 on. The calendar itself lives in jalali_date as HijriDate and IranianHijri; use it directly when you need Hijri dates without holidays.

What the offline mode cannot do:

  • A month officially starts when the crescent is actually seen, which is announced only days before. A later announcement that moves a holiday is not picked up. Pass the announced start yourself, or use an online source:

    dart
    final offline = OfflineHolidaySource(
      // 1 Muharram 1448 announced for 1405/03/27.
      hijriMonthStarts: {(1448, 1): PersianDate(1405, 3, 27)},
    );
  • Changes to the holiday law are not picked up either; pass your own holidays list (built from OfficialHoliday.jalali and OfficialHoliday.hijri) if the law changes.

  • It lists official days off only, not the many other events of the calendar.

The official holidays

CalendarDateHoliday
Jalali1 to 4 FarvardinNowruz
Jalali12 FarvardinIslamic Republic Day
Jalali13 FarvardinSizdah Bedar
Jalali14 KhordadDeath of Imam Khomeini
Jalali15 Khordad15 Khordad uprising
Jalali22 BahmanVictory of the Islamic Revolution
Jalali29 EsfandOil nationalization day
Hijri9 and 10 MuharramTasua and Ashura
Hijri20 SafarArbaeen
Hijri28 SafarDeath of the Prophet and martyrdom of Imam Hasan
Hijri29 SafarMartyrdom of Imam Reza
Hijri8 Rabi al-AwwalMartyrdom of Imam Hasan Askari
Hijri17 Rabi al-AwwalBirth of the Prophet and Imam Sadiq
Hijri3 Jumada al-ThaniMartyrdom of Fatima
Hijri13 RajabBirth of Imam Ali
Hijri27 RajabMab'ath
Hijri15 Sha'banBirth of Imam Mahdi
Hijri21 RamadanMartyrdom of Imam Ali
Hijri1 and 2 ShawwalEid al-Fitr
Hijri25 ShawwalMartyrdom of Imam Sadiq
Hijri10 Dhu al-HijjahEid al-Adha
Hijri18 Dhu al-HijjahEid al-Ghadir

The Persian names are in OfficialHoliday.iran. Imam Reza is on 29 Safar even in years where Safar has 30 days, as on the published calendars. Fridays are holidays as well.

Example: 1405 and 1406

Output of OfflineHolidaySource().holidaysOf(year), Fridays not listed. Both years match the calendar published on time.ir day for day. A Hijri holiday falls twice in one Jalali year when the lunar year (354 or 355 days) fits inside it: Eid al-Fitr in 1405.

1405

JalaliWeekdayGregorianHolidayCalendar date
1405/01/01شنبه2026-03-21جشن نوروز/جشن سال نو
عید سعید فطر
1 فروردین
1 شوال 1447
1405/01/02یکشنبه2026-03-22عیدنوروز
تعطیل به مناسبت عید سعید فطر
2 فروردین
2 شوال 1447
1405/01/03دوشنبه2026-03-23عیدنوروز3 فروردین
1405/01/04سه‌شنبه2026-03-24عیدنوروز4 فروردین
1405/01/12چهارشنبه2026-04-01روز جمهوری اسلامی12 فروردین
1405/01/13پنجشنبه2026-04-02جشن سیزده به در13 فروردین
1405/01/25سه‌شنبه2026-04-14شهادت امام جعفر صادق (ع)25 شوال 1447
1405/03/06چهارشنبه2026-05-27عید سعید قربان10 ذوالحجه 1447
1405/03/14پنجشنبه2026-06-04رحلت حضرت امام خمینی
عید سعید غدیر خم
14 خرداد
18 ذوالحجه 1447
1405/03/15جمعه2026-06-05قیام 15 خرداد15 خرداد
1405/04/03چهارشنبه2026-06-24تاسوعای حسینی9 محرم 1448
1405/04/04پنجشنبه2026-06-25عاشورای حسینی10 محرم 1448
1405/05/13سه‌شنبه2026-08-04اربعین حسینی20 صفر 1448
1405/05/21چهارشنبه2026-08-12رحلت رسول اکرم؛شهادت امام حسن مجتبی (ع)28 صفر 1448
1405/05/22پنجشنبه2026-08-13شهادت امام رضا (ع)29 صفر 1448
1405/05/30جمعه2026-08-21شهادت امام حسن عسکری (ع)8 ربیع الاول 1448
1405/06/08یکشنبه2026-08-30میلاد رسول اکرم و امام جعفر صادق (ع)17 ربیع الاول 1448
1405/08/22جمعه2026-11-13شهادت حضرت فاطمه زهرا (س)3 جمادی الثانیه 1448
1405/10/02چهارشنبه2026-12-23ولادت امام علی (ع) و روز پدر13 رجب 1448
1405/10/16چهارشنبه2027-01-06مبعث رسول اکرم (ص)27 رجب 1448
1405/11/04یکشنبه2027-01-24ولادت حضرت قائم عجل الله تعالی فرجه و جشن نیمه شعبان15 شعبان 1448
1405/11/22پنجشنبه2027-02-11پیروزی انقلاب اسلامی22 بهمن
1405/12/09یکشنبه2027-02-28شهادت حضرت علی (ع)21 رمضان 1448
1405/12/19چهارشنبه2027-03-10عید سعید فطر1 شوال 1448
1405/12/20پنجشنبه2027-03-11تعطیل به مناسبت عید سعید فطر2 شوال 1448
1405/12/29شنبه2027-03-20روز ملی شدن صنعت نفت ایران29 اسفند

1406

JalaliWeekdayGregorianHolidayCalendar date
1406/01/01یکشنبه2027-03-21جشن نوروز/جشن سال نو1 فروردین
1406/01/02دوشنبه2027-03-22عیدنوروز2 فروردین
1406/01/03سه‌شنبه2027-03-23عیدنوروز3 فروردین
1406/01/04چهارشنبه2027-03-24عیدنوروز4 فروردین
1406/01/12پنجشنبه2027-04-01روز جمهوری اسلامی12 فروردین
1406/01/13جمعه2027-04-02جشن سیزده به در13 فروردین
1406/01/14شنبه2027-04-03شهادت امام جعفر صادق (ع)25 شوال 1448
1406/02/27دوشنبه2027-05-17عید سعید قربان10 ذوالحجه 1448
1406/03/04سه‌شنبه2027-05-25عید سعید غدیر خم18 ذوالحجه 1448
1406/03/14جمعه2027-06-04رحلت حضرت امام خمینی14 خرداد
1406/03/15شنبه2027-06-05قیام 15 خرداد15 خرداد
1406/03/25سه‌شنبه2027-06-15تاسوعای حسینی9 محرم 1449
1406/03/26چهارشنبه2027-06-16عاشورای حسینی10 محرم 1449
1406/05/03یکشنبه2027-07-25اربعین حسینی20 صفر 1449
1406/05/11دوشنبه2027-08-02رحلت رسول اکرم؛شهادت امام حسن مجتبی (ع)28 صفر 1449
1406/05/12سه‌شنبه2027-08-03شهادت امام رضا (ع)29 صفر 1449
1406/05/20چهارشنبه2027-08-11شهادت امام حسن عسکری (ع)8 ربیع الاول 1449
1406/05/29جمعه2027-08-20میلاد رسول اکرم و امام جعفر صادق (ع)17 ربیع الاول 1449
1406/08/12چهارشنبه2027-11-03شهادت حضرت فاطمه زهرا (س)3 جمادی الثانیه 1449
1406/09/21یکشنبه2027-12-12ولادت امام علی (ع) و روز پدر13 رجب 1449
1406/10/05یکشنبه2027-12-26مبعث رسول اکرم (ص)27 رجب 1449
1406/10/23پنجشنبه2028-01-13ولادت حضرت قائم عجل الله تعالی فرجه و جشن نیمه شعبان15 شعبان 1449
1406/11/22جمعه2028-02-11پیروزی انقلاب اسلامی22 بهمن
1406/11/29جمعه2028-02-18شهادت حضرت علی (ع)21 رمضان 1449
1406/12/08یکشنبه2028-02-27عید سعید فطر1 شوال 1449
1406/12/09دوشنبه2028-02-28تعطیل به مناسبت عید سعید فطر2 شوال 1449
1406/12/29یکشنبه2028-03-19روز ملی شدن صنعت نفت ایران29 اسفند

Online holidays

dart
import 'package:jalali_date/jalali_date.dart';
import 'package:iranian_holidays/iranian_holidays.dart';

Future<void> main() async {
  final api = HolidayApiIrSource();
  print(api.notice); // read this before shipping

  final source = CachedHolidaySource(api);
  final day = await source.day(PersianDate(1403, 1, 1));
  print(day.isHoliday); // true
  print(day.holidays.first.description); // جشن نوروز/جشن سال نو

  final mehr = await source.month(1403, 7);
  print(mehr.where((d) => d.isHoliday).map((d) => d.date));
  api.close();
}

Online first, offline as fallback

dart
final source = FallbackHolidaySource(
  CachedHolidaySource(HolidayApiIrSource()),
  OfflineHolidaySource(),
);
final day = await source.day(PersianDate(1405, 4, 4)); // works without network

FallbackHolidaySource uses the second source only when the first throws HolidaySourceException.

Caching

CachedHolidaySource keeps answers in memory, so each day is requested once; failed requests are retried on the next call. CalendarificSource and GoogleCalendarSource already cache whole years or months, so they do not need it. Errors from any source are HolidaySourceException, and API keys are replaced by REDACTED in its URL.

Sources with your own API key

dart
// Calendarific: https://calendarific.com, key from your account.
final calendarific = CalendarificSource(apiKey: calendarificKey);

// Google Calendar API: key from a Google Cloud project with the Calendar API.
final google = GoogleCalendarSource(apiKey: googleKey);

// Persian names from Google; tell it how days off are marked there.
final googleFa = GoogleCalendarSource(
  apiKey: googleKey,
  calendarId: GoogleCalendarSource.persianCalendarId,
  isHolidayEvent: (summary, description) => description.contains('تعطیل'),
);

// Keep the key on your server: a proxy that adds it and forwards the request.
final proxied = CalendarificSource(
  apiKey: 'unused',
  baseUri: Uri.parse('https://api.example.com/calendarific/'),
);

Read keys from your configuration (for example --dart-define), never from source code. These two classes are tested against the providers' documented response formats with mock clients; check the results against the official calendar before you rely on them.

Writing your own source

dart
class MyTableSource implements HolidaySource {
  @override
  String get name => 'Built-in table 1403';

  @override
  Uri get website => Uri.parse('https://example.com/holidays');

  @override
  String get notice => 'Official 1403 holidays, updated by hand.';

  static final _holidays = {
    PersianDate(1403, 1, 1): 'جشن نوروز',
    // ...
  };

  @override
  Future<HolidayDay> day(PersianDate date) async {
    final key = PersianDate(date.year, date.month, date.day);
    final name = _holidays[key];
    return HolidayDay(
      date: key,
      isHoliday: name != null || key.isWeekend,
      events: [if (name != null) HolidayEvent(description: name, isHoliday: true)],
    );
  }

  @override
  Future<List<HolidayDay>> month(int year, int month) {
    final first = PersianDate(year, month, 1);
    return Future.wait(first.daysUntil(first.lastDayOfMonth).map(day));
  }
}
Edit this page on GitHub Last updated