Skip to main content

jalali_date 1.0.0 copy "jalali_date: ^1.0.0" to clipboard
jalali_date: ^1.0.0 copied to clipboard

Persian (Jalali) calendar for Dart: convert between Gregorian and Jalali dates, leap years, month lengths, formatting. Pure Dart, works on Web, Flutter and the Dart VM.

jalali_date #

pub package CI

Persian (Jalali, Shamsi) calendar for Dart. It converts between Gregorian and Jalali dates in both directions, knows leap years and month lengths, and formats dates with Persian month and weekday names. The conversion is a port of jalaali-js, so century years and leap cycles are handled correctly. It is pure Dart and works on the Web, Flutter, and the Dart VM.

Installation #

dart pub add jalali_date

Or with Flutter:

flutter pub add jalali_date

Usage #

import 'package:jalali_date/jalali_date.dart';

Creating dates #

// From Jalali values. Throws ArgumentError for invalid dates.
final a = PersianDate(1400, 1, 1);

// From the current date and time.
final b = PersianDate.now();

// From a DateTime. The time of day and time zone are kept.
final c = PersianDate.fromDateTime(DateTime.utc(2018, 7, 7, 21, 43, 44));

// From Gregorian values. Out-of-range values roll over like DateTime.
final d = PersianDate.fromGregorian(2021, 3, 21);

// From an ISO 8601 string, parsed with DateTime.parse.
final e = PersianDate.fromGregorianString('2018-07-07T21:43:44.909Z');

print(a.year); // 1400
print(a.month); // 1
print(a.day); // 1

Jalali to Gregorian #

print(PersianDate(1357, 11, 22).toDateTime()); // 1979-02-11 00:00:00.000

A date created from a DateTime returns that exact DateTime, with its time and time zone. A date created from Jalali values returns local midnight of that day.

Leap years and month lengths #

final date = PersianDate(1399, 12, 1);
print(date.isLeapYear); // true
print(date.monthLength); // 30

Comparing dates #

final last = PersianDate(1399, 12, 30);
final first = PersianDate(1400, 1, 1);
print(last.compareTo(first) < 0); // true
print(first == PersianDate.fromGregorian(2021, 3, 21)); // true

Equality and ordering use the day only; the time of day is ignored.

Persian names #

final date = PersianDate.fromGregorian(1979, 2, 11);
print(date.monthName); // بهمن
print(date.weekday); // 7 (DateTime.sunday)
print(date.weekdayName); // یکشنبه

weekday follows DateTime.weekday (1 is Monday, 7 is Sunday), even though the Persian week starts on Saturday. PersianDate.monthNames and PersianDate.weekdayNames hold the full lists.

toString #

final date = PersianDate.fromGregorianString('2018-07-07T21:43:44.909Z');
print(date.toString()); // 1397/04/16
print(date.toString(showTime: true)); // 1397/04/16 21:43:44
print(date.toString(showTime: true, showSecond: false)); // 1397/04/16 21:43
print(date.toString(showDate: false, showTime: true)); // 21:43:44

The flags are showDate, showTime, showHour, showMinute, and showSecond. Every part is zero-padded to two digits. Hiding everything throws ArgumentError. Showing the time of a date created from Jalali values throws StateError, because it has no time of day.

format #

final date = PersianDate.fromGregorian(2021, 3, 21);
print(date.format('d MMMM yyyy')); // 1 فروردین 1400
print(date.format('EEEE yyyy/MM/dd')); // یکشنبه 1400/01/01
Token Output
yyyy year, at least four digits
yy last two digits of the year
MMMM Persian month name
MM month, two digits
M month
dd day, two digits
d day
EEEE Persian weekday name
HH hour (0 to 23), two digits
H hour (0 to 23)
mm minute, two digits
m minute
ss second, two digits
s second

The longest token wins, and every other character is copied as is. There is no escaping, so letters that form a token are always replaced: format('Month') gives 1onth. Time tokens throw StateError for a date created from Jalali values.

In fromJson #

class Item {
  final String text;
  final String? date;

  Item(this.text, this.date);

  factory Item.fromJson(Map<String, dynamic> json) {
    final rawDate = json['date'] as String?;
    return Item(
      json['text'] as String,
      rawDate == null
          ? null
          : PersianDate.fromDateTime(DateTime.parse(rawDate).toLocal())
              .format('yyyy/MM/dd HH:mm'),
    );
  }
}

Supported range #

Jalali -61/01/01 to 3177/10/11, which is Gregorian 560-03-20 to 3798-12-31. Every constructor throws ArgumentError outside that range.

Migrating from 0.1.x #

  • Dart 3 is required, and the package no longer depends on Flutter.
  • toString() pads the date, so 1396/1/1 is now 1396/01/01.
  • year, month, and day are final; create a new PersianDate instead of changing them.
  • PersianDate(year, month, day) throws ArgumentError for invalid dates.
  • The ld field, the monthsLength and kabiseMonthsLength tables, and the public greToJal() are gone. Use isLeapYear and monthLength instead.
  • Conversion results changed for some dates, because 0.1.x was wrong around Gregorian century years and Jalali leap cycles.

Credits #

  • The conversion algorithm is a port of jalaali-js v1.2.8, MIT, Copyright (c) 2020 Behrang Norouzinia. See THIRD_PARTY_NOTICES.md.
  • The first version was based on Java code by breceivemail.
  • Time-part flags on toString by AliRn76.

License #

Apache-2.0. See LICENSE.

3
likes
0
points
70
downloads

Publisher

verified publishernodets.com

Weekly Downloads

Persian (Jalali) calendar for Dart: convert between Gregorian and Jalali dates, leap years, month lengths, formatting. Pure Dart, works on Web, Flutter and the Dart VM.

Repository (GitHub)
View/report issues

Topics

#jalali #persian #shamsi #date #calendar

License

unknown (license)

More

Packages that depend on jalali_date