# Verta - Jalali (Persian/Shamsi) Date and Time Library Verta is a PHP library designed for working with the Jalali (Persian/Shamsi) calendar system. It extends PHP's DateTime functionality to provide seamless conversion between Gregorian and Jalali calendars, making it essential for applications serving Persian-speaking users in Iran, Afghanistan, and other regions. The library integrates with Laravel framework and is fully compatible with Carbon, offering a familiar API for PHP developers. The package provides comprehensive date and time manipulation capabilities including creation, formatting, modification, comparison, and validation of Jalali dates. It supports multiple locales (Persian, Dari, Arabic, Kurdish, Pashto, English), human-readable date differences, and includes Laravel validation rules for form inputs. Verta maintains timezone awareness and offers both static methods and helper functions for convenient instantiation. ## Installation Installation via Composer ```bash composer require hekmatinasser/verta ``` ## Creating Verta Instances Instantiate Verta objects from various date formats ```php use Hekmatinasser\Verta\Verta; // Current Jalali datetime echo verta(); // 1401-05-24 00:00:00 // From Gregorian date (auto-converts to Jalali) echo verta('2022-08-15'); // 1401-05-24 00:00:00 // From Jalali string with parsing echo Verta::parse('1401-05-24 14:12:32')->datetime(); // Returns DateTime object: 2022-08-15 14:12:32 // From specific Jalali date components $date = Verta::createJalali(1401, 5, 24, 14, 12, 32); echo $date->format('Y-m-d H:i:s'); // 1401-05-24 14:12:32 // From Gregorian components (converts to Jalali) $date = Verta::create(2022, 8, 15, 14, 12, 32); echo $date->format('Y-m-d H:i:s'); // 1401-05-24 14:12:32 // From Unix timestamp $date = Verta::createTimestamp(1583501791); echo $date->format('Y-m-d H:i:s'); // 1398-12-16 13:36:31 // Parse with custom format $date = Verta::parseFormat('Y-m-d H:i:s', '1401-05-24 14:12:32'); echo $date->formatGregorian('Y-m-d H:i:s'); // 2022-08-15 14:12:32 // Static factory methods $now = Verta::now(); $today = Verta::today(); // Sets time to 00:00:00 $yesterday = Verta::yesterday(); $tomorrow = Verta::tomorrow(); ``` ## Carbon Integration Convert between Carbon and Verta instances ```php use Illuminate\Support\Carbon; use Hekmatinasser\Verta\Verta; // Carbon to Jalali $carbon = Carbon::now(); echo $carbon->toJalali(); // 1401-05-24 14:25:30 // Using helper with Carbon dates echo now()->toJalali(); // 1401-05-24 14:25:30 // Jalali to Carbon $verta = verta('1401-05-24 14:12:32'); $carbon = $verta->toCarbon(); echo $carbon->format('Y-m-d H:i:s'); // 2022-08-15 14:12:32 // Chain Carbon methods after conversion $carbonDate = verta('1401-05-24')->toCarbon()->addDays(5); echo $carbonDate->toJalali()->format('Y-m-d'); // 1401-05-29 ``` ## Getters and Setters Access and modify date components ```php $v = verta('1401-05-24 14:18:23'); // Getters echo $v->year; // 1401 echo $v->month; // 5 echo $v->day; // 24 echo $v->hour; // 14 echo $v->minute; // 18 echo $v->second; // 23 echo $v->dayOfWeek; // 2 (1=Saturday, 7=Friday in Jalali) echo $v->dayOfYear; // 155 echo $v->weekOfMonth; // 4 echo $v->weekOfYear; // 22 // Setters (modifies instance) $v->year = 1402; $v->month = 6; $v->day = 15; echo $v->format('Y-m-d H:i:s'); // 1402-06-15 14:18:23 // Fluent setters $v->setDate(1401, 5, 24); $v->setTime(15, 30, 45); $v->setTimeString('12:25:45'); $v->setDateTime(1401, 5, 24, 12, 25, 45); echo $v->format('Y-m-d H:i:s'); // 1401-05-24 12:25:45 ``` ## Date Formatting Format dates in various styles ```php $date = verta('1401-05-24 14:12:25'); // Custom format (similar to PHP date()) echo $date->format('Y/m/d'); // 1401/05/24 echo $date->format('Y.m.d H:i'); // 1401.05.24 14:12 echo $date->format('y-n-j g:i:s'); // 01-5-24 2:12:25 // Gregorian format echo $date->formatGregorian('Y-m-d H:i:s'); // 2022-08-15 14:12:25 // Common format shortcuts echo $date->formatDatetime(); // 1401-05-24 14:12:25 echo $date->formatDate(); // 1401-05-24 echo $date->formatTime(); // 14:12:25 echo $date->formatJalaliDatetime(); // 1401/05/24 14:12:25 echo $date->formatJalaliDate(); // 1401/05/24 // Word format (Persian names) Verta::setLocale('fa'); // Set Persian locale echo $date->formatWord('l d F Y'); // دوشنبه 24 مرداد 1401 echo $date->formatWord('l dS F'); // دوشنبه بیست و چهارم مرداد // Quarter format echo $date->format('Q'); // تابستان (summer) echo $date->format('q'); // 2 (quarter number) // Custom default format Verta::setFormat('Y-m-d-H-i-s'); echo $date; // 1401-05-24-14-12-25 Verta::resetFormat(); // Reset to default ``` ## Human-Readable Differences Display relative time differences ```php Verta::setLocale('fa'); // Persian locale $now = verta(); // Past dates echo verta('-13 month')->formatDifference(); // 1 سال قبل (1 year ago) echo verta('-5 days')->formatDifference(); // 5 روز قبل (5 days ago) echo verta('-2 hours')->formatDifference(); // 2 ساعت قبل (2 hours ago) echo verta('-30 seconds')->formatDifference(); // 30 ثانیه قبل (30 seconds ago) // Future dates echo verta('+3 days')->formatDifference(); // 3 روز بعد (3 days later) echo verta('+2 weeks')->formatDifference(); // 2 هفته بعد (2 weeks later) echo verta('+6 months')->formatDifference(); // 6 ماه بعد (6 months later) // Difference from specific date $target = verta('1401-05-24'); $base = verta('1401-05-20'); echo $target->formatDifference($base); // 4 روز بعد // English locale Verta::setLocale('en'); echo verta('-1 day')->formatDifference(); // 1 day ago echo verta('+5 hours')->formatDifference(); // 5 hours from now ``` ## Date Modification Add or subtract time periods ```php $date = verta('1401-05-24 14:30:50'); // Add time units (returns modified instance) echo $date->addYears(2)->format('Y-m-d'); // 1403-05-24 echo $date->addMonths(3)->format('Y-m-d'); // 1403-08-24 echo $date->addWeeks(2)->format('Y-m-d'); // 1403-09-07 echo $date->addDays(10)->format('Y-m-d'); // 1403-09-17 echo $date->addHours(5)->format('H:i:s'); // 19:30:50 echo $date->addMinutes(30)->format('H:i:s'); // 20:00:50 echo $date->addSeconds(45)->format('H:i:s'); // 20:01:35 // Subtract time units $date = verta('1401-05-24 14:30:50'); echo $date->subYears(1)->format('Y-m-d'); // 1400-05-24 echo $date->subMonths(2)->format('Y-m-d'); // 1400-03-24 echo $date->subWeeks(1)->format('Y-m-d'); // 1400-03-17 echo $date->subDays(5)->format('Y-m-d'); // 1400-03-12 echo $date->subHours(3)->format('H:i:s'); // 11:30:50 echo $date->subMinutes(15)->format('H:i:s'); // 11:15:50 echo $date->subSeconds(30)->format('H:i:s'); // 11:15:20 // Method chaining $future = verta('1401-05-24') ->addMonths(2) ->addDays(5) ->addHours(3); echo $future->format('Y-m-d H:i:s'); // 1401-07-29 03:00:00 ``` ## Time Boundaries Get start and end of time periods ```php $date = verta('1401-05-24 14:30:50'); // Minute boundaries echo $date->startMinute()->format('Y-m-d H:i:s'); // 1401-05-24 14:30:00 // Day boundaries echo $date->startDay()->format('Y-m-d H:i:s'); // 1401-05-24 00:00:00 echo $date->endDay()->format('Y-m-d H:i:s'); // 1401-05-24 23:59:59 // Week boundaries (Saturday to Friday in Jalali) echo $date->startWeek()->format('Y-m-d H:i:s'); // 1401-05-21 00:00:00 (Saturday) echo $date->endWeek()->format('Y-m-d H:i:s'); // 1401-05-27 23:59:59 (Friday) // Month boundaries echo $date->startMonth()->format('Y-m-d H:i:s'); // 1401-05-01 00:00:00 echo $date->endMonth()->format('Y-m-d H:i:s'); // 1401-05-31 23:59:59 // Quarter boundaries (Jalali quarters: 1-3, 4-6, 7-9, 10-12) echo $date->startQuarter()->format('Y-m-d H:i:s'); // 1401-04-01 00:00:00 echo $date->endQuarter()->format('Y-m-d H:i:s'); // 1401-06-31 23:59:59 // Year boundaries echo $date->startYear()->format('Y-m-d H:i:s'); // 1401-01-01 00:00:00 echo $date->endYear()->format('Y-m-d H:i:s'); // 1401-12-29 23:59:59 // Practical example: Get all dates in current month $start = verta()->startMonth(); $end = verta()->endMonth(); echo "Month range: {$start->format('Y-m-d')} to {$end->format('Y-m-d')}"; ``` ## Date Comparison Compare dates and calculate differences ```php $date1 = verta('1401-05-24 14:30:50'); $date2 = verta('1401-05-20 10:15:30'); // Equality comparison $date1->eq($date2); // false (equal to) $date1->ne($date2); // true (not equal to) // Greater than comparison $date1->gt($date2); // true (greater than) $date1->gte($date2); // true (greater than or equal) // Less than comparison $date1->lt($date2); // false (less than) $date1->lte($date2); // false (less than or equal) // Range comparison $date1->between($date2, verta('1401-06-01')); // true (inclusive by default) $date1->between($date2, verta('1401-05-24'), false); // false (exclusive) // Difference calculations (absolute by default) echo $date1->diffYears($date2); // 0 echo $date1->diffMonths($date2); // 0 echo $date1->diffWeeks($date2); // 0 echo $date1->diffDays($date2); // 4 echo $date1->diffHours($date2); // 100 echo $date1->diffMinutes($date2); // 6015 echo $date1->diffSeconds($date2); // 360920 // Signed differences (false = include negative) echo $date2->diffDays($date1, false); // -4 // Find closest/farthest date $target = verta('1401-05-25'); $option1 = verta('1401-05-20'); $option2 = verta('1401-05-30'); echo $target->closest($option1, $option2)->format('Y-m-d'); // 1401-05-20 echo $target->farthest($option1, $option2)->format('Y-m-d'); // 1401-05-30 // Min/Max comparison echo $date1->min($date2)->format('Y-m-d'); // 1401-05-20 (earlier date) echo $date1->max($date2)->format('Y-m-d'); // 1401-05-24 (later date) // Comparison with string dates echo verta('+2 day')->gte('2022-08-15'); // true ``` ## Date Validation and Checking Validate dates and check temporal properties ```php // Validate Jalali date components Verta::isValidDate(1401, 5, 24); // true Verta::isValidDate(1401, 13, 24); // false (invalid month) Verta::isValidDate(1401, 5, 32); // false (invalid day) // Validate time components Verta::isValidTime(14, 30, 50); // true Verta::isValidTime(25, 30, 50); // false (invalid hour) Verta::isValidTime(14, 65, 50); // false (invalid minute) // Check leap year Verta::isLeapYear(1403); // true (1403 is a leap year) Verta::isLeapYear(1402); // false // Temporal position checks $date = verta('1400-05-24'); $date->isPast(); // true $date->isFuture(); // false $date->isToday(); // false $date->isYesterday(); // false $date->isTomorrow(); // false // Week position $date->isLastWeek(); // false $date->isNextWeek(); // false // Month/Year position $date->isLastMonth(); // false $date->isNextMonth(); // false $date->isLastYear(); // true $date->isNextYear(); // false $date->isCurrentYear(); // false // Day of week checks $date = verta('1401-05-24'); // Monday $date->isMonday(); // true $date->isSaturday(); // false $date->isWeekday(); // true (Sat-Wed in Jalali) $date->isWeekend(); // false (Thu-Fri in Jalali) // Same date checks $date1 = verta('1401-05-24 14:30:00'); $date2 = verta('1401-05-24 18:45:00'); $date1->isSameDay($date2); // true $date1->isSameYear($date2); // true // Birthday check (same month-day, different year) $birthdate = verta('1380-05-24'); $today = verta('1401-05-24'); $birthdate->isBirthday($today); // true // Custom format comparison $date1->isSameAs('Y-m-d', $date2); // true $date1->isSameAs('Y-m-d H:i', $date2); // false ``` ## Laravel Validation Rules Validate Jalali dates in Laravel forms ```php use Illuminate\Http\Request; // Basic date validation public function store(Request $request) { $validated = $request->validate([ 'birthday' => ['required', 'jdate'], 'appointment' => ['required', 'jdatetime'], ]); } // Custom format validation $request->validate([ 'birthday' => ['required', 'jdate:Y/m/d'], 'meeting_time' => ['required', 'jdatetime:Y/m/d H:i'], ]); // Multiple format support $request->validate([ 'flexible_date' => ['required', 'jdate_multi_format:Y-m-d,Y/m/d,Y.m.d'], ]); // Date comparison validation $request->validate([ 'start_date' => ['required', 'jdate'], 'end_date' => ['required', 'jdate_after:' . $request->start_date], 'event_date' => ['required', 'jdate_before:1402-01-01'], 'registration' => ['required', 'jdate_after_equal:1401-01-01'], 'deadline' => ['required', 'jdate_before_equal:1401-12-29'], ]); // Datetime comparison $request->validate([ 'checkin' => ['required', 'jdatetime_after:1401-05-20 14:00:00'], 'checkout' => ['required', 'jdatetime_before:1401-05-25 12:00:00'], ]); // Equality validation $request->validate([ 'exact_date' => ['required', 'jdate_equal:1401-05-24'], 'not_holiday' => ['required', 'jdate_not_equal:1401-01-01'], ]); // Validation with custom format $request->validate([ 'birth_date' => ['required', 'jdate_before_equal:1380-12-29,Y/m/d'], ]); // Available validation rules: // - jdate, jdate_multi_format // - jdatetime // - jdate_equal, jdate_not_equal // - jdatetime_equal, jdatetime_not_equal // - jdate_after, jdate_after_equal // - jdate_before, jdate_before_equal // - jdatetime_after, jdatetime_after_equal // - jdatetime_before, jdatetime_before_equal ``` ## Localization Configure language for date output ```php use Hekmatinasser\Verta\Verta; // Set locale (fa, en, ar, ku, ps) Verta::setLocale('fa'); // Persian (Farsi) echo verta()->formatWord('l d F Y'); // دوشنبه 24 مرداد 1401 Verta::setLocale('en'); // English echo verta()->formatWord('l d F Y'); // Monday 24 Mordad 1401 Verta::setLocale('ar'); // Arabic echo verta()->formatWord('l d F Y'); // الاثنين 24 مرداد 1401 Verta::setLocale('ku'); // Kurdish echo verta()->formatWord('l d F Y'); // Monday 24 Mordad 1401 Verta::setLocale('ps'); // Pashto echo verta()->formatWord('l d F Y'); // Monday 24 Mordad 1401 // Get current locale $currentLocale = Verta::getLocale(); // 'fa' // Locale affects formatDifference() output Verta::setLocale('fa'); echo verta('-2 hours')->formatDifference(); // 2 ساعت قبل Verta::setLocale('en'); echo verta('-2 hours')->formatDifference(); // 2 hours ago // Get localized month/day names $messages = Verta::getMessages(); // Returns array of localized strings $messages = Verta::getMessages('en'); // Get specific locale messages ``` ## Summary Verta serves as a comprehensive solution for Persian/Shamsi calendar operations in PHP applications, particularly those built with Laravel. The library's primary use cases include Persian calendar display for user interfaces, date storage and retrieval with automatic conversion, form validation for Persian date inputs, and localized datetime formatting for multi-language applications. It enables developers to handle birthday tracking, event scheduling, and historical date management while maintaining the cultural relevance of the Jalali calendar system. The package's Carbon compatibility ensures smooth integration with existing Laravel codebases that rely on Carbon for date manipulation. Integration patterns include using the global `verta()` helper function for quick instantiation, leveraging Laravel's service container through the facade pattern, extending Carbon instances with the `toJalali()` macro for seamless conversion, and registering custom validation rules through the VertaServiceProvider. Developers can maintain consistent date formatting across applications by setting global defaults via `Verta::setFormat()` and `Verta::setLocale()`, while timezone-aware operations ensure accurate conversions between Gregorian and Jalali calendars. The library's fluent interface and method chaining support enable readable date manipulation code, and its comprehensive test coverage guarantees reliability in production environments handling Persian calendar operations.