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 Laravel Package

hekmatinasser/jalali

Jalali (Shamsi) date/time utilities for PHP and Laravel. Converts between Jalali (solar) and Gregorian calendars, provides helper functions for formatting and working with dates. Extends PHP DateTime and is compatible with Carbon.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require hekmatinasser/jalali
    

    Add the service provider to config/app.php:

    'providers' => [
        // ...
        Hekmatinasser\Jalali\JalalianServiceProvider::class,
    ],
    
  2. Publish Config (Optional):

    php artisan vendor:publish --provider="Hekmatinasser\Jalali\JalalianServiceProvider"
    

    This generates config/jalali.php for customization (e.g., default locale, timezone).

  3. First Use Case: Convert a Gregorian DateTime to Jalali:

    use Hekmatinasser\Jalali\Jalalian;
    
    $gregorian = new \DateTime('2023-12-25');
    $jalali = Jalalian::fromGregorian($gregorian);
    echo $jalali->format('Y/m/d'); // Output: 1402/10/04
    
  4. Carbon Integration:

    use Carbon\Carbon;
    use Hekmatinasser\Jalali\Jalalian;
    
    $carbon = Carbon::parse('2023-12-25');
    $jalaliCarbon = Jalalian::fromCarbon($carbon);
    echo $jalaliCarbon->format('Y/m/d'); // Output: 1402/10/04
    

Implementation Patterns

Core Workflows

  1. Date Conversion:

    • Gregorian → Jalali:
      $jalali = Jalalian::fromGregorian($gregorianDateTime);
      
    • Jalali → Gregorian:
      $gregorian = Jalalian::fromJalali($jalaliDateTime);
      
    • Carbon Integration:
      $jalaliCarbon = Jalalian::fromCarbon($carbon);
      $gregorianCarbon = Jalalian::toCarbon($jalaliCarbon);
      
  2. Formatting: Use Jalali’s built-in formatters (supports all PHP DateTime formatters + Jalali-specific ones):

    $jalali->format('l j F Y'); // e.g., "شنبه ۴ آبان ۱۴۰۲"
    $jalali->format('Y/m/d H:i'); // e.g., "1402/10/04 12:30"
    
  3. Query Builder Integration: Use with Laravel’s query builder for Jalali-aware timestamps:

    use Hekmatinasser\Jalali\Jalalian;
    
    $jalaliDate = Jalalian::fromFormat('Y/m/d', '1402/10/04');
    $gregorianDate = $jalaliDate->toGregorian();
    
    // Store Jalali date as Gregorian in DB (recommended for consistency)
    DB::table('events')->whereDate('created_at', $gregorianDate)->get();
    
  4. Helper Functions:

    • Current Jalali Date:
      $nowJalali = Jalalian::now();
      
    • Parse Jalali String:
      $jalali = Jalalian::fromFormat('d/m/Y', '04/10/1402');
      
  5. Timezone Handling: Set default timezone in config/jalali.php (e.g., Asia/Tehran) to avoid manual conversions:

    'timezone' => 'Asia/Tehran',
    

Advanced Patterns

  1. Custom Formatters: Extend the package to add Jalali-specific formatters (e.g., Persian month names):

    Jalalian::addFormat('F', function($date) {
        $months = ['فروردین', 'اردیبهشت', /* ... */];
        return $months[$date->format('n') - 1];
    });
    
  2. Middleware for Jalali Responses: Convert all responses to Jalali dates in API:

    namespace App\Http\Middleware;
    
    use Hekmatinasser\Jalali\Jalalian;
    use Closure;
    
    class ConvertJalaliDates
    {
        public function handle($request, Closure $next)
        {
            $response = $next($request);
            $response->getContent();
            $response->setContent(
                preg_replace_callback(
                    '/"(\d{4}-\d{2}-\d{2})"/',
                    fn($matches) => '"' . Jalalian::fromFormat('Y-m-d', $matches[1])->format('Y/m/d') . '"',
                    $response->getContent()
                )
            );
            return $response;
        }
    }
    
  3. Model Observers: Automatically convert timestamps to/from Jalali:

    use Hekmatinasser\Jalali\Jalalian;
    use Illuminate\Database\Eloquent\Model;
    
    class Event extends Model
    {
        protected $dates = ['created_at', 'updated_at'];
    
        public function getCreatedAtAttribute($value)
        {
            return Jalalian::fromGregorian($value)->format('Y/m/d H:i');
        }
    
        public function setCreatedAtAttribute($value)
        {
            $this->attributes['created_at'] = Jalalian::fromFormat('Y/m/d H:i', $value)->toGregorian();
        }
    }
    
  4. Validation: Validate Jalali dates in Laravel:

    use Hekmatinasser\Jalali\Jalalian;
    use Illuminate\Support\Facades\Validator;
    
    $validator = Validator::make($request->all(), [
        'event_date' => [
            'required',
            function ($attribute, $value, $fail) {
                if (!Jalalian::isValid($value)) {
                    $fail('The ' . $attribute . ' is invalid.');
                }
            },
        ],
    ]);
    

Gotchas and Tips

Pitfalls

  1. Database Storage:

    • Avoid storing Jalali dates directly in the database. Always convert to Gregorian (toGregorian()) before saving to ensure consistency.
    • Example of incorrect approach:
      // ❌ Bad: Storing Jalali directly
      $model->date = Jalalian::now()->format('Y/m/d');
      
    • Correct approach:
      // ✅ Good: Store Gregorian, convert on retrieval
      $model->date = Jalalian::now()->toGregorian();
      
  2. Timezone Mismatches:

    • Jalali dates are timezone-agnostic by design. Ensure your app’s timezone (e.g., Asia/Tehran) matches the expected Jalali calculations.
    • Debug timezone issues with:
      Jalalian::setTimezone('Asia/Tehran');
      
  3. Carbon vs. Native DateTime:

    • The package extends both DateTime and Carbon. Prefer Carbon for Laravel apps to avoid quirks with native DateTime immutability.
    • Example of quirk:
      $jalali = Jalalian::fromGregorian($gregorian);
      $jalali->modify('+1 day'); // Works with Carbon; may behave unexpectedly with native DateTime.
      
  4. Leap Year Calculations:

    • Jalali leap years (e.g., 1404) can cause off-by-one errors in date arithmetic. Test edge cases like:
      $leapYear = Jalalian::fromFormat('Y', '1404');
      $leapYear->modify('+1 year'); // Should correctly roll over to 1405.
      
  5. Locale-Specific Formatting:

    • The package does not handle locale-specific formatting (e.g., RTL/LTR) out of the box. Use libraries like voku/helpertypes or symfony/intl for advanced localization.

Debugging Tips

  1. Validate Jalali Dates: Use Jalalian::isValid() to check if a Jalali string is correct:

    if (!Jalalian::isValid('1402/13/04')) {
        // Invalid: Month 13 doesn't exist in Jalali.
    }
    
  2. Compare Dates: Convert both dates to Gregorian before comparison:

    $jalali1 = Jalalian::fromFormat('Y/m/d', '1402/10/04');
    $jalali2 = Jalalian::fromFormat('Y/m/d', '1402/10/05');
    if ($jalali1->toGregorian() < $jalali2->toGregorian()) {
        // jalali1 is earlier.
    }
    
  3. Log Raw Data: Log Gregorian timestamps alongside Jalali for debugging:

    $jalali = Jalalian::now();
    \Log::debug([
        'jalali' => $jalali->format('Y/m/d'),
        'gregorian' => $jalali->toGregor
    
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.
besmartand-pro/php-quality-config
sentix/ai-chatbot
terminal42/code-quality-tools
codifyo/ts-generator-bundle
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity