Hijri — تقویم هجری قمری
یک شیء تاریخ هجری قمری تغییرناپذیر (immutable)، پیادهسازیشده بر پایهٔ Carbon و افزونهٔ ext-intl — با امکان تبدیل به/از Carbon، Jalali و DateTime.
نصب و راهاندازی
ماژول Hijri بخشی از dornica/doravel است و نیازی به نصب جداگانه ندارد.
برای استفاده کافی است در هر بخشی از برنامه کلاس Hijri را وارد کنید:
use Dornica\Foundation\Hijri\Facade\Hijri;
// یا کلاس
use Dornica\Foundation\Hijri\Hijri;
نکته: تابع کمکی سراسری
hijri()توسط این پکیج تأمین میشود.
متدها
now()
تاریخ هجری قمری لحظهٔ جاری:
$date = Hijri::now();
$date = Hijri::now('Asia/Tehran');
$date = Hijri::now(new DateTimeZone('Asia/Tehran'));
// با تابع کمکی
$date = hijri();
parse()
ساخت از رشتهٔ قمری — فرمتهای مجاز: Y-m-d یا Y/m/d با یا بدون زمان:
$date = Hijri::parse('1447-09-15');
$date = Hijri::parse('1447/09/15');
$date = Hijri::parse('1447-09-15 14:30:00');
// با تابع کمکی
$date = hijri('1447-09-15');
hijri() خودداری کنیدparse() — و در نتیجه hijri('...') — رشته را همیشه قمری فرض میکند و هیچ تشخیصی روی میلادی بودن انجام نمیدهد. نکتهٔ مهمتر اینکه در بیشتر موارد خطایی صادر نمیشود و تاریخ نادرست بازگردانده میشود:
// ❌ نادرست و بدون خطا — «2026-07-15» عیناً قمری خوانده میشود
hijri('2026-07-15')->format('Y/m/d'); // 2026/07/15 (مقدار صحیح: 1448/02/01)
// ❌ بروز خطا قطعی نیست و تنها در برخی حالتها رخ میدهد
hijri('2026-07-31');
// InvalidHijriDateException: Invalid Hijri date: 2026/7/31.
// (به دلیل اینکه ماه قمری بیش از 30 روز ندارد، نه به دلیل میلادی بودن سال)
// ✅ شیء تاریخ را مستقیماً ارسال کنید
hijri($user->created_at);
hijri(new DateTime('2026-07-15'));
// ✅ یا در صورتی که تنها اجزای میلادی در دسترس است
Hijri::fromGregorian(2026, 7, 15);
رایجترین موقعیت بروز این خطا زمانی است که تاریخ ابتدا با format() به رشته تبدیل شده و سپس همان رشته به hijri() ارسال میشود:
// ❌ تبدیل غیرضروری به رشته و بازگردانی مجدد
$key = $date->format('Y-m-d');
$label = hijri($key)->format('Y/m/d');
// ✅ تبدیل را روی خود شیء تاریخ انجام دهید
$label = hijri($date)->format('Y/m/d');
تابع کمکی hijri() برای Carbon، DateTime، Jalali و timestamp عددی مسیر صحیح را بهصورت خودکار انتخاب میکند؛ تنها رشته است که قمری فرض میشود.
fromGregorian()
ساخت از تاریخ میلادی:
$date = Hijri::fromGregorian(2026, 5, 24);
$date = Hijri::fromGregorian(2026, 5, 24, 14, 30, 0, 'Asia/Tehran');
fromCarbon()
ساخت از Carbon:
$date = Hijri::fromCarbon(Carbon::now());
$date = Hijri::fromCarbon(Carbon::create(2026, 5, 24, 12, 0, 0));
// با تابع کمکی
$date = hijri(Carbon::now());
fromJalali()
ساخت از Jalali — تبدیل تاریخ شمسی به قمری:
$date = Hijri::fromJalali(jalali());
$date = Hijri::fromJalali(Jalali::now());
// با تابع کمکی
$date = hijri(jalali());
زنجیرهٔ تبدیل:
Jalali (شمسی)←Carbon (میلادی)←Hijri (قمری)
fromDateTime()
ساخت از DateTime:
$date = Hijri::fromDateTime(new DateTime('2026-05-24'));
// با تابع کمکی
$date = hijri(new DateTime('2026-05-24'));
fromTimestamp()
ساخت از Unix timestamp:
$date = Hijri::fromTimestamp(1748044800);
$date = Hijri::fromTimestamp(1748044800, 'Asia/Tehran');
// با تابع کمکی
$date = hijri(1748044800);
فرمتبندی
متدهای آماده
$date = hijri('1447-09-15 08:05:03');
$date->formatDate(); // 1447/09/15
$date->formatDatetime(); // 1447/09/15 08:05:03
$date->formatTime(); // 08:05:03
$date->formatWord(); // 15 رمضان 1447
(string) $date; // 1447/09/15 08:05:03
format()
فرمتبندی سفارشی مشابه date() در PHP:
$date->format('Y-m-d'); // 1447-09-15
$date->format('j F Y'); // 15 رمضان 1447
$date->format('d N Y'); // 15 Ramadan 1447
$date->format('Y/m/d H:i'); // 1447/09/15 08:05
$date->format('Y\\-m\\-d'); // 1447-09-15 (کاراکتر گریز با \)
جدول توکنها:
| توکن | توضیح | مثال |
|---|---|---|
Y | سال چهار رقمی | 1447 |
y | سال دو رقمی | 47 |
m | ماه دو رقمی | 09 |
n | ماه بدون صفر | 9 |
d | روز دو رقمی | 05 |
j | روز بدون صفر | 5 |
H | ساعت ۲۴ ساعته | 08 |
G | ساعت بدون صفر | 8 |
i | دقیقه | 05 |
s | ثانیه | 03 |
F | نام ماه عربی | رمضان |
N | نام ماه انگلیسی | Ramadan |
M | نام کوتاه انگلیسی | Ram |
t | تعداد روزهای ماه | 30 |
U | Unix timestamp | 1748044800 |
نام ماهها
$date->getMonthName(); // رمضان (پیشفرض: عربی)
$date->getMonthName('ar'); // رمضان
$date->getMonthName('en'); // Ramadan
تبدیل
$date = hijri('1447-12-08');
// به Carbon (میلادی)
$carbon = $date->toCarbon();
$carbon->format('Y-m-d'); // 2026-05-24
// به Jalali (شمسی)
$jalali = $date->toJalali();
$jalali->format('Y/m/d'); // 1405/03/03
// به DateTime
$dt = $date->toDateTime();
// به آرایهٔ میلادی
$date->toGregorian();
// ['year' => 2026, 'month' => 5, 'day' => 24]
// Unix timestamp
$date->timestamp(); // int
تغییر تاریخ (Mutation)
تمام متدهای تغییر تغییرناپذیر (immutable) هستند — در هر فراخوانی یک شیء جدید بازگردانده میشود و شیء اصلی بدون تغییر باقی میماند.
$base = hijri('1447-06-15 12:00:00');
// روز
$base->addDay(); // 1447/06/16
$base->addDays(10); // 1447/06/25
$base->subDay(); // 1447/06/14
$base->subDays(5); // 1447/06/10
// هفته
$base->addWeek(); // 1447/06/22
$base->addWeeks(2); // 1447/06/29
$base->subWeek(); // 1447/06/08
// ماه
$base->addMonth(); // 1447/07/15
$base->addMonths(8); // 1448/02/15 (سرریز به سال بعد)
$base->subMonth(); // 1447/05/15
// سال
$base->addYear(); // 1448/06/15
$base->addYears(3); // 1450/06/15
$base->subYear(); // 1446/06/15
// ساعت
$base->addHour(); // ساعت 13
$base->addHours(14); // ساعت 2 بامداد روز بعد
$base->subHour(); // ساعت 11
// دقیقه
$base->addMinutes(90); // ساعت 13:30
$base->subMinute(); // 11:59
// شیء base بدون تغییر باقی مانده است
$base->getDay(); // 15
تنظیمکنندهها
$base->setYear(1448);
$base->setMonth(9);
$base->setDay(1);
$base->setTime(14, 30, 0);
مقایسه
$a = hijri('1447-09-01');
$b = hijri('1447-09-15');
$a->eq($b); // false
$b->gt($a); // true
$a->lt($b); // true
$a->gte($a); // true
$a->lte($b); // true
// بین دو تاریخ
$mid = hijri('1447-09-08');
$mid->between($a, $b); // true
// وضعیت نسبت به زمان حال
hijri('1400-01-01')->isPast(); // true
hijri('1500-01-01')->isFuture(); // true
hijri()->isToday(); // true
// ماه رمضان
hijri('1447-09-15')->isRamadan(); // true
تفاوت
$a->diffDays($b); // 14
$a->diffMonths(hijri('1447-12-01')); // 3
$a->diffYears(hijri('1450-09-01')); // 3
اعتبارسنجی (Validation)
Hijri::isValidDate(1447, 9, 15); // true
Hijri::isValidDate(1447, 13, 1); // false — ماه نامعتبر
Hijri::isValidDate(1447, 1, 31); // false — روز نامعتبر
Hijri::isLeapYear(1447); // true
Hijri::isLeapYear(1446); // false
hijri('1447-09-01')->daysInMonth(); // 29 یا 30
تابع کمکی hijri()
hijri() // لحظهٔ جاری
hijri('1447-09-15') // تجزیهٔ رشتهٔ قمری
hijri('1447-09-15 14:30:00') // با زمان
hijri(Carbon::now()) // از Carbon
hijri(jalali()) // از Jalali (شمسی → قمری)
hijri(new DateTime()) // از DateTime
hijri(1748044800) // از Unix timestamp
hijri('1447-09-15', 'Asia/Tehran') // با تایمزون
Facade
use Dornica\Foundation\Hijri\Facade\Hijri;
Hijri::now();
Hijri::parse('1447-09-15');
Hijri::fromGregorian(2026, 5, 24);
Hijri::fromCarbon(Carbon::now());
Hijri::fromJalali(jalali());
Hijri::isLeapYear(1447);
Hijri::isValidDate(1447, 9, 15);
متدهای دسترسی (Getters)
$date = hijri('1447-09-15 08:05:03');
// متد
$date->getYear(); // 1447
$date->getMonth(); // 9
$date->getDay(); // 15
$date->getHour(); // 8
$date->getMinute(); // 5
$date->getSecond(); // 3
// magic property
$date->year; // 1447
$date->month; // 9
$date->day; // 15
$date->hour; // 8
$date->minute; // 5
$date->second; // 3
استثناها (Exceptions)
| Exception | شرایط بروز |
|---|---|
InvalidHijriDateException | تاریخ نامعتبر، ماه خارج از ۱–۱۲، فرمت ناشناس |
ExtensionNotLoadedException | افزونهٔ ext-intl نصب نشده است |
use Dornica\Foundation\Hijri\Exceptions\InvalidHijriDateException;
try {
$date = hijri('invalid-date');
} catch (InvalidHijriDateException $e) {
// فرمت نامعتبر
}
try {
$date = new Hijri(1447, 13, 1);
} catch (InvalidHijriDateException $e) {
// ماه نامعتبر
}