Most existing Jalali libraries for PHP are either outdated, depend on deprecated functions like strftime(), tied to a specific framework, or have clunky APIs. ParsiDate is built from the ground up for modern PHP:
- ✅ Zero external dependencies — pure PHP 8.1+
- ✅ Immutable by default — no side-effects, no surprises
- ✅ Fluent, chainable API — similar feel to Carbon
- ✅ Full holiday support — official Iranian public holidays built-in (1400–1405+)
- ✅ Period & Range — iterate, filter, split date ranges
- ✅ Persian digit support — نمایش اعداد فارسی out of the box
- ✅ PHP 8.1–8.4 tested and working
composer require mahdyaralipor/parsidateuse ParsiDate\ParsiDate;
use ParsiDate\ParsiDateTime;
use ParsiDate\ParsiPeriod;
// Today
$today = ParsiDate::now(); // e.g. 1403/06/15
echo $today->format('l j M Y'); // شنبه 15 شهریور 1403
// Create & convert
$nowruz = ParsiDate::create(1403, 1, 1);
$greg = $nowruz->toGregorian(); // ['year'=>2024,'month'=>3,'day'=>20]
// Parse
$date = ParsiDate::parse('1403/06/15');
$date = ParsiDate::parse('۱۴۰۳/۰۶/۱۵'); // Persian digits supported
// From Gregorian
$date = ParsiDate::fromGregorian(2024, 3, 20);$date = ParsiDate::create(1403, 1, 1);
$date->addDays(10); // 1403/01/11
$date->subMonths(2); // 1402/11/01
$date->addYears(1); // 1404/01/01
$date->startOfMonth(); // 1403/01/01
$date->endOfMonth(); // 1403/01/31
$date->startOfYear(); // 1403/01/01
$date->endOfYear(); // 1403/12/30 (leap year)$date = ParsiDate::create(1403, 6, 15);
$date->format('Y/m/d'); // 1403/06/15
$date->format('j M Y'); // 15 شهریور 1403
$date->format('D، j F Y'); // شنبه، 15 Shahrivar 1403
$date->formatPersian('Y/m/d'); // ۱۴۰۳/۰۶/۱۵
// Available tokens
// Y=year, m=month(pad), n=month, d=day(pad), j=day
// M=Persian month name, F=English month name
// D=Persian day name, l=English day name
// L=leap(0/1), t=days in month, z=day of yearuse ParsiDate\ParsiDateTime;
$now = ParsiDateTime::now(); // 1403/06/15 14:30:00
$now->format('Y/m/d H:i:s'); // 1403/06/15 14:30:00
$now->formatPersian('Y/m/d H:i'); // ۱۴۰۳/۰۶/۱۵ ۱۴:۳۰
$dt = ParsiDateTime::create(1403, 6, 15, 22, 0, 0);
$dt->addHours(3)->format('H:i'); // 01:00 (next day)
$dt->startOfDay()->format('H:i:s'); // 00:00:00
$dt->endOfDay()->format('H:i:s'); // 23:59:59
// Timezone support
$dt->inTimezone('UTC')->format('H:i');$date = ParsiDate::create(1403, 1, 1);
$date->isHoliday(); // true — Nowruz
$date->holidayName(); // "جشن نوروز"
$date->isWeekend(); // false (it's Wednesday)
$date->isWorkday(); // false (holiday)
// Working day navigation
$date->nextWorkday(); // first workday after this date
$date->previousWorkday(); // last workday before this date
$date->addWorkdays(5); // 5 working days from now (skips weekends & holidays)
$date->workdaysUntil($other); // count working days between two dates
// Custom/updated holidays
use ParsiDate\Holidays\HolidayChecker;
HolidayChecker::setVariableHolidays(1406, [
[3, 15, 'تعطیل فرضی'],
]);
// List holidays
HolidayChecker::ofMonth(1403, 1); // all holidays in Farvardin 1403
HolidayChecker::ofYear(1403); // all holidays in 1403use ParsiDate\ParsiPeriod;
// Create a period
$period = ParsiPeriod::create(
ParsiDate::create(1403, 1, 1),
ParsiDate::create(1403, 1, 31)
);
// Or use shortcuts
$period = ParsiPeriod::ofMonth(1403, 1);
$period = ParsiPeriod::ofYear(1403);
$period = ParsiPeriod::fromDate(ParsiDate::create(1403, 1, 1), 30); // 30 days
// Info
$period->days(); // 31
$period->countWorkdays(); // working days count
$period->countHolidays(); // holidays count
// Filter
$period->toArray(); // all ParsiDate objects
$period->workdays(); // only working days
$period->holidays(); // only official holidays
$period->fridays(); // only Fridays
$period->byDayOfWeek(6); // all Saturdays (6=Sat)
$period->filter(fn($d) => $d->day() % 2 === 0); // custom filter
// Contains & overlap
$period->contains($date); // bool
$period->overlap($other); // ParsiPeriod|null
// Split
$period->splitByDays(7); // weekly chunks
$period->splitByMonth(); // monthly chunks
// Iterable — use in foreach!
foreach ($period as $date) {
echo $date->format('Y/m/d') . PHP_EOL;
}$a = ParsiDate::create(1403, 1, 1);
$b = ParsiDate::create(1403, 6, 1);
$a->before($b); // true
$a->after($b); // false
$a->equalTo($b); // false
$a->between($start, $end); // true/false
$a->diffInDays($b); // 153
$a->diffInMonths($b); // 5Contributions, bug reports, and pull requests are welcome!
git clone https://github.com/Mahdyaralipor/parsidate.git
cd parsidate
composer install
./vendor/bin/phpunit tests/اکثر کتابخانههای موجود برای تاریخ جلالی در PHP یا قدیمی هستن، یا به توابع deprecated مثل strftime() وابستهان، یا به یه فریمورک خاص نیاز دارن. ParsiDate از صفر برای PHP مدرن نوشته شده:
- ✅ بدون وابستگی خارجی — PHP خالص 8.1+
- ✅ Immutable — بدون side-effect
- ✅ API روان و chainable — شبیه Carbon
- ✅ تعطیلات رسمی — تعطیلات ایران از 1400 تا 1405+ به صورت built-in
- ✅ Period و Range — پیمایش، فیلتر و تقسیم بازه زمانی
- ✅ اعداد فارسی — پشتیبانی کامل از ارقام فارسی
- ✅ PHP 8.1 تا 8.4 — تستشده
composer require mahdyaralipor/parsidateuse ParsiDate\ParsiDate;
// امروز
$today = ParsiDate::now();
echo $today->format('l j M Y'); // شنبه 15 شهریور 1403
// ساخت و تبدیل
$nowruz = ParsiDate::create(1403, 1, 1);
$greg = $nowruz->toGregorian(); // ['year'=>2024,'month'=>3,'day'=>20]
// Parse با اعداد فارسی
$date = ParsiDate::parse('۱۴۰۳/۰۶/۱۵');$date = ParsiDate::create(1403, 1, 1);
$date->isHoliday(); // true — نوروز
$date->holidayName(); // "جشن نوروز"
$date->isWeekend(); // false
$date->isWorkday(); // false
$date->nextWorkday(); // اولین روز کاری بعد
$date->addWorkdays(5); // ۵ روز کاری بعد (جمعهها و تعطیلات skip)
$date->workdaysUntil($other); // تعداد روزهای کاری بین دو تاریخuse ParsiDate\ParsiPeriod;
$period = ParsiPeriod::ofMonth(1403, 1); // کل فروردین ۱۴۰۳
$period->days(); // ۳۱
$period->countWorkdays(); // روزهای کاری
$period->workdays(); // لیست ParsiDate های کاری
$period->fridays(); // همه جمعهها
$period->holidays(); // همه تعطیلات رسمی
// قابل استفاده در foreach
foreach ($period as $date) {
echo $date->format('Y/m/d');
}این پروژه تحت لایسنس MIT منتشر شده است.