PHPackages                             remls/hijri-date - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Localization &amp; i18n](/categories/localization)
4. /
5. remls/hijri-date

ActiveLibrary[Localization &amp; i18n](/categories/localization)

remls/hijri-date
================

Laravel helper package for Hijri dates.

v3.0.0(3w ago)1022.7k↓49.5%5MITPHPPHP &gt;=8.1

Since Apr 5Pushed 3w ago1 watchersCompare

[ Source](https://github.com/Remls/hijri-date)[ Packagist](https://packagist.org/packages/remls/hijri-date)[ RSS](/packages/remls-hijri-date/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (4)Versions (15)Used By (0)

HijriDate
=========

[](#hijridate)

Laravel helper package for Hijri dates. Supports displaying dates in Arabic, Bengali, Dhivehi, English, Indonesian, Malay and Urdu out of the box, with support for further customizations or adding a language of your choice.

A demo of some of the package's capabilities is available at .

[![Today's Hijri date, rendered live by the demo](https://camo.githubusercontent.com/de61d9cee71c645dbd61f740423554edb53ad6fc5155d5f256d9b2a393ccba55/68747470733a2f2f68696a72692e72656d6c732e696f2f6f672e706e67)](https://hijri.remls.io)

Warning

This package was built *primarily for use in Maldives*: the default language is Dhivehi, and the default calendar is a custom mapping of dates specifically for Maldives. [(Why?)](https://github.com/Remls/hijri-date/pull/7#issuecomment-3273063713)

However, this can all be customised for your specific needs; read further for how to do so.

- [Installation](#installation)
- [Creating dates](#creating-dates)
    - [Customizing how dates are converted between Hijri and Gregorian](#customizing-how-dates-are-converted-between-hijri-and-gregorian)
- [Available methods](#available-methods)
    - [Conversions](#conversions)
    - [Calculations](#calculations)
    - [Comparisons](#comparisons)
    - [Formatting](#formatting)
- [Casting](#casting)
- [Validation](#validation)
- [Localization](#localization)
    - [Adding a language](#adding-a-language)
- [Migrating from v2 to v3](#migrating-from-v2-to-v3)
- [Migrating from v1 to v2](#migrating-from-v1-to-v2)

Installation
------------

[](#installation)

```
composer require remls/hijri-date

```

To publish configuration files:

```
php artisan vendor:publish --provider="Remls\HijriDate\HijriDateServiceProvider" --tag="config"
```

Creating dates
--------------

[](#creating-dates)

All of the following methods return an instance of `Remls\HijriDate\HijriDate`.

```
use Carbon\Carbon;

new HijriDate();                    // 1st Muharram 1000
new HijriDate(1443, 9, 1);          // 1st Ramadan 1443
HijriDate::parse('1443-09-01');     // 1st Ramadan 1443

// From Gregorian
HijriDate::createFromGregorian();              // Today's date
today_hijri();                                 // Today's date
HijriDate::createFromGregorian('1991-12-01');  // 20th Jumada al-Ula 1412
$input = Carbon::parse('2002-03-04');
HijriDate::createFromGregorian($input);        // 12th Dhul-Hijja 1422
```

### Customizing how dates are converted between Hijri and Gregorian

[](#customizing-how-dates-are-converted-between-hijri-and-gregorian)

By default, the package uses [an external map](https://gist.github.com/Remls/b0ebba53bb2a8670f333f8a88de4aae3) between Hijri and Gregorian dates in Maldives to convert between the two. This map is cached and reused for subsequent conversions.

You may customize for how long the map is cached by changing `config/hijri.php` &gt; `conversion.cache_period`.

You may manually re-fetch data from the external source by running `php artisan hijri:fetch`.

The package also comes with an alternative class for converting dates using calculations instead of a map. You may enable it by changing `config/hijri.php` &gt; `conversion.converter` to `\Remls\HijriDate\Converters\MaldivesEstimateG2HConverter::class`.

You may customize how dates are converted by:

- providing your own map in `config/hijri.php` &gt; `conversion.data_url`
- providing your own custom converter class in `config/hijri.php` &gt; `conversion.converter`
    - The class must implement `\Remls\HijriDate\Converters\Contracts\GregorianToHijriConverter`.
- binding your own implementation of `GregorianToHijriConverter` in the service container
    - This takes precedence over `config/hijri.php` &gt; `conversion.converter`
    - Example:

```
// App/Providers/AppServiceProvider.php

use Remls\HijriDate\Converters\Contracts\GregorianToHijriConverter;

public function register(): void
{
    $this->app->singleton(GregorianToHijriConverter::class, fn () => new YourCustomConverter());
}
```

Available methods
-----------------

[](#available-methods)

### Conversions

[](#conversions)

```
// Gregorian to Hijri
HijriDate::createFromGregorian('1991-12-01'); // returns HijriDate

// Hijri to Gregorian
$date = new HijriDate(1443, 9, 1);
$date->getGregorianDate();                    // returns Carbon
```

By default, conversions are date-only: any time component on the input is ignored, and input `Carbon` instances are never modified. `getGregorianDate()` returns a copy of the original input (for dates created with `createFromGregorian()`), or a date at midnight in Maldives time (UTC+5), derived on first call.

You may customise how the conversion works, as detailed [here](#customizing-how-dates-are-converted-between-hijri-and-gregorian).

### Calculations

[](#calculations)

```
$date = new HijriDate(1443, 9, 1);   // 1st Ramadan 1443
$date->addDays(1);                   // 2nd Ramadan 1443
$date->subDays(3);                   // 28th Sha'ban 1443
$date2 = new HijriDate(1443, 8, 20); // 20th Sha'ban 1443
$date->diffInDays($date2);           // 8
```

### Comparisons

[](#comparisons)

You may compare two HijriDate objects `$a` and `$b` using the following methods:

MethodDescription`$a->compareWith($b)`Returns -1 if $a &lt; $b.
Returns 0 if $a == $b.
Returns 1 if $a &gt; $b.`$a->equalTo($b)`Returns true if $a == $b.`$a->greaterThan($b)`Returns true if $a &gt; $b (a is after b).`$a->lessThan($b)`Returns true if $a &lt; $b (a is before b).`$a->greaterThanOrEqualTo($b)`Returns true if $a &gt;= $b (a is after or equal to b).`$a->lessThanOrEqualTo($b)`Returns true if $a &lt;= $b (a is before or equal to b).### Formatting

[](#formatting)

Each HijriDate object will have a set locale when it is created. This locale will be used for formatting.

The locale is `'dv'` by default, but you may customize it by:

- passing locale in constructor (eg: `new HijriDate(1443, 9, 1, 'en')`)
- changing locale after creation (eg: `$date->setLocale('en')`)
- changing `default_locale` in configuration, so all HijriDate objects are created using that default locale

The following options are supported with `$date->format()`:

OptionDescriptionExampledDay of month (with leading zero)01 ... 30DWeekday (short)Sun ... SatjDay of month (without leading zero)1 ... 30l
(lowercase L)WeekdaySunday ... SaturdayFMonthMuharram ... Dhul-HijjamMonth (number, with leading zero)01 ... 12MMonth (short)Mhr ... DhHnMonth (number, without leading zero)1 ... 12YYear1000 ... 1999yYear (final two digits)00 ... 99```
$date = new HijriDate(1443, 9, 1);  // 1st Ramadan 1443
$date->format("F");                 // "ރަމަޟާން" (using default locale 'dv')

$date->setLocale('ar');
$date->format("F Y");               // "رمضان 1443"
// Use numerals from locale
$date->format("F Y", true);         // "رمضان ١٤٤٣"
```

Casting
-------

[](#casting)

The field to be cast must be a string field on database.

```
// App/Models/YourModel.php

class YourModel
{
    ...

    protected $casts = [
        ...
        'your_hijri_date_field' => HijriDate::class,
    ];
}
```

This will automatically store data as `Y-m-d` string in database, and cast to `Remls\HijriDate\HijriDate` when accessing.

Validation
----------

[](#validation)

Any string that passes the following conditions is considered a valid Hijri date:

- in the format `Y-m-d`
- year between 1000 and 1999 (This can be changed in config.)
- month between 1 and 12
- day between 1 and 30

```
use Remls\HijriDate\Rules\ValidHijriDate;

...
request()->validate([
    'your_hijri_date_field' => ['required', new ValidHijriDate],
]);
```

Note that validation error messages will use app's locale (unlike formatting).

Localization
------------

[](#localization)

Publish translation files by using:

```
php artisan vendor:publish --provider="Remls\HijriDate\HijriDateServiceProvider" --tag="lang"
```

You may then customize strings as needed.

### Adding a language

[](#adding-a-language)

To add support for another language:

1. Publish the configuration file. The file will be copied to `config/hijri.php`.
2. Publish the translation files. The files will be copied to `lang/vendor/hijri`.
3. Copy one of the existing translation folders, and rename it with the language code of your choice. Eg: `lang/vendor/hijri/es`
4. Change strings to their respective translations.
5. Add the language code to `supported_locales` in `config/hijri.php`.
6. (Optional) Change `default_locale` in `config/hijri.php` to the new language code.

Migrating from v2 to v3
-----------------------

[](#migrating-from-v2-to-v3)

This version mainly addresses stale code and bug fixes, with little to no change in functionality for the vast majority of cases.

Minimum supported Laravel version has been bumped from v8 to v10.

⚠️ denotes new behaviour that could potentially be a breaking change.

### Improvements

[](#improvements)

- `ValidHijriDate` now implements `Illuminate\Contracts\Validation\ValidationRule` instead of the deprecated `Rule`.
    - Normal usage (`new ValidHijriDate` in a rules array) is unaffected.
    - ⚠️ If you called `passes()` or `message()` on the rule directly, or extended the class, update to the new `validate()` method.
- The map is now fetched with Laravel's HTTP client, with timeouts and a retry.
    - ⚠️ Network failures throw `Illuminate\Http\Client\ConnectionException` or `RequestException` instead of `RuntimeException`. Invalid map data still throws `RuntimeException`.
    - `allow_url_fopen` is no longer required.
    - Fetched data is validated before use, and the last successfully fetched map is kept indefinitely and served as a fallback if a refetch fails.
- The converter is resolved from the service container as a singleton, instead of being constructed for every conversion.
    - You can now register your conversion class in `AppServiceProvider` instead of changing `conversion.converter` in config.
    - ⚠️ Changing `conversion.converter` in config at runtime after the first conversion now has no effect.

### Bug fixes

[](#bug-fixes)

- `conversion.cache_period` is now set to 6 hours by default. If you have published `config/hijri.php`, update `conversion.cache_period` to `60 * 60 * 6` (optional, leaving as the previous default just means the cache expires more quickly).
- ⚠️ `Carbon` instances passed into the package are never modified anymore.
    - Previously, an instance passed to `createFromGregorian()` was silently mutated by the default converter class. It now stays exactly as you created it, and `getGregorianDate()` returns a copy of it as provided.
- Negative amounts passed to `addDays()` / `subDays()` now stay on the calculation path selected by `$useGregorian`. Previously they always used the Gregorian path.
- ⚠️ Out-of-range results from `addDays()` / `subDays()` with `$useGregorian = false` now throw `InvalidArgumentException`, consistent with the rest of the package, instead of `OutOfRangeException`.
- `isParsable()` now checks the year against the configured range, so it no longer returns `true` for strings that `parse()` would then reject.

Migrating from v1 to v2
-----------------------

[](#migrating-from-v1-to-v2)

The package no longer uses estimates when converting from Hijri to Gregorian by default.

- New keys have been added to `config/hijri.php`. You may need to update your configuration file.
- The function `getEstimateFromGregorian` has been **REMOVED** in favour of `createFromGregorian`.
    - To maintain the same behaviour as before:
        1. Change `config/hijri.php` &gt; `conversion.converter` to `\Remls\HijriDate\Converters\MaldivesEstimateG2HConverter::class`.
        2. Change all calls from `getEstimateFromGregorian` to `createFromGregorian`.
- The function `isEstimate` has been **REMOVED**. There is no more need to check if the date was made from an estimate, as you can now always just get the corresponding Gregorian date with a call to `getGregorianDate`, regardless of how it was created.
- The function `getEstimatedFrom` has been **REMOVED** in favour of `getGregorianDate`.
- The function `resetEstimation` has been **REMOVED** in favour of `resetGregorianDate`.
- The functions `addDays` and `subDays` will now use the underlying Gregorian date by default for calculations.
    - To maintain the same behaviour as before, pass `false` to `$useGregorian` parameter of these functions.

###  Health Score

56

—

FairBetter than 97% of packages

Maintenance94

Actively maintained with recent releases

Popularity36

Limited adoption so far

Community15

Small or concentrated contributor base

Maturity66

Established project with proven stability

 Bus Factor1

Top contributor holds 72.1% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~120 days

Recently: every ~199 days

Total

14

Last Release

27d ago

Major Versions

v1.5.0 → v2.0.02023-04-26

v2.4.0 → v3.0.02026-07-22

PHP version history (3 changes)v1.2.0PHP ^8.0

v2.3.0PHP &gt;=8.0

v3.0.0PHP &gt;=8.1

### Community

Maintainers

![](https://www.gravatar.com/avatar/25be312107995406bdba6fc1df1e99502e3a29726b69feb6c655e89b632fdb4d?d=identicon)[Remls](/maintainers/Remls)

---

Top Contributors

[![Remls](https://avatars.githubusercontent.com/u/43497786?v=4)](https://github.com/Remls "Remls (49 commits)")[![Remls7](https://avatars.githubusercontent.com/u/86112728?v=4)](https://github.com/Remls7 "Remls7 (15 commits)")[![HajMo](https://avatars.githubusercontent.com/u/50548630?v=4)](https://github.com/HajMo "HajMo (2 commits)")[![AnowarDotDev](https://avatars.githubusercontent.com/u/85840896?v=4)](https://github.com/AnowarDotDev "AnowarDotDev (1 commits)")[![MdAnowarHosen](https://avatars.githubusercontent.com/u/85840896?v=4)](https://github.com/MdAnowarHosen "MdAnowarHosen (1 commits)")

---

Tags

datehijri-datesi18nlanguagelaravellocalizationphptranslation

### Embed Badge

![Health badge](/badges/remls-hijri-date/health.svg)

```
[![Health](https://phpackages.com/badges/remls-hijri-date/health.svg)](https://phpackages.com/packages/remls-hijri-date)
```

###  Alternatives

[backpack/crud

Quickly build admin interfaces using Laravel, Bootstrap and JavaScript.

3.4k3.8M228](/packages/backpack-crud)[statamic/cms

The Statamic CMS Core Package

4.9k3.8M1.2k](/packages/statamic-cms)[unopim/unopim

UnoPim Laravel PIM

10.8k2.5k](/packages/unopim-unopim)[leantime/leantime

Open source project management system for non-project managers. Simple like Trello, powerful like Jira. Built with neurodiversity in mind.

11.3k4.0k](/packages/leantime-leantime)[eslazarev/wildberries-sdk

Wildberries OpenAPI clients (generated).

353.6k](/packages/eslazarev-wildberries-sdk)[scriptdevelop/whatsapp-manager

Paquete para manejo de WhatsApp Business API en Laravel

793.9k](/packages/scriptdevelop-whatsapp-manager)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
