Limits

Every hard limit in one place. Supported year ranges, input size caps, number-word ranges, the Umm al-Qura range, tuning ranges and the other numeric boundaries of the library.

On this page
  1. Calendar year ranges
    1. Amounts and timestamps
    2. String-year thresholds
    3. Umm al-Qura range
  2. Input size caps
  3. Number ranges
  4. Setting ranges
  5. Data coverage
  6. Platform limits

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:

CalendarMIN_YEARMAX_YEARGregorian date of 1/1 of those years
Jalali-62093770001-03-21 .. 9998-03-20
Hijri196650622-07-19 .. 9998-10-12
Hebrew3762137590001-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() or subDays() 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 with InvalidDateException. 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() and addYears() 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:

ClassOwn-calendar yearOtherwise
Jalali / jdate()below 1700Gregorian
Hijri / hdate()below 1700Gregorian
Hebrew / hebrew_date()3000 or moreGregorian

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, Hijri uses 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()).
  • IranHolidays uses 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() and allFixed() work for every Jalali year from -620 to 9377.

Input size caps#

WhereLimitWhen exceeded
Validators (NationalCode, Sheba, BankCard, Mobile, PostalCode, VehiclePlate)4096 bytes per stringinvalid Result, error input_too_long
NumberToWords::convert() and fromWords() (string input)4096 bytesInvalidNumberException, input_too_long
Format string input (withSeparator())4096 bytesInvalidNumberException, 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() separator64 bytes, valid UTF-8RtlyKitException (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#

FunctionRangeBeyond it
number_to_words($n) (Persian, default)integers up to 21 digits (less than 10^21), and negativesInvalidNumberException, number_too_large
number_to_words($n, 'ar') and NumberToWords::convert($n, 'ar', $options)integers less than 10^27, and negativesInvalidNumberException, number_too_large
NumberToWords::ordinal($n, 'ar')1 to 99InvalidNumberException (invalid_number for 0 or less, number_too_large above 99)
number_to_words($n, 'de') or any other localeonly fa and arUnsupportedLocaleException
NumberToWords::convert(), Format::ordinal()whole numbers. Whole floats such as 3.0 are acceptedInvalidNumberException for 1.5, NaN, INF
Format::ordinal()non-negative integersInvalidNumberException
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#

SettingRangeBeyond it
HolidayCalendar::withIslamicOffset()-3 to +3 daysInvalidDateException
HolidayCalendar::withHijriMonthStart()within 3 days of the computed start. 29 or 30 days from a neighbouring month start you gaveInvalidDateException
PrayerTimes::withTune()-30 to +30 minutes, whole numbers, for fajr, sunrise, dhuhr, asr, maghrib, ishaInvalidPrayerConfigException

Data coverage#

DataCoverage
Bank card BINs39 BINs. Others give null from getBankName()
Sheba bank codes38 codes. Others give null
National-code place of issue547 prefixes. Others give null
Official holiday datesJalali 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 methodsTehran, MWL, ISNA, Egypt, Makkah, Karachi. Asr factor 1 (standard) or 2 (Hanafi)
Prayer times at high latitudesThe 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.