On this page
These limits are on purpose. They keep every call cheap and predictable, and they stop untrusted input from turning into a wrapped-around date or an expensive computation. Going over a limit always raises a documented RtlyKitException (see Error handling) or, for validators, gives an invalid Result.
Calendar year ranges#
Every supported date of every calendar maps to a Gregorian year between 1 and 9999. So any value the classes produce fits in a DateTimeImmutable without wrapping around. The ranges are the public constants MIN_YEAR and MAX_YEAR:
| Calendar | MIN_YEAR | MAX_YEAR | Gregorian date of 1/1 of those years |
|---|---|---|---|
Jalali | -620 | 9377 | 0001-03-21 .. 9998-03-20 |
Hijri | 1 | 9665 | 0622-07-19 .. 9998-10-12 |
Hebrew | 3762 | 13759 | 0001-09-06 .. 9998-10-15 |
<?php
require __DIR__.'/vendor/autoload.php';
use RtlyKit\Calendar\{Hebrew, Hijri, Jalali};
foreach ([Jalali::class, Hijri::class, Hebrew::class] as $class) {
printf(
"%-7s %5d..%-5d %s .. %s\n",
(new ReflectionClass($class))->getShortName(),
$class::MIN_YEAR,
$class::MAX_YEAR,
$class::create($class::MIN_YEAR, 1, 1)->toGregorian()->format('Y-m-d'),
$class::create($class::MAX_YEAR, 1, 1)->toGregorian()->format('Y-m-d'),
);
}
// Jalali -620..9377 0001-03-21 .. 9998-03-20
// Hijri 1..9665 0622-07-19 .. 9998-10-12
// Hebrew 3762..13759 0001-09-06 .. 9998-10-15
Every entry point follows the range: make, create, createFromFormat, Unix timestamps, add*() and sub*() (including huge amounts), the helpers and the Carbon macros. A value outside the range throws InvalidDateException. Nothing returns a wrapped-around date, and no TypeError or ValueError escapes.
Amounts and timestamps#
- An
addDays()orsubDays()amount (and hours, minutes, seconds) larger than the span of the whole supported calendar (about 3.7 million days, or the same span in hours, minutes or seconds) is refused up front withInvalidDateException. A smaller amount that lands outside the supported years is refused too. - A Unix timestamp must fall within Gregorian years 1 to 9999 (with a little room for the time zone). Anything further out is refused.
Hebrew::addMonths()andaddYears()take the same short time however large the amount is.
String-year thresholds#
A string such as 1405/01/01 or 1405-01-01 passed to make() or a helper is read as a date of the calendar itself when the year is below the threshold. Otherwise it is read as a Gregorian string:
| Class | Own-calendar year | Otherwise |
|---|---|---|
Jalali / jdate() | below 1700 | Gregorian |
Hijri / hdate() | below 1700 | Gregorian |
Hebrew / hebrew_date() | 3000 or more | Gregorian |
To pass a real Gregorian date below the threshold (for example the year 999), use a DateTimeImmutable. It is never reinterpreted. See the FAQ.
Umm al-Qura range#
- The embedded Umm al-Qura month table covers AH 1300 to 1500 (1882-11-12 to 2077-11-16). Outside it, and always for
HijriVariant::Tabular,Hijriuses arithmetic rules that can differ from observation by a day or two.Hijri::hasUmmAlQuraData($year)tells you whether a year is covered. Years AH 1318 to 1500 are the ones checked against the official KACST calendar (Hijri::ummAlQuraVerifiedRange()). IranHolidaysuses official or reported dates for the Jalali years 1380 to 1405. For other years it reports Islamic holidays only inside the Umm al-Qura range. Outside it, and for years before the Hijri epoch, only the fixed Jalali holidays are returned, without an exception.all(),allTitles()andallFixed()work for every Jalali year from -620 to 9377.
Input size caps#
| Where | Limit | When exceeded |
|---|---|---|
Validators (NationalCode, Sheba, BankCard, Mobile, PostalCode, VehiclePlate) | 4096 bytes per string | invalid Result, error input_too_long |
NumberToWords::convert() and fromWords() (string input) | 4096 bytes | InvalidNumberException, input_too_long |
Format string input (withSeparator()) | 4096 bytes | InvalidNumberException, input_too_long |
Format::withSeparator() and format_number() | 1000 characters in the plain decimal number (whole and fraction digits together) | InvalidNumberException, input_too_long |
Slugify::make() separator | 64 bytes, valid UTF-8 | RtlyKitException (input_too_long or invalid_argument) |
format() pattern (Jalali, Hijri, Hebrew) | 256 bytes (MAX_FORMAT_LENGTH on each class) | InvalidDateException |
The caps are part of the contract (see API stability).
Number ranges#
| Function | Range | Beyond it |
|---|---|---|
number_to_words($n) (Persian, default) | integers up to 21 digits (less than 10^21), and negatives | InvalidNumberException, number_too_large |
number_to_words($n, 'ar') and NumberToWords::convert($n, 'ar', $options) | integers less than 10^27, and negatives | InvalidNumberException, number_too_large |
NumberToWords::ordinal($n, 'ar') | 1 to 99 | InvalidNumberException (invalid_number for 0 or less, number_too_large above 99) |
number_to_words($n, 'de') or any other locale | only fa and ar | UnsupportedLocaleException |
NumberToWords::convert(), Format::ordinal() | whole numbers. Whole floats such as 3.0 are accepted | InvalidNumberException for 1.5, NaN, INF |
Format::ordinal() | non-negative integers | InvalidNumberException |
use function RtlyKit\number_to_words;
echo number_to_words(999999999, 'ar'), "\n";
// تسعمئة وتسعة وتسعون مليون وتسعمئة وتسعة وتسعون ألف وتسعمئة وتسعة وتسعون
// number_to_words(str_repeat('9', 27), 'ar') throws InvalidNumberException (number_too_large, limit "10^27 - 1")
// number_to_words(str_repeat('9', 22)) throws InvalidNumberException (number_too_large, limit "10^21 - 1")
Setting ranges#
| Setting | Range | Beyond it |
|---|---|---|
HolidayCalendar::withIslamicOffset() | -3 to +3 days | InvalidDateException |
HolidayCalendar::withHijriMonthStart() | within 3 days of the computed start. 29 or 30 days from a neighbouring month start you gave | InvalidDateException |
PrayerTimes::withTune() | -30 to +30 minutes, whole numbers, for fajr, sunrise, dhuhr, asr, maghrib, isha | InvalidPrayerConfigException |
Data coverage#
| Data | Coverage |
|---|---|
| Bank card BINs | 39 BINs. Others give null from getBankName() |
| Sheba bank codes | 38 codes. Others give null |
| National-code place of issue | 547 prefixes. Others give null |
| Official holiday dates | Jalali years 1394 and 1396 to 1405 (official), 1380 to 1393 and 1395 (reported). Other years are estimated |
Prayer-time cities (PrayerTimes::forCity()) | 14: tehran, mashhad, isfahan, shiraz, tabriz, qom, mecca, medina, riyadh, istanbul, cairo, dubai, baghdad, jakarta. For any other place, use new PrayerTimes($lat, $lng, ...) |
| Prayer methods | Tehran, MWL, ISNA, Egypt, Makkah, Karachi. Asr factor 1 (standard) or 2 (Hanafi) |
| Prayer times at high latitudes | The default rule fills in a time the sun cannot produce. With HighLatitudeRule::None that time is null, not an error |
See Accuracy and data for what these tables are based on.
Platform limits#
PHP 8.2 to 8.5 with no extension beyond a standard build, Laravel 11, 12 and 13, and Carbon 3. See API stability.