در این صفحه
چرا این کلاس هست#
در ایران تاریخ مناسبتهای مذهبی را رؤیت هلال تعیین میکند. جدول امالقری یک تخمین میدهد که ۰ تا ۲ روز با اعلام رسمی فرق دارد. برای همین کتابخانه تاریخهای رسمی سالهای ۱۳۹۴ و ۱۳۹۶ تا ۱۴۰۵ را دارد (برای هر سال دو منبع). برای ۱۳۸۰ تا ۱۳۹۳ و ۱۳۹۵ فقط تاریخها را داریم و بقیهٔ سالها تخمین است.
کلاس RtlyKit\Holiday\HolidayCalendar به شما اجازه میدهد خودتان هم دخالت کنید. وقتی هلال دیده شد، تاریخ واقعی را بدهید. اگر سازمانتان روز خاصی را تعطیل کرده، اضافهاش کنید. هر تغییر یک تقویم تازه میسازد و چیزی سراسری عوض نمیشود. کلاس ساده IranHolidays که در تعطیلات دیدید، از همین کلاس با تنظیمات پیشفرض استفاده میکند.
تاریخها از کجا میآیند#
برای سالهای جلالی ۱۳۹۴ و ۱۳۹۶ تا ۱۴۰۵ تاریخهای رسمی داریم، با دو منبع برای هر سال. برای ۱۳۸۰ تا ۱۳۹۳ و ۱۳۹۵ فقط تاریخها را از یک منبع گزارششده داریم. بقیهٔ سالها تخمین از جدول امالقری است. منبعها در دقت و داده آمدهاند.
یک تقویم از پیشفرضها بسازید و بپرسید هر سال از کجا آمده است:
<?php
require 'vendor/autoload.php';
use RtlyKit\Holiday\HolidayCalendar;
use RtlyKit\Holiday\IranHolidays;
$cal = HolidayCalendar::default();
echo $cal->sourceOf(1405)->name, "\n"; // Official
echo $cal->sourceOf(1395)->name, "\n"; // Reported
echo $cal->sourceOf(1406)->name, "\n"; // Estimated
echo implode(' | ', $cal->getTitles(1405, 1, 1)), "\n"; // جشن نوروز | عید فطر
مقدار sourceOf() یکی از این سه است:
| مقدار | معنا |
|---|---|
HolidaySource::Official | تاریخهای رسمی، با دو منبع (۱۳۹۴ و ۱۳۹۶ تا ۱۴۰۵) |
HolidaySource::Reported | فقط تاریخها، از یک منبع (۱۳۸۰ تا ۱۳۹۳ و ۱۳۹۵). فهرست مناسبتها در این سالها کامل نیست |
HolidaySource::Estimated | تخمین از جدول امالقری |
کلاس IranHolidays هم همین را دارد: IranHolidays::calendar() تقویم پیشفرض را میدهد و IranHolidays::sourceOf($year) منبع آن سال را.
آموزش کوتاه#
چهار کار رایج، یکییکی. همه با $cal = HolidayCalendar::default(); شروع میشوند.
۱. جابهجایی همهٔ تعطیلات اسلامی#
اگر میبینید تخمین، چند ماه پشتسرهم یک روز زودتر است، withIslamicOffset() همهٔ تعطیلات اسلامیِ تخمینی را جابهجا میکند. عدد بین -۳ و ۳ است. فقط روی سالهای تخمینی اثر دارد. سالهای رسمی و تعطیلات ثابت دست نمیخورند.
$later = $cal->withIslamicOffset(1);
echo implode(' | ', $cal->getTitles(1406, 12, 7)), "\n"; // عید فطر
echo implode(' | ', $later->getTitles(1406, 12, 7)), "\n"; // (خالی)
echo implode(' | ', $later->getTitles(1406, 12, 8)), "\n"; // عید فطر
echo implode(' | ', $later->getTitles(1405, 1, 1)), "\n"; // جشن نوروز | عید فطر (سال رسمی تغییر نمیکند)
۲. شروع واقعی یک ماه قمری#
وقتی هلال دیده شد و روز اول ماه معلوم شد، همان را بدهید. withHijriMonthStart($hijriYear, $hijriMonth, $firstDay) روز اول ماه را به میلادی میگیرد (رشته، با رقم فارسی هم قبول است، یا هر DateTimeInterface). همهٔ تعطیلات اسلامی آن ماه از همین روز حساب میشوند، حتی در سالهای رسمی. این تغییر از جدول رسمی و از جابهجایی کلی قویتر است.
// اول شوال ۱۴۴۹ طبق تخمین 2028-02-26 است. هلال یک روز دیرتر دیده شد.
$fixed = $cal->withHijriMonthStart(1449, 10, '2028-02-27');
echo implode(' | ', $fixed->getTitles(1406, 12, 7)), "\n"; // (خالی)
echo implode(' | ', $fixed->getTitles(1406, 12, 8)), "\n"; // عید فطر
echo implode(' | ', $fixed->getTitles(1406, 12, 9)), "\n"; // تعطیل عید فطر
چند قاعده برای تاریخی که میدهید:
- حداکثر ۳ روز با تاریخ محاسبهشده فاصله داشته باشد.
- اگر شروع ماه قبل یا بعد را هم دادهاید، فاصلهاش با آن ۲۹ یا ۳۰ روز باشد.
- تعطیلی امام رضا (آخر صفر) از شروع ربیعالاول همان سال حساب میشود، اگر داده باشید. وگرنه از شروع صفر و طول صفر در جدول.
تاریخی که این قاعدهها را نداشته باشد InvalidDateException میدهد.
۳. افزودن و حذف تعطیلی#
withHoliday($date, $title) یک تعطیلی به آن روز اضافه میکند. $date یک شیء Jalali است یا رشتهٔ جلالی مثل '1406/02/03' (رقم فارسی هم قبول است). withoutHoliday($date) همهٔ تعطیلیهای آن روز را برمیدارد. اگر عنوان هم بدهید، فقط همان عنوان حذف میشود.
$company = $cal
->withHoliday('1406/02/03', 'روز شرکت')
->withoutHoliday('1406/01/13'); // روز طبیعت را برمیداریم
echo implode(' | ', $company->getTitles(1406, 2, 3)), "\n"; // روز شرکت
var_dump($company->isHoliday(1406, 1, 13)); // bool(false)
$onlyNowruz = $cal->withoutHoliday('1405/01/01', 'عید فطر');
echo implode(' | ', $onlyNowruz->getTitles(1405, 1, 1)), "\n"; // جشن نوروز
متن عنوان نباید خالی باشد، نباید نویسهٔ کنترلی داشته باشد و حداکثر ۲۰۰ نویسه است.
۴. دیدن منبع هر تعطیلی#
statusOf() برای هر عنوان نشان میدهد از کجا آمده است. جواب فهرستی از HolidayEntry است و هر کدام title و origin دارد. origin یکی از HolidayOrigin::Fixed، Official، Reported، Estimated یا User است.
foreach ($cal->statusOf(1405, 1, 1) as $entry) {
echo $entry->title, ' ', $entry->origin->name, "\n";
}
// جشن نوروز Fixed
// عید فطر Official
foreach ($fixed->statusOf(1406, 12, 8) as $entry) {
echo $entry->title, ' ', $entry->origin->name, "\n";
}
// عید فطر User
با این میتوانید در رابط کاربری کنار تاریخهای تخمینی یک توضیح بگذارید.
جدول گزینهها#
اینها همان گزینههایی هستند که HolidayCalendar::fromArray() و فایل تنظیمات Laravel (کلید holidays) میپذیرند. کلید ناشناخته یا مقدار نادرست InvalidDateException میدهد.
| گزینه | متد معادل | مقدار | پیشفرض |
|---|---|---|---|
islamic_offset | withIslamicOffset() | عدد صحیح -۳ تا ۳. فقط سالهای تخمینی | 0 |
hijri_month_starts | withHijriMonthStart() | نقشه از '1449-10' به تاریخ میلادی روز اول ماه | [] |
extra | withHoliday() | نقشه از تاریخ جلالی به عنوان یا فهرست عنوانها | [] |
removed | withoutHoliday() | تاریخ (همهٔ آن روز) یا نقشه از تاریخ به عنوان یا فهرست عنوانها | [] |
use_official_data | withOfficialData() | true یا false | true |
$custom = HolidayCalendar::fromArray([
'islamic_offset' => 1,
'hijri_month_starts' => ['1449-10' => '2028-02-27'],
'extra' => ['1406/02/03' => 'روز شرکت'],
'removed' => ['1406/01/13'],
]);
echo implode(' | ', $custom->getTitles(1406, 2, 3)), "\n"; // روز شرکت
var_dump($custom->isHoliday(1406, 1, 13)); // bool(false)
کدام تاریخ برنده است#
برای هر روز، این ترتیب اجرا میشود:
- تغییرهای شما:
withHoliday،withoutHolidayوwithHijriMonthStart. - جدول رسمی برای سالهایی که دارد.
- تخمین از جدول امالقری، با
withIslamicOffsetجابهجا میشود.
تعطیلات ثابت شمسی (نوروز، ۲۲ بهمن و ...) دقیقاند و هیچ جابهجایی یا شروع ماهی آنها را عوض نمیکند. فقط خودتان با withoutHoliday میتوانید حذفشان کنید.
در Laravel#
فایل تنظیمات را منتشر کنید:
php artisan vendor:publish --tag=rtly-kit-config
فایل config/rtly-kit.php ساخته میشود و گزینهها زیر کلید holidays هستند:
// config/rtly-kit.php
return [
'holidays' => [
'islamic_offset' => 0,
'hijri_month_starts' => [], // '1449-10' => '2028-02-27'
'extra' => [], // '1406/02/03' => 'روز شرکت'
'removed' => [], // '1406/01/13'
'use_official_data' => true,
],
];
service provider یک HolidayCalendar از این تنظیمات میسازد و در container میگذارد. کلید جاافتاده مقدار پیشفرضش را میگیرد. اگر تنظیمات نادرست باشد، خطا موقع اولین استفاده از تقویم پیش میآید.
use RtlyKit\Holiday\HolidayCalendar;
$calendar = app(HolidayCalendar::class);
$calendar->isHoliday(1406, 2, 3);
is_iran_holiday() و متدهای استاتیک IranHolidays همیشه تقویم پیشفرض را میخوانند، نه تقویمی را که از تنظیمات Laravel ساخته شده. اگر میخواهید تنظیمات شما اعمال شود، تقویم را از container بگیرید.چه چیزی نسبت به نسخههای قبل عوض شد#
در سالهای ۱۳۸۰ تا ۱۴۰۵ نتیجهها حالا از تاریخهای رسمی یا گزارششده میآیند. مثلاً عید فطر ۱۴۴۷ روی ۱۴۰۵/۰۱/۰۱ است. بیرون از این سالها خروجی همان است که قبلاً بود.
برای برگشتن به رفتار قبلی، withOfficialData(false) جدول رسمی را کنار میگذارد و همهٔ سالها را تخمین میزند. رفتار نسخههای قبل از این امکان همین بود.
$estimate = $cal->withOfficialData(false);
echo $estimate->sourceOf(1405)->name, "\n"; // Estimated
echo implode(' | ', $estimate->getTitles(1404, 12, 29)), "\n"; // ملی شدن صنعت نفت | عید فطر
echo implode(' | ', $cal->getTitles(1404, 12, 29)), "\n"; // ملی شدن صنعت نفت
نکتهها و محدودیتها#
- جابهجایی یکنواخت (
withIslamicOffset) برای ماهبهماه تفاوت رؤیت هلال کافی نیست. این فقط یک تأخیر ثابت را درست میکند. برای تاریخ دقیق یک ماه،withHijriMonthStartرا بزنید. - برای سال ۱۴۰۶ هنوز تاریخ رسمی منتشر نشده است (تا 2026-10-08). هر وقت منتشر شود به داده اضافه میشود و کد شما تغییر نمیکند.
- در سالهای
Reported(۱۳۸۰ تا ۱۳۹۳ و ۱۳۹۵) فقط تاریخها از یک منبع است و بعضی مناسبتها در فهرست نیستند، مثلاً تعطیلی امام رضا. اگر لازم دارید، باsourceOf()بفهمید و خودتان باwithHoliday()اضافه کنید. - تعطیلیهای موردی که دولت اعلام میکند (مثل آلودگی هوا) جزو داده نیست. با
withHoliday()اضافهاش کنید.
مرتبط: تعطیلات، راهاندازی Laravel و دقت و داده.