jalali_date v1.3.1

Persian date picker for Flutter

jalali_calendar_picker: a Material 3 Jalali date picker and range picker for Flutter with Saturday-first weeks, Persian digits and right-to-left layout.

Persian (Jalali, Shamsi) date picker and range picker for Flutter, built on jalali_date. انتخابگر تاریخ و بازه‌ی تاریخ شمسی برای Flutter.

  • Material 3, follows your app's ColorScheme.
  • Saturday-first weeks, Fridays marked as the weekend.
  • Persian digits by default, Latin digits on request.
  • Right-to-left layout by default, even inside a left-to-right app.
  • Day, month, and year views for quick jumps.
  • Limits with firstDate, lastDate, and selectableDayPredicate.
  • Persian labels; the dialog texts can be changed with helpText, confirmText, and cancelText.

Installation

jalali_calendar_picker is published on pub.dev:

sh
flutter pub add jalali_calendar_picker

jalali_calendar_picker re-exports jalali_date, so one import is enough:

dart
import 'package:jalali_calendar_picker/jalali_calendar_picker.dart';

Dialogs

dart
final date = await showPersianDatePicker(
  context: context,
  initialDate: PersianDate.now(),
  firstDate: PersianDate(1400, 1, 1),
  lastDate: PersianDate(1410, 12, 29),
);
if (date != null) print(date.format('EEEE d MMMM yyyy')); // یکشنبه 1 مهر 1403

final range = await showPersianDateRangePicker(context: context);
if (range != null) print('${range.length} days');

Both return null when the dialog is cancelled or dismissed. The range dialog returns a one-day range when only a start was picked.

ParameterDefault
initialDate / initialRangetoday, clamped to the limits / none
firstDate, lastDatePersianDate.min, PersianDate.max
selectableDayPredicateevery day
persianDigitstrue
helpTextانتخاب تاریخ / انتخاب بازه
confirmText, cancelTextتأیید, لغو
textDirectionTextDirection.rtl

Inline calendars

dart
PersianCalendarDatePicker(
  selectedDate: selected,
  onDateChanged: (date) => setState(() => selected = date),
  selectableDayPredicate: (day) => !day.isWeekend,
)

PersianCalendarRangePicker(
  onRangeChanged: (range) => setState(() => this.range = range),
)

For other selection rules, such as several separate days, use PersianCalendar directly with your own isSelected, isInRange, and onDayTapped.

Holidays

iranian_holidays gives Iran's official holidays, calculated offline on the device or fetched from an online source. The offline source answers synchronously, so it fits selectableDayPredicate directly:

dart
final holidays = OfflineHolidaySource();

PersianCalendarDatePicker(
  selectedDate: selected,
  onDateChanged: (date) => setState(() => selected = date),
  selectableDayPredicate: holidays.isWorkingDay, // no Fridays or holidays
)

With an online source, load a month with HolidaySource.month first, then pass a predicate over the result, or mark the days in your own PersianCalendar cells.

Building a date picker

For a ready-made Flutter date picker and range picker, use jalali_calendar_picker. This package has no widgets, but it has the calendar logic a picker of your own needs. A month grid with Saturday in the first column:

dart
List<PersianDate?> monthCells(int year, int month) {
  final first = PersianDate(year, month, 1);
  return [
    for (var i = 1; i < first.weekdayPersian; i++) null, // leading blanks
    ...first.daysUntil(first.lastDayOfMonth),
  ];
}

final header = [
  for (var i = 0; i < 7; i++) PersianDate(1403, 1, 4).addDays(i).weekdayNameShort,
]; // ش ی د س چ پ ج, 1403/01/04 is a Saturday

Other building blocks:

  • Navigation: addMonths(1), addMonths(-1), addYears(1); the day is clamped, so moving from 1403/06/31 lands on 1403/07/30.
  • Selection limits: PersianDate.min, PersianDate.max, isBefore, isAfter, or a PersianDateRange and contains.
  • Highlights: isToday, isWeekend (Friday), isSameDay for the selected day.
  • Range selection: PersianDateRange with overlaps and days.
  • Text input: PersianDate.tryParse accepts Persian digits from a Persian keyboard.
  • Labels: monthName, weekdayNameShort, format('MMMM yyyy', persianDigits: true).
  • Right-to-left layout is the widget's job; in Flutter, wrap the grid in Directionality(textDirection: TextDirection.rtl, ...).
Edit this page on GitHub Last updated