ariaieboy/filament-jalali-datetimepicker
Filament Jalali DateTime Picker adds Persian (Jalali) date and time picker fields to Filament forms, helping Laravel apps accept and display Shamsi dates with configurable formats and seamless Filament resource integration.
Before anything else: this package is archived (last release 2024-09-29). Treat it as a vendored dependency you own, not a maintained one. Pin an exact version in composer.json and budget for a fork if Filament bumps its JS/picker internals.
Install and register:
composer require ariaieboy/filament-jalali-datetimepicker
php artisan filament:assets
php artisan view:clear
Requires Filament 3.x on PHP 8.1+. There is no service provider to register manually — the component is autoloaded.
Look first at src/Forms/Components/ in the repo. You'll see a class extending Filament's DateTimePicker, which is why it works as a drop-in. That inheritance is the whole design: any fluent method on Filament\Forms\Components\DateTimePicker is available, and the package only swaps the front-end picker and formats the display.
First use case — replace an existing field:
use Ariaieboy\FilamentJalaliDatetimepicker\Forms\Components\JalaliDateTimePicker;
JalaliDateTimePicker::make('published_at')
->label('تاریخ انتشار')
->required();
That's it. The database column still stores a Gregorian timestamp; only the rendered input is Jalali.
Timezone-explicit fields. Set both the storage format and the display timezone so conversion is unambiguous:
JalaliDateTimePicker::make('published_at')
->format('Y-m-d H:i:s')
->displayFormat('Y/m/d H:i')
->timezone('Asia/Tehran')
->seconds(false);
Table columns are not included. The package ships a form component. For tables, use Filament's TextColumn with a Jalali formatter from morilog/jalali (or whichever conversion lib the package pulls in — check composer.json and reuse it rather than adding a second one):
TextColumn::make('published_at')
->label('تاریخ')
->formatStateUsing(fn ($state) => $state
? \Morilog\Jalali\Jalalian::fromCarbon($state)->format('Y/m/d')
: '—');
Filter integration. Filament's Filter with a date range works, but the picker inside won't be Jalali unless you build a custom filter form. A pragmatic pattern is a custom filter class that returns JalaliDateTimePicker fields and manually applies whereBetween on the Gregorian column.
Shared form schema. Because it's a drop-in, you can define one canonical PostForm::schema() and reuse it from both the resource and a front-end Livewire form. No Jalali-specific adaptation needed on the PHP side.
Reactive/conditional fields. ->reactive(), ->afterStateUpdated(), ->hidden(), ->disabled() all behave as usual. State in Livewire is a Gregorian string — this is what makes ->rules('after:now') and similar validations keep working.
Migrating an existing resource. Do a global find-and-replace of DateTimePicker::make → JalaliDateTimePicker::make for user-facing fields, but leave fields that are set programmatically or hidden from users on the stock component to reduce surface area.
Archived status is the biggest risk. No security fixes, no compatibility patches. If you're on Filament 3.2+ and the JS picker's DOM contract changes, the component can silently break — the PHP side will still render, you'll just get a plain or non-functional input. Add a smoke test that visits a form page and asserts the picker element exists.
Asset caching bites hardest. After composer update or a deploy, run php artisan filament:assets and clear view:clear + config:clear. If styles look half-applied, it's almost always stale published assets in public/vendor.
Do not change ->format() to Jalali. The value written to the database must stay Gregorian, or every whereBetween, orderBy, and Carbon cast in your app breaks. ->displayFormat() controls what users see; ->format() controls storage.
Timezone drift. If your app timezone is UTC and users are in Tehran, a stored 2024-03-20 20:30:00 displays as 1403/01/01 00:00 in Jalali +03:30. Explicitly set ->timezone() on every instance rather than relying on config defaults, and verify with a test asserting the persisted value.
JS library duplication. The package bundles its own picker JS. If you also load a Persian datepicker for other parts of the app, you can get two flatpickr/picker instances fighting over document event listeners. Consolidate on one library.
Testing. Assertions should target the Gregorian value in the database, not the displayed string. Use ->fillForm(['published_at' => '2024-03-20 12:00:00']) — the component accepts Gregorian programmatically. Driving the Jalali UI via browser tests is brittle because of the archived JS.
Extending it. The cleanest extension point is subclassing the component and overriding getView() or the asset registration, so if the package dies you can lift the class into your app/ namespace with minimal changes.
How can I help you explore Laravel packages today?