در این صفحه
قبل از ۱٫۰٫۰، هر نسخهٔ minor ممکن است تغییر ناسازگار داشته باشد. هر مورد اینجا با گامهای مهاجرت آمده است. سیاست نسخهگذاری در پایداری API است. این صفحه از جدیدترین نسخه شروع میشود. بخش آخر به ساختهای اولیهٔ قبل از 0.1.0 میپردازد.
از 0.1.x به 0.2.0#
بیشتر برنامهها نیازی به تغییر ندارند. موارد زیر را نگاه کنید. موردهای ۹ تا ۱۲ خروجی کتابخانه را برای بعضی ورودیها عوض میکنند.
ext-mbstringدیگر لازم نیست.composer.jsonقبلاً این افزونه را میخواست. حالا فقط PHP لازم است. کاری لازم نیست. اگرext-mbstringرا فقط برای این بسته بهcomposer.jsonخودتان اضافه کرده بودید، میتوانید حذفش کنید.- قالببندی float.
Format::withSeparator()وformat_number()حالا float را با کوتاهترین عدد اعشاری مینویسند که دوباره همان float را بدهد، با حداکثر ۱۵ رقم معنادار. خطای دودویی دیگر دیده نمیشود. رشتهها عوض نشدهاند و دقیق میمانند. برای رقم بیشتر رشته بدهید.
| فراخوانی | قبل | بعد |
|---|---|---|
withSeparator(-1234567.891) | -۱٬۲۳۴٬۵۶۷٫۸۹۱۰۰۰۰۰۰۰۶۱۴۶۷ | -۱٬۲۳۴٬۵۶۷٫۸۹۱ |
withSeparator(0.1 + 0.2) | ۰٫۳ | ۰٫۳ (بدون تغییر) |
withSeparator(-0.0) | ۰ | ۰ |
اگر نتیجهٔ محاسبهٔ اعشاری را قالببندی میکنید، اول گرد کنید (round($x, 2)) یا رشته بدهید.
NumberToWords::fromWords()سختگیر شد. قبلاً واژهها را به هر ترتیبی جمع میزد.
| ورودی | قبل | بعد |
|---|---|---|
دو صد | 102 | InvalidNumberException (با invalid_number_words) |
بیست یک | 21 | InvalidNumberException |
صد و بیست و | 120 | InvalidNumberException |
پنج و بیست | 25 | InvalidNumberException |
سی و پنج | 35 | 35 |
بین بخشها «و» بگذارید و ترتیب صدگان، دهگان، یکان را رعایت کنید. هر چه convert() بسازد هنوز درست خوانده میشود.
Slugify::make()برای متنی که UTF-8 معتبر نیستRtlyKitExceptionمیدهد (باinvalid_argumentوargumentبرابرtext). قبلاً فقط جداکننده بررسی میشد.RtlyKitThrowableرا بگیرید یا ورودی را اول تمیز کنید.Hijri::format()وHebrew::format()الگوی بلندتر از ۲۵۶ بایت را باInvalidDateExceptionرد میکنند (باinput_too_long، وargumentبرابرformat، وlimitبرابر ۲۵۶).Jalali::format()از قبل همینطور بود. سقف درHijri::MAX_FORMAT_LENGTHوHebrew::MAX_FORMAT_LENGTHاست.- بکاسلش آخر الگوی format در هر سه تقویم نادیده گرفته میشود.
format('Y\')فقط سال را میدهد. IranHolidays::all()وallTitles()وallFixed()برای هر سال جلالی از -620 تا 9377 کار میکنند. قبلاً سالهای قبل از مبدأ هجری و آخرین روز 9377invalid_dateمیدادند. جایی که تعطیلات اسلامی را نشود حساب کرد، فقط تعطیلات ثابت میآید. برای سال بیرون از بازهInvalidDateExceptionمیدهند (باdate_out_of_rangeو context شاملyear،minوmax).- پیام خطاها وقتی ورودی شما را تکرار میکنند آن را به ۴۰ نویسه کوتاه میکنند و UTF-8 معتبر میمانند. اگر روی متن پیام شرط میگذارید، بهجایش روی
getErrorCode()شرط بگذارید. - تاریخهای رسمی تعطیلات ۱۳۸۰ تا ۱۴۰۵. در این سالهای جلالی، متدهای استاتیک (
IranHolidaysوis_iran_holiday()) حالا تاریخهای منتشرشده را میدهند، نه تخمین امالقری. بقیهٔ سالها عوض نشدهاند.
| روز | قبل (تخمین) | بعد (رسمی) |
|---|---|---|
| 1404/01/10 | عید فطر | تعطیل نیست |
| 1404/01/11 | تعطیل عید فطر | عید فطر |
| 1404/01/01 | جشن نوروز + شهادت امام علی | جشن نوروز |
| 1404/12/29 | ملی شدن صنعت نفت + عید فطر | ملی شدن صنعت نفت |
| 1405/01/01 | جشن نوروز + تعطیل عید فطر | جشن نوروز + عید فطر |
در سالهای رسمی فقط عنوانهایی میآیند که در جدول رسمی هستند. سالهای ۱۳۸۰ تا ۱۳۹۳ و ۱۳۹۵ گزارششده هستند: تاریخها از یک منبعاند و فهرست روزها ممکن است کامل نباشد. برای رفتار قبلی در همهٔ سالها، HolidayCalendar::default()->withOfficialData(false) را به کار ببرید. برای اینکه ببینید یک سال از کجا آمده، IranHolidays::sourceOf($year) را بزنید. بیشتر در تقویم تعطیلات.
- اوقات شرعی در عرضهای بالا.
PrayerTimesحالاHighLatitudeRuleدارد. پیشفرضAngleBasedاست. فقط جایی اثر میکند که وقت صبح یا عشا نباشد، یا از طلوع یا غروب دورتر از حد قاعده بیفتد. جنوب حدود ۴۴ درجهٔ شمالی چیزی عوض نمیشود. شمال حدود ۴۴ تا ۴۶ درجه، نزدیک انقلاب تابستانی (ژوئن)، بعضی مقدارها فرق میکنند. وقتی که قبلاًnullبود حالا مقدار دارد.
| مکان و روز (MWL) | قبل (مثل None) | بعد (پیشفرض) |
|---|---|---|
| استکهلم، 2026-06-21 | صبح null، عشا null | صبح 01:54، عشا 23:40 |
| مونیخ، 2026-06-21 | صبح 01:50، عشا 00:12 | صبح 02:51، عشا 23:32 |
برای خروجی قبلی، $prayer->withHighLatitudeRule(HighLatitudeRule::None) را بزنید. nextPrayer() هم حالا نمازی را که بعد از نیمهشب میافتد پیدا میکند. عرضهای جغرافیایی بالا را ببینید.
- اعتبارسنجی موبایل. بررسی شکل همان است، پس اعتبار هیچ ورودی عوض نمیشود. دو چیز تازه است. هر نتیجه کلید
allocatedدارد وMobile::isAllocated()آن را به شکل bool میدهد. جدول اپراتور هم به طرح شمارهگذاری نزدیکتر شد: کلید شاتل موبایل از998به09981و09982محدود شد، کلید آپتل از99910به9991گسترده شد، و0923و0931و0932و0934اضافه شدند.
| شماره | اپراتور قبل | اپراتور بعد |
|---|---|---|
09981234567 | شاتل موبایل | شاتل موبایل |
09983112345 | شاتل موبایل | null (تخصیصیافته، ولی دارنده تأیید نشده) |
09231234567 | null | رایتل |
09321234567 | null | تالیا |
اگر کل آرایهٔ details() را مقایسه میکنید، منتظر کلید اضافهی allocated باشید.
- عدد به حروف عربی.
convert($n, 'ar')بدون گزینه برای هر عدد زیر 109 همان متن قبلی را میدهد. حالا عدد تا 1027 هم قبول میکند، که قبلاًnumber_too_largeمیداد. گزینههای تازه و عدد ترتیبی در عدد به حروف عربی است. - پلتفرمها. PHP 8.2 تا 8.5، Laravel 11 و 12 و 13 و Carbon 3 پشتیبانی میشوند. پایداری API را ببینید.
از ساختهای اولیه (قبل از 0.1.0): توابع کمکی در فضاینام#
۱. توابع کمکی سراسری دیگر پیشفرض تعریف نمیشوند#
jdate() و to_persian() و is_national_code() و بقیه را سراسری تعریف میکردند. این میتوانست با کد شما یا بستهٔ دیگری تداخل کند، پس برداشته شد. توابع کمکی حالا در فضاینام RtlyKit هستند و چیزی سراسری تعریف نمیشود.۲۷ تابع کمکی: jdate، hdate، hebrew_date، to_persian_digits، to_english_digits، to_persian، to_english، is_national_code، is_sheba، is_bank_card، is_mobile، is_postal_code، is_vehicle_plate، validate_national_code، validate_sheba، validate_bank_card، validate_mobile، validate_postal_code، validate_vehicle_plate، number_to_words، normalize_text، contains_rtl، text_direction، is_iran_holiday، prayer_times، format_number و ordinal.
راه الف: هر چه لازم دارید import کنید (پیشنهاد ما).
use function RtlyKit\jdate;
use function RtlyKit\is_national_code;
echo jdate('2026-03-21')->format('Y/m/d'); // 1405/01/01
یا با نام کامل صدا بزنید: \RtlyKit\jdate('2026-03-21').
راه ب: نامهای کوتاه سراسری قبلی را برگردانید. یک بار Globals::register() را صدا بزنید، مثلاً در فایل راهاندازی:
\RtlyKit\Globals::register();
echo jdate('2026-03-21')->format('Y/m/d'); // 1405/01/01، مثل قبل کار میکند
register() فقط نامهای آزاد را تعریف میکند. تابع موجود را عوض نمیکند و خطا پرتاب نمیکند. نامهایی را که چون جای دیگری استفاده شده بودند رد کرده، برمیگرداند. چند بار صدا زدنش مشکلی ندارد:
$skipped = \RtlyKit\Globals::register();
if ($skipped !== []) {
error_log('RTLY-Kit globals skipped: '.implode(', ', $skipped)); // برای اینها از \RtlyKit\name() استفاده کنید
}
service provider در Laravel هم تابع سراسری ثبت نمیکند. در Blade بنویسید {{ \RtlyKit\jdate($post->created_at)->format('j F Y') }}، یا Globals::register() را در AppServiceProvider::register() صدا بزنید. بیشتر در توابع کمکی و سراسری.
۲. تغییرهای دیگر که باید بدانید#
| تغییر | چه کار کنید |
|---|---|
اعتبارسنجها هر مقداری را قبول میکنند. هر شش تا RtlyKit\Contracts\Validator را دارند (validate(mixed): Result و isValid(mixed): bool). ورودی غیررشتهای (null، آرایه، شیء) یک Result نامعتبر با invalid_type میدهد. ورودی بیش از ۴۰۹۶ بایت input_too_long میدهد. برای ورودی بد هیچوقت خطا پرتاب نمیکنند. | try و بررسی نوع دور اعتبارسنج را بردارید. مرور اعتبارسنجها را ببینید. |
خطاها کد دارند. getErrorCode() (یک enum به نام ErrorCode) و getContext() روی هر خطای کتابخانه هست. | کاری لازم نیست. روی کد شرط بگذارید، نه روی متن پیام. مدیریت خطا را ببینید. |
Slugify::make() خطا میدهد (RtlyKitException با input_too_long یا invalid_argument) اگر جداکننده UTF-8 معتبر نباشد یا از ۶۴ بایت بلندتر باشد. | فقط وقتی مهم است که جداکننده را کاربر تعیین کند. RtlyKitThrowable را بگیرید. |
تقویمها قرارداد مشترک دارند. Jalali و Hijri و Hebrew اینترفیس RtlyKit\Contracts\CalendarDate را دارند. مقایسهها و diffIn*() یک CalendarDate یا هر DateTimeInterface قبول میکنند، make() یک CalendarDate قبول میکند، و equals() و isBefore() و isAfter() نامهای تازه هستند. | فراخوانیهای قبلی کار میکنند. تبدیل و مقایسه را ببینید. |
دادههای مرجع جابهجا شدند به resources/data/*.php. | اگر کلاسهای جدول قبلی را مستقیم میخواندید (هیچوقت API نبودند)، به کلاسهای عمومی مثل Hijri یا Sheba::getBankName() یا NationalCode::getLocation() بروید. |
عشای مکه در رمضان عوض شد. PrayerTimes::METHOD_MAKKAH حالا در رمضان عشا را مغرب + ۱۲۰ دقیقه میدهد (روش امالقری) و در بقیهٔ زمان + ۹۰ دقیقه. ساخت قبلی همیشه ۹۰ میداد. | عشای رمضان ۳۰ دقیقه دیرتر میشود. این رفع باگ است. مقدارهای مورد انتظار ذخیرهشده را بهروز کنید. نمونه پایینتر است. |
رفتار مکه (2026-03-01 در رمضان است و 2026-03-21 نیست):
use RtlyKit\Prayer\PrayerTimes;
$mecca = PrayerTimes::forCity('mecca', PrayerTimes::METHOD_MAKKAH);
foreach (['2026-03-01', '2026-03-21'] as $d) {
$t = $mecca->getTimes(new DateTimeImmutable($d));
echo $d, ' maghrib ', $t['maghrib'], ' isha ', $t['isha'], "\n";
}
// 2026-03-01 maghrib 18:25 isha 20:25
// 2026-03-21 maghrib 18:32 isha 20:02
نکتههای مهم تغییرنامه برای سری 0.x#
اینها نکتههایی از تغییرنامهاند که کاربران میبینند. فهرست کامل در CHANGELOG.md مخزن است.
رفتارهایی که عوض شد#
- ورودی تقویم بیرون از بازه خطا میدهد. سال، زمان یونیکس و مقدار خیلی بزرگ
add*()وsub*()بیرون از بازه، بهجایTypeErrorیا تاریخ سرریزشده،InvalidDateExceptionمیدهند. بازهها: جلالی -620 تا 9377، هجری 1 تا 9665، عبری 3762 تا 13759 (سقفها). - قاعدهٔ رشته در
make()ثابت شد. سال کمتر از 1700 (در عبری 3000 یا بیشتر) در تقویم همان کلاس خوانده میشود و بقیه میلادی است. رشتهٔ خالی خطا میدهد وnullیعنی همین الان. رشتهٔ میلادی ISO با سال کمتر از 1700 جلالی یا هجری خوانده میشود، پس برای چنین تاریخیDateTimeImmutableبدهید (پرسشهای متداول). - تعطیلات. تاریخهای رسمی برای جلالی ۱۳۸۰ تا ۱۴۰۵ (بالا را ببینید). برای بقیهٔ سالها تعطیلات اسلامی فقط برای ۱۳۰۰ تا ۱۵۰۰ هجری قمری گزارش میشود و سال بیرون از بازهٔ جلالی
InvalidDateExceptionمیدهد. - ورودی عدد.
NumberToWords::convert()وFormat::ordinal()floatصحیح (3.0) را قبول میکنند و برای float کسری وNaNوINFInvalidNumberExceptionمیدهند. - سقف ورودی (امنیت): رشتههای بیش از ۴۰۹۶ بایت در
NumberToWordsوFormatرد میشوند وFormat::withSeparator()عدد بیش از ۱۰۰۰ نویسه را رد میکند.InvalidNumberException(باinput_too_long) میدهند. - جدولهای داده فقط موردهای تأییدشده را نگه میدارند.
NationalCode::getLocation()۵۴۷ پیششماره را دارد و برای بقیهnullمیدهد. جدول BIN بانک (۳۹)، کد شبا (۳۸) و اپراتور فقط موردهایی را دارند که دو منبع تأییدشان کردهاند. نامی که قبلاً میآمد ممکن است حالاnullباشد.BankCardشمارهای را که یک رقم تکراری است رد میکند. - هستهٔ اوقات شرعی از نو نوشته شد از معادلههای استاندارد نجومی. فاصله با پیادهسازی قبلی در شبکهٔ مقایسه برای رویدادهای عصر حداکثر ۲ دقیقه بود (میانگین ۰٫۵ دقیقه یا کمتر). ساعت تابستانی برای هر رویداد جدا اعمال میشود و آرگومان سازندهٔ
$elevationتازه است.
چیزهای اضافهشده#
- تقویم عبری با PHP خالص (
Hebrew) بدون نیاز بهext-calendar. تقویم هجری حول جدول امالقری ۱۳۰۰ تا ۱۵۰۰ بازسازی شد، باHijriVariant::Tabularبرای بیرون از آن. - اعتبارسنجی ساختیافته:
Result(isValid()وerrors()وdetails()) و توابعvalidate_*()با کدهای خطای پایدار. NumberToWords::fromWords()، عدد تا ۲۱ رقم، عدد منفی، و عدد به حروف عربی (number_to_words($n, 'ar')).Normalizer::fixHalfSpace()وclean()،Detector::isRtlLocale()وisHebrew()،IranHolidays::getTitles()وisBusinessDay()وnextBusinessDay()، وPrayerTimes::nextPrayer().- Laravel: facade به نام
Jalaliو factory در container، شناسایی خودکار، شش قانون اعتبارسنجی با پیام fa و en و ar، وJalaliCast. - ماکروهای Carbon:
toJalali،jformat،createFromJalali،toHijri،toHebrew،createFromHijri،createFromHebrew. - سلسلهمراتب خطا زیر
RtlyKitThrowable، enum به نامErrorCode،Globals::register()، و قراردادهایCalendarDateوValidator.
رفع شدهها#
- عشای روش مکه در رمضان (بالا توضیح داده شد).
Format::ordinal()برای ۳۰ و ۲۳.Format::withSeparator()رقم فارسی و عربی را بدون گرد کردن قبول میکند.Mobileشکلهای0098و98و9xxxxxxxxxساده را قبول میکند.Shebaشکل ۲۴ رقمیِ ساده را قبول میکند.- کار با منطقهٔ زمانی در اوقات شرعی دور ساعت تابستانی، و خطا برای روش یا ضریب عصر ناشناخته.
- تعریف تکراری تابع
hdate().
~0.2.0)، قبل از هر ارتقای minor این صفحه را بخوانید، و تستهای خودتان را روی تاریخ و اوقات شرعی ذخیرهشده اجرا کنید.