Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Jalali Date Time Laravel Package

borsaco/jalali-date-time

Convert dates between Gregorian and Jalali (Shamsi/Hijri Shamsi) calendars in PHP. Simple standalone class or Composer package, with support for dates beyond the 2038 limit.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require borsaco/jalali-date-time
    

    Or manually include jdatetime.class.php in your project.

  2. Basic Usage:

    require_once 'vendor/borsaco/jalali-date-time/jdatetime.class.php';
    $jalaliDate = new JalaliDateTime('2023-10-25'); // Gregorian input
    echo $jalaliDate->format('Y-m-d'); // Outputs Jalali date (e.g., 1402-08-03)
    
  3. First Use Case: Convert a Gregorian Carbon instance to Jalali:

    use Carbon\Carbon;
    $gregorianDate = Carbon::now();
    $jalaliDate = new JalaliDateTime($gregorianDate->toDateString());
    echo $jalaliDate->format('Y/m/d H:i:s'); // Jalali formatted output
    

Implementation Patterns

Core Workflows

  1. Date Conversion:

    • Gregorian → Jalali:
      $jalali = new JalaliDateTime('2023-10-25');
      echo $jalali->format('Y/m/d'); // 1402/08/03
      
    • Jalali → Gregorian:
      $gregorian = new JalaliDateTime('1402-08-03', true); // Second param: $jalaliInput
      echo $gregorian->format('Y-m-d'); // 2023-10-25
      
  2. Integration with Laravel:

    • Accessors/Mutators (for Eloquent models):
      use borsaco\JalaliDateTime\JalaliDateTime;
      
      class Post extends Model {
          protected $dates = ['published_at'];
      
          public function getPublishedAtAttribute($value) {
            return JalaliDateTime::createFromFormat('Y-m-d', $value)->format('Y/m/d');
          }
      
          public function setPublishedAtAttribute($value) {
            $this->attributes['published_at'] = JalaliDateTime::createFromFormat('Y/m/d', $value)->format('Y-m-d');
          }
      }
      
  3. Timezone Handling:

    • Use DateTime methods for timezone-aware operations:
      $jalaliDate = new JalaliDateTime('2023-10-25 14:30:00');
      $jalaliDate->setTimezone(new DateTimeZone('Asia/Tehran'));
      echo $jalaliDate->format('Y/m/d H:i:s');
      
  4. Validation:

    • Validate Jalali dates in Laravel:
      use Illuminate\Support\Facades\Validator;
      
      $validator = Validator::make(['date' => '1402/08/03'], [
          'date' => 'required|date_format:Y/m/d|after_or_equal:1300/01/01',
      ]);
      
  5. Carbon Compatibility:

    • Convert Carbon instances bidirectionally:
      $carbon = Carbon::parse('2023-10-25');
      $jalali = new JalaliDateTime($carbon->toDateString());
      $carbonFromJalali = Carbon::parse($jalali->format('Y-m-d'));
      

Integration Tips

  • Middleware for Jalali Dates: Parse/format Jalali dates globally in requests/responses:

    namespace App\Http\Middleware;
    
    use Closure;
    use borsaco\JalaliDateTime\JalaliDateTime;
    
    class ConvertJalaliDates {
        public function handle($request, Closure $next) {
            $request->merge([
                'jalali_date' => JalaliDateTime::createFromFormat('Y/m/d', $request->date)->format('Y-m-d')
            ]);
            return $next($request);
        }
    }
    
  • API Responses: Use Laravel’s Response macros to auto-format dates:

    Response::macro('jalali', function ($data, $status = 200, array $headers = [], $options = 0) {
        return $this->json($this->convertDatesToJalali($data), $status, $headers, $options);
    });
    
    protected function convertDatesToJalali($data) {
        if (is_array($data)) {
            return array_map([$this, 'convertDatesToJalali'], $data);
        } elseif ($data instanceof \DateTime) {
            return (new JalaliDateTime($data))->format('Y/m/d H:i:s');
        }
        return $data;
    }
    

Gotchas and Tips

Pitfalls

  1. Year 2038 Limitation:

    • While the package claims to support years beyond 2038, test thoroughly for edge cases (e.g., 14000-01-01). The underlying logic may still fail for extreme values.
  2. Time Handling:

    • The package ignores time if not explicitly provided. Always include H:i:s for time-aware operations:
      // ❌ Silent failure (time defaults to 00:00:00)
      $jalaliDate = new JalaliDateTime('2023-10-25');
      
      // ✅ Explicit time
      $jalaliDate = new JalaliDateTime('2023-10-25 14:30:00');
      
  3. Leap Year Bugs:

    • Jalali leap years (e.g., 1404-03-31) may cause off-by-one errors. Validate with:
      $jalaliDate = new JalaliDateTime('1404-03-31');
      if (!$jalaliDate->isValid()) {
          // Handle invalid date (e.g., throw exception or adjust)
      }
      
  4. Locale Conflicts:

    • Avoid mixing with setlocale() or IntlDateFormatter unless you reset the locale afterward:
      setlocale(LC_TIME, 'fa_IR'); // May interfere with JalaliDateTime
      // ... operations ...
      setlocale(LC_TIME, 'C'); // Reset to default
      
  5. Carbon Incompatibility:

    • Directly passing Carbon instances without converting to string may fail:
      // ❌ Fails silently
      $jalaliDate = new JalaliDateTime(Carbon::now());
      
      // ✅ Works
      $jalaliDate = new JalaliDateTime(Carbon::now()->toDateTimeString());
      

Debugging Tips

  1. Validate Dates: Use the isValid() method to check for invalid dates:

    $jalaliDate = new JalaliDateTime('invalid-date');
    if (!$jalaliDate->isValid()) {
        throw new \InvalidArgumentException('Invalid Jalali date');
    }
    
  2. Log Raw Conversions: Debug conversion issues by logging intermediate steps:

    $gregorian = new JalaliDateTime('1402-08-03', true);
    \Log::debug('Gregorian timestamp:', $gregorian->getTimestamp());
    
  3. Test Edge Cases:

    • Test dates around Jalali year transitions (e.g., 1402-08-02 to 1402-08-03).
    • Test time-only inputs (e.g., 1402-08-03 23:59:59).

Extension Points

  1. Custom Formatters: Extend the class to add Jalali-specific formatters:

    class ExtendedJalaliDateTime extends \JalaliDateTime {
        public function formatPersianWeekday() {
            $weekdays = ['شنبه', 'یک‌شنبه', 'دوشنبه', 'سه‌شنبه', 'چهارشنبه', 'پنج‌شنبه', 'جمعه'];
            return $weekdays[$this->format('w')];
        }
    }
    
  2. Database Storage: Store Jalali dates in Gregorian format in the DB for consistency:

    // Model
    protected $dates = ['jalali_published_at'];
    
    public function setJalaliPublishedAtAttribute($value) {
        $this->attributes['jalali_published_at'] = (new JalaliDateTime($value))->format('Y-m-d');
    }
    
    public function getJalaliPublishedAtAttribute($value) {
        return (new JalaliDateTime($value))->format('Y/m/d');
    }
    
  3. Service Provider: Bind the package to Laravel’s container for dependency injection:

    // app/Providers/AppServiceProvider.php
    public function register() {
        $this->app->bind(JalaliDateTime::class, function () {
            return new \JalaliDateTime();
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
daikazu/eloquent-salesforce-objects
unseen-codes/chat
romalytar/yammi-jobs-monitoring-laravel
kisame76/filament-db-table-state
nqxcode/laravel-lucene-search
dpfx/laravel-livewire-wizards
workos/workos-php-laravel
sofa/laravel-global-scope
nawasara/auth-primitives
adhocrat-io/arkhe-main
make-dev/orca-harpoon
itsemon245/lamet
baks-dev/dashboard
amoifr/pickle-panther-bundle
make-dev/orca
dmstr/symfony-system-resources-bundle
dmstr/symfony-job-queue-bundle
dmstr/openapi-json-schema-bundle
dmstr/keycloak-security-bundle
dmstr/doctrine-audit-log-bundle