定制 hpakdaman/multicarbon 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

hpakdaman/multicarbon

Composer 安装命令:

composer require hpakdaman/multicarbon

包简介

Multi-calendar extension for Carbon — Jalali (Solar Hijri), Hijri (Islamic Lunar), and Gregorian support.

README 文档

README

A multi-calendar extension for Carbon — seamlessly work with Jalali (Solar Hijri), Hijri (Islamic Lunar), and Gregorian calendars using the same familiar Carbon API.

License: MIT PHP Version

Part of UnfoldCMS — the open, self-hosted CMS for developers. MultiCarbon powers the multi-calendar date handling behind UnfoldCMS.

Why MultiCarbon?

Carbon is the gold standard for date/time in PHP. But if you work with Persian (Jalali) or Islamic (Hijri) calendars, you've had to choose between limited wrappers or entirely separate libraries that throw away everything Carbon gives you.

MultiCarbon is Carbon. It extends Carbon\Carbon directly, which means every single Carbon feature — timezone handling, diffing, serialization, immutability, macros, Laravel integration — works exactly as you expect. You don't lose anything. You just gain Jalali and Hijri support on top.

Every method you already know (format(), addMonths(), diffForHumans(), startOfMonth(), addDays(), isPast(), ...) works natively in your calendar of choice. Switch between calendars on the same instance, and the underlying timestamp never changes.

// Create a date in Jalali calendar — the most natural way
$carbon = MultiCarbon::createJalali(1404, 1, 1); // Nowruz 1404

echo $carbon->format('Y/m/d');                   // "1404/01/01"
echo $carbon->format('l j F Y');                  // "جمعه 1 فروردین 1404"

// Switch between calendars on the same instance
echo $carbon->hijri()->format('Y/m/d');          // "1446/08/21"
echo $carbon->gregorian()->format('Y/m/d');      // "2025/03/21"

// Or start from a Gregorian string — works seamlessly
echo (new MultiCarbon('2025-03-21'))->jalali()->format('Y/m/d'); // "1404/01/01"

It's Just Carbon

Because MultiCarbon extends Carbon, every Carbon method works out of the box — even in Jalali or Hijri mode:

$date = MultiCarbon::createJalali(1404, 6, 15, 14, 30, 0);

// All of Carbon's methods work — you lose nothing
$date->addDays(10);                    // add 10 days (Carbon native)
$date->addMonths(2);                   // add 2 Jalali months (calendar-aware)
$date->isPast();                       // true/false
$date->isWeekend();                    // Friday detection (Iranian week)
$date->diffForHumans();                // "۳ ماه پیش" (localized Persian)
$date->getTimestamp();                 // Unix timestamp — always correct
$date->timezone('Asia/Tehran');        // Carbon timezone support
$date->toIso8601String();             // ISO output via Carbon
$date->copy()->startOfMonth();        // 1404/08/01 00:00:00

// Switch to Gregorian anytime — full Carbon, no restrictions
$date->gregorian()->format('Y-m-d');  // "2025-11-05"

// Pass it anywhere that expects Carbon — it just works
function logDate(Carbon\Carbon $date) { /* ... */ }
logDate($date); // MultiCarbon IS Carbon

Features

  • Full Carbon compatibility — extends Carbon\Carbon, so every Carbon method works out of the box
  • Three calendar systems — Jalali (Solar Hijri), Hijri Qamari (Islamic Lunar), and Gregorian
  • Fluent calendar switching->jalali(), ->hijri(), ->gregorian() on any instance
  • Calendar-aware arithmeticaddMonths(), addYears(), startOfMonth(), endOfYear() respect calendar boundaries
  • Localized output — Persian and Arabic month names, weekday names, AM/PM, and "diff for humans"
  • Digit display — Latin, Farsi (۱۲۳۴), or Arabic-Indic (١٢٣٤) digits globally
  • Iranian week — Saturday as first day, Friday as weekend
  • Laravel integration — auto-discovery, Facade, Blade directives (@jalali, @hijri, @jdate, @hdate)
  • Global helpersjdate(), hdate(), multicarbon() available everywhere
  • Zero dependencies beyond Carbon itself

Installation

composer require hpakdaman/multicarbon

Requirements: PHP 8.1+ and Carbon 2.x or 3.x.

Laravel

The package auto-discovers its ServiceProvider and Facade. No manual registration needed.

Quick Start

Create Dates

use MultiCarbon\MultiCarbon;

// From now
$date = new MultiCarbon();

// From a Gregorian string (defaults to Jalali mode)
$date = new MultiCarbon('2025-03-21');
echo $date->year;   // 1404
echo $date->month;  // 1
echo $date->day;    // 1

// Create directly in Jalali
$date = MultiCarbon::createJalali(1404, 1, 1, 12, 0, 0);

// Create directly in Hijri
$date = MultiCarbon::createHijri(1446, 9, 1);

Switch Calendars

$date = new MultiCarbon('2025-03-21');

// Fluent switching — same underlying moment, different calendar view
echo $date->jalali()->format('Y/m/d');     // "1404/01/01"
echo $date->hijri()->format('Y/m/d');      // "1446/08/21"
echo $date->gregorian()->format('Y/m/d');  // "2025/03/21"

// The timestamp never changes
echo $date->jalali()->timestamp === $date->gregorian()->timestamp;  // true

Format Dates

All of PHP's date format characters are supported:

$date = MultiCarbon::createJalali(1404, 1, 15, 14, 30, 0);

$date->format('Y-m-d H:i:s');  // "1404-01-15 14:30:00"
$date->format('l j F Y');      // "شنبه 15 فروردین 1404"
$date->format('D, M j, Y');    // "ش, فرو 15, 1404"

// Hijri formatting
$hijri = MultiCarbon::createHijri(1446, 9, 1);
$hijri->format('F Y');          // "رمضان 1446"

Date Arithmetic

Month and year arithmetic respects calendar boundaries:

$date = MultiCarbon::createJalali(1404, 6, 31);  // Shahrivar 31

$date->addMonth();
echo $date->format('Y/m/d');  // "1404/07/30" — clamped to Mehr's max (30 days)

$date = MultiCarbon::createJalali(1403, 12, 30);  // Esfand 30 (leap year)
$date->addYear();
echo $date->format('Y/m/d');  // "1404/12/29" — clamped (1404 is not leap)

Boundary Methods

$date = MultiCarbon::createJalali(1404, 6, 15, 14, 30, 0);

$date->startOfMonth();  // 1404/06/01 00:00:00
$date->endOfMonth();    // 1404/06/31 23:59:59
$date->startOfYear();   // 1404/01/01 00:00:00
$date->endOfYear();     // 1404/12/29 23:59:59

$date->startOfWeek();   // Previous Saturday 00:00:00
$date->endOfWeek();     // Next Friday 23:59:59

Comparison

$a = MultiCarbon::createJalali(1404, 1, 1);
$b = MultiCarbon::createJalali(1404, 1, 25);

$a->isSameMonth($b);   // true
$a->isSameDay($b);     // false
$a->lessThan($b);      // true
$a->diffInDays($b);    // 24

Diff for Humans

Localized in Persian and Arabic:

// Persian
$date = MultiCarbon::createJalali(1403, 1, 1);
echo $date->diffForHumans();  // "1 سال پیش"

// Arabic
$date = MultiCarbon::createHijri(1445, 1, 1);
echo $date->diffForHumans();  // "منذ 1 سنة"

Digit Display

MultiCarbon::setDigitsType(MultiCarbon::DIGITS_FARSI);
echo MultiCarbon::createJalali(1404, 1, 1)->format('Y/m/d');
// "۱۴۰۴/۰۱/۰۱"

MultiCarbon::setDigitsType(MultiCarbon::DIGITS_ARABIC);
echo MultiCarbon::createHijri(1446, 9, 1)->format('Y/m/d');
// "١٤٤٦/٠٩/٠١"

MultiCarbon::setDigitsType(MultiCarbon::DIGITS_LATIN);  // default

Conversion & Interop

use Carbon\Carbon;
use MultiCarbon\MultiCarbon;

// From Carbon
$carbon = Carbon::parse('2025-03-21');
$mc = MultiCarbon::fromCarbon($carbon);  // Jalali mode by default

// From DateTime
$dt = new \DateTime('2025-03-21');
$mc = MultiCarbon::fromDateTime($dt);

// Back to Carbon
$carbon = $mc->toCarbon();

// Parse a calendar-specific string
$mc = MultiCarbon::parseFormat('Y/m/d', '1404/01/15');  // Jalali
$mc = MultiCarbon::parseFormat('Y/m/d', '1446/07/15', CalendarMode::HIJRI);

// To array
$mc->toArray();
// ['year' => 1404, 'month' => 1, 'day' => 15, 'hour' => 0, 'minute' => 0, 'second' => 0]

Global Helpers

// Jalali
jdate();                  // MultiCarbon instance in Jalali mode
jdate('Y/m/d');           // "1404/01/15"
jdate('Y/m/d', $timestamp);

// Hijri
hdate();                  // MultiCarbon instance in Hijri mode
hdate('Y/m/d');           // "1446/08/15"

// General
multicarbon();            // MultiCarbon instance

Laravel Blade Directives

{{-- Current Jalali date --}}
@jdate('Y/m/d H:i:s')

{{-- Current Hijri date --}}
@hdate('Y/m/d')

{{-- Convert a variable --}}
@jalali($user->created_at, 'Y/m/d')
@hijri($post->published_at, 'Y/m/d')

API Reference

Calendar Mode

Method Description
->jalali() Switch to Jalali (Solar Hijri) mode
->hijri() Switch to Hijri (Islamic Lunar) mode
->gregorian() Switch to Gregorian mode
->isJalali() Check if in Jalali mode
->isHijri() Check if in Hijri mode
->isGregorian() Check if in Gregorian mode
->getCalendar() Get current calendar mode string

Factory Methods

Method Description
MultiCarbon::createJalali($y, $m, $d, $h, $min, $s, $tz) Create from Jalali components
MultiCarbon::createHijri($y, $m, $d, $h, $min, $s, $tz) Create from Hijri components
MultiCarbon::fromCarbon($carbon, $calendar) Create from a Carbon instance
MultiCarbon::fromDateTime($dateTime, $calendar) Create from a DateTime instance
MultiCarbon::parseFormat($format, $date, $calendar, $tz) Parse a calendar-specific date string

Getters

Property / Method Description
->year, ->getYear() Year in active calendar
->month, ->getMonth() Month in active calendar
->day, ->getDay() Day in active calendar
->monthName, ->getMonthName() Localized month name
->dayName Localized weekday name
->dayOfWeek, ->getDayOfWeek() Day of week (Saturday=0)
->dayOfYear, ->getDayOfYear() Day of year (1-indexed)
->daysInMonth, ->getMonthDays() Days in current month
->quarter Quarter (1-4)
->isLeapYear() Is the current year a leap year?

Arithmetic

Method Description
->addMonths($n) / ->subMonths($n) Add/subtract months (calendar-aware)
->addYears($n) / ->subYears($n) Add/subtract years (calendar-aware)
->addDays($n) / ->subDays($n) Add/subtract days (inherited from Carbon)
->addWeekdays($n) / ->subWeekdays($n) Add/subtract weekdays (skips weekends)

Boundaries

Method Description
->startOfMonth() / ->endOfMonth() Calendar-aware month boundaries
->startOfYear() / ->endOfYear() Calendar-aware year boundaries
->startOfWeek() / ->endOfWeek() Week boundaries (Saturday-Friday)

How It Works

MultiCarbon extends Carbon and intercepts property access (year, month, day) and key methods (format(), setDate(), addMonths(), etc.). It uses debug_backtrace() to detect whether a method was called by user code or by Carbon's internal engine:

  • User code calls $date->year → returns the value in the active calendar (Jalali/Hijri)
  • Carbon internally calls $this->year → returns Gregorian so parent logic works correctly

This means all of Carbon's existing methods (diffing, timezone handling, serialization) continue to work without modification. The conversion only happens at the boundary between your code and Carbon.

Testing

composer install
./vendor/bin/phpunit

Part of UnfoldCMS

MultiCarbon is built and maintained as part of UnfoldCMS — an open, self-hosted CMS for developers and teams. UnfoldCMS uses MultiCarbon for all of its Jalali, Hijri, and Gregorian date handling.

If you find MultiCarbon useful, check out the full CMS at unfoldcms.com.

License

MIT License. See LICENSE for details.

hpakdaman/multicarbon 适用场景与选型建议

hpakdaman/multicarbon 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 58 次下载、GitHub Stars 达 4, 最近一次更新时间为 2026 年 02 月 14 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「php」 「calendar」 「laravel」 「persian」 「Jalali」 「carbon」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 hpakdaman/multicarbon 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 hpakdaman/multicarbon 我们能提供哪些服务?
定制开发 / 二次开发

基于 hpakdaman/multicarbon 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 58
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 4
  • 点击次数: 44
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 4
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-02-14