All guides
No guide matches your search.
Carbon macros
Optional Carbon support. Turn any Carbon instance into a Jalali, Hijri or Hebrew date, and create Carbon dates from calendar parts. The page lists every macro with its return type and errors.
On this page
What this gives you
If nesbot/carbon is installed, RTLY-Kit adds a few macros to Carbon\Carbon and Carbon\CarbonImmutable. They move you between Carbon and the calendar classes in one call, in both directions. Carbon is optional. Without it nothing is registered and nothing breaks. Laravel apps already ship Carbon, so the macros are there without any extra step (see Laravel setup).
Before you start. Install RTLY-Kit (Installation) and Carbon 3 (composer require nesbot/carbon).
How registration works
Composer loads the package's helper file on autoload. That file starts the integration. It checks whether the Carbon classes exist and, if they do, registers the macros once. You call nothing yourself:
<?php
require 'vendor/autoload.php';
use Carbon\Carbon;
use Carbon\CarbonImmutable;
use RtlyKit\Calendar\HijriVariant;
use RtlyKit\Calendar\Jalali;
var_dump(Carbon::hasMacro('toJalali')); // bool(true)Install Carbon with Composer. The macros are registered when Composer's autoloader starts and can find the Carbon classes. A Carbon copy that is not on the same autoloader, such as a bundled phar, is not found. The registration classes are internal. The macro names are part of the public API.
Macro reference
| Macro | Kind | Returns | Notes |
|---|---|---|---|
toJalali() | instance | Jalali | Same moment and time zone as the Carbon object |
jformat($format = 'Y/m/d H:i:s') | instance | string | Shortcut for toJalali()->format($format). Tokens as in Jalali formatting |
toHijri(?HijriVariant $variant = null) | instance | Hijri | Umm al-Qura unless you give a variant |
toHebrew() | instance | Hebrew | |
createFromJalali($y, $m, $d, $h = 0, $i = 0, $s = 0, $tz = null) | static | the class you called it on | Carbon:: returns Carbon. CarbonImmutable:: returns CarbonImmutable |
createFromHijri($y, $m, $d, $h = 0, $i = 0, $s = 0, $tz = null, ?HijriVariant $variant = null) | static | the class you called it on | The variant defaults to Umm al-Qura |
createFromHebrew($y, $m, $d, $h = 0, $i = 0, $s = 0, $tz = null) | static | the class you called it on | Month numbers by position, see Hebrew months |
The $tz argument takes a DateTimeZone, a time zone name or null. With null the PHP default zone applies, not the zone of any existing Carbon object.
From Carbon to a calendar
$c = Carbon::create(2026, 3, 21, 12, 0, 0, 'UTC');
echo $c->toJalali(); // 1405/01/01 12:00:00
echo get_class($c->toJalali()); // RtlyKit\Calendar\Jalali
echo $c->jformat('l j F Y'); // شنبه 1 فروردین 1405
echo $c->jformat(); // 1405/01/01 12:00:00
echo $c->toHijri()->format('j F Y', 'en'); // 2 Shawwal 1447
echo $c->toHebrew()->format('j F Y'); // 3 Nisan 5786The result is a calendar object, not a Carbon object. Use the calendar API from there, for example Persian digits with $c->toJalali()->format('Y/m/d', true). You can keep working with it and go back at any time with toGregorian():
echo Carbon::now('UTC')->setDate(2026, 3, 21)->toJalali()->addMonths(1)->format('Y/m/d'); // 1405/02/01Calling the calendar's make() with a Carbon instance does the same, because Carbon is a DateTimeInterface:
echo Jalali::make($c)->format('Y/m/d H:i'); // 1405/01/01 12:00
echo Jalali::make(Carbon::create(2026, 3, 21, 22, 0, 0, 'UTC'), new DateTimeZone('Asia/Tehran'))->format('Y/m/d H:i'); // 1405/01/02 01:30From calendar parts to Carbon
$a = Carbon::createFromJalali(1405, 1, 1, 0, 0, 0, 'UTC');
echo get_class($a), ' ', $a->toDateTimeString(); // Carbon\Carbon 2026-03-21 00:00:00
$b = CarbonImmutable::createFromJalali(1405, 1, 1, 8, 30, 0, 'Asia/Tehran');
echo get_class($b), ' ', $b->toIso8601String(); // Carbon\CarbonImmutable 2026-03-21T08:30:00+03:30
echo Carbon::createFromHijri(1446, 9, 1, 0, 0, 0, 'UTC')->toDateString(); // 2025-03-01
echo Carbon::createFromHebrew(5786, 1, 1, 0, 0, 0, 'UTC')->toDateString(); // 2025-09-23To use the Tabular Hijri variant, pass it as the last argument: Carbon::createFromHijri(1446, 10, 1, 0, 0, 0, 'UTC', HijriVariant::Tabular).
Errors
The macros check input through the calendar classes. Invalid or out-of-range input throws RtlyKit\Exceptions\InvalidDateException, not a Carbon InvalidFormatException. An unknown time zone name does the same:
use RtlyKit\Exceptions\RtlyKitThrowable;
$cases = [
fn () => Carbon::createFromJalali(1404, 12, 30),
fn () => Carbon::createFromJalali(1404, 1, 1, 0, 0, 0, 'Nowhere/Land'),
fn () => Carbon::createFromHijri(9999, 1, 1),
fn () => Carbon::createFromHebrew(1, 1, 1),
];
foreach ($cases as $f) {
try { $f(); }
catch (RtlyKitThrowable $e) { echo get_class($e), ': ', $e->getMessage(), "\n"; }
}
// RtlyKit\Exceptions\InvalidDateException: Invalid Jalali date: 1404/12/30
// RtlyKit\Exceptions\InvalidDateException: Unknown timezone: Nowhere/Land
// RtlyKit\Exceptions\InvalidDateException: Invalid Hijri date: 9999/1/1
// RtlyKit\Exceptions\InvalidDateException: Invalid Hebrew date: 1/1/1The supported ranges are those of the calendars: Jalali -620..9377, Hijri 1..9665, Hebrew 3762..13759.
Good to know
Good to know. The macros have the same accuracy as the calendar classes. Jalali matches the official calendar for the years 1206 to 1497. Hijri Umm al-Qura month starts match the official KACST calendar for AH 1318 to 1500 (checked 2026-10-08). Day boundaries are at civil midnight.
- Macros are global per class. If another package defines a macro with the same name (
toJalali,toHijriand so on), the one registered last wins. Call the calendar classes directly (Jalali::make($carbon)) when you need to be sure. - Time zones travel with the object.
toJalali()uses the zone of the Carbon object, so set the zone before converting when the calendar day matters. - Weekday numbers differ between calendars. Do not feed
getDayOfWeek()of one calendar into another. See Convert and compare dates .
Was this page helpful?