Search by

imrandevbd / tarikh

imranbru99

A modern, immutable, Laravel-native date/time toolkit with built-in South Asian calendar, holiday, and locale support.

Package info

github.com/imranbru99/tarikh

pkg:composer/imrandevbd/tarikh

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

dev-main 2026-10-16 22:10 UTC

This package is auto-updated.

Last update: 2026-10-16 22:14:10 UTC


README

Latest Version on Packagist Total Downloads PHP Version Laravel Support License

Tarikh (تاریخ / তারিখ) is an ultra-fast, modern, and immutable DateTime toolkit engineered from the ground up for PHP 8.3+ and Laravel. Designed as an elegant, lightweight alternative to legacy date libraries, Tarikh guarantees zero unwanted side-effects through strict immutability, microsecond precision, macroable extensibility, and seamless developer ergonomics.

⚡ Highlights & Key Features

  • 🔒 100% Immutable by Design: Every modification returns a pristine new instance. Say goodbye to accidental mutation bugs in loops and queries.
  • 🚀 Built for Modern PHP 8.3+: Type-safe backed enums (Unit, Month, Weekday), strict types, and zero legacy bloat.
  • 🧪 Time Travel & Testing Mock: Built-in setTestNow() for deterministic testing across suites.
  • 🎯 Fluent Sugar Modifiers: Intuitive arithmetic (addDays(), subMonths(), addHours(), etc.).
  • 📐 Boundary Precision: Precise startOf() and endOf() boundaries down to the microsecond (Second, Minute, Hour, Day, Week, Month, Quarter, Year).
  • ⚖️ Rich Comparisons: isBefore(), isAfter(), isBetween(), isWeekend(), isLeapYear(), and more.
  • 📊 Detailed Diff Engine: High-precision difference metrics (diffInSeconds, diffInMinutes, diffInHours, diffInDays, diffInWeeks, diffInMonths, diffInYears).
  • 🔌 Macroable & Extensible: Add custom domain logic or regional calendar rules at runtime via Tarikh::macro() and Tarikh::mixin().
  • 📦 First-Class Laravel Integration: Auto-discovered Service Provider and Facade ready out of the box.

📥 Installation

Install via Composer:

composer require imrandevbd/tarikh

Requirements: PHP 8.3 or higher with the ext-intl extension.

🚀 Quick Start

use Tarikh\Tarikh;
use Tarikh\Enums\Unit;

// Create instances
$now = Tarikh::now();
$today = Tarikh::today('Asia/Dhaka');
$event = Tarikh::parse('2025-12-31 23:59:59', 'UTC');

// Immutable arithmetic
$nextWeek = $now->addWeeks(1);
$prevQuarter = $now->sub(1, Unit::Quarter);

// Boundaries
$monthStart = $now->startOf(Unit::Month); // YYYY-MM-01 00:00:00
$monthEnd   = $now->endOf(Unit::Month);   // YYYY-MM-31 23:59:59.999999

// Human-friendly formats
echo $now->toDateString();     // "2025-05-15"
echo $now->toDateTimeString(); // "2025-05-15 14:30:00"
echo $now->toIso8601String();  // "2025-05-15T14:30:00+00:00"

📖 Complete Feature Guide

1. Creation & Parsing

use Tarikh\Tarikh;

// Current timestamp
$now = Tarikh::now();
$nowDhaka = Tarikh::now('Asia/Dhaka');

// Start of today, tomorrow, yesterday
$today     = Tarikh::today();
$tomorrow  = Tarikh::tomorrow();
$yesterday = Tarikh::yesterday();

// Parse strings or DateTimeInterface
$date = Tarikh::parse('2025-06-15 18:30:00', 'America/New_York');

// Explicit constructor
$created = Tarikh::create(year: 2025, month: 12, day: 25, hour: 10, minute: 0, second: 0, tz: 'UTC');

// From UNIX timestamp
$fromEpoch = Tarikh::fromTimestamp(1735689600);

2. Time Travel & Testing (setTestNow)

Freeze or shift time during unit tests effortlessly:

use Tarikh\Tarikh;

// Freeze time for tests
Tarikh::setTestNow(Tarikh::parse('2024-01-01 12:00:00'));

echo Tarikh::now()->toDateTimeString(); // "2024-01-01 12:00:00"
echo Tarikh::today()->toDateTimeString(); // "2024-01-01 00:00:00"

// Reset back to system time
Tarikh::setTestNow(null);

3. Date Arithmetic & Modifiers

All operations return a new instance without mutating the original object:

use Tarikh\Tarikh;
use Tarikh\Enums\Unit;

$tarikh = Tarikh::parse('2025-01-15 12:00:00');

// Enums-based manipulation
$modified = $tarikh
    ->add(2, Unit::Day)
    ->sub(1, Unit::Month)
    ->add(3, Unit::Hour);

// Convenient fluent modifiers
$tarikh->addDays(5);
$tarikh->subDays(2);
$tarikh->addWeeks(3);
$tarikh->subWeeks(1);
$tarikh->addMonths(6);
$tarikh->subMonths(2);
$tarikh->addYears(1);
$tarikh->subYears(5);
$tarikh->addHours(4);
$tarikh->subHours(2);
$tarikh->addMinutes(30);
$tarikh->subMinutes(15);
$tarikh->addSeconds(45);
$tarikh->subSeconds(10);

4. Boundary Calculation (startOf & endOf)

Accurately calculate periods down to the microsecond:

use Tarikh\Tarikh;
use Tarikh\Enums\Unit;

$date = Tarikh::parse('2025-05-15 14:30:45');

// Start of periods
$startOfDay     = $date->startOf(Unit::Day);     // 2025-05-15 00:00:00
$startOfWeek    = $date->startOf(Unit::Week);    // Monday of the week 00:00:00
$startOfMonth   = $date->startOf(Unit::Month);   // 2025-05-01 00:00:00
$startOfQuarter = $date->startOf(Unit::Quarter); // 2025-04-01 00:00:00
$startOfYear   = $date->startOf(Unit::Year);    // 2025-01-01 00:00:00

// End of periods (with microsecond precision: 23:59:59.999999)
$endOfDay   = $date->endOf(Unit::Day);
$endOfWeek  = $date->endOf(Unit::Week);          // Sunday 23:59:59.999999
$endOfMonth = $date->endOf(Unit::Month);
$endOfYear  = $date->endOf(Unit::Year);

5. Comparisons & State Checks

use Tarikh\Tarikh;

$t1 = Tarikh::parse('2025-01-01');
$t2 = Tarikh::parse('2025-01-15');
$t3 = Tarikh::parse('2025-02-01');

// Relative comparisons
$t1->isBefore($t2);              // true
$t2->isAfter($t1);               // true
$t1->equalTo($t1);               // true
$t2->isBetween($t1, $t3);        // true

// Same unit checks
$t1->isSameDay($t2);             // false
$t1->isSameMonth($t2);           // true
$t1->isSameYear($t3);            // true

// State predicates
$t1->isWeekend();                // true/false
$t1->isWeekday();                // true/false
$t1->isToday();                  // true/false
$t1->isFuture();                 // true/false
$t1->isPast();                   // true/false
$t1->isLeapYear();               // true/false

6. Differences & Intervals

Calculate precise differences between two dates:

use Tarikh\Tarikh;

$start = Tarikh::parse('2025-01-01 00:00:00');
$end   = Tarikh::parse('2025-01-05 12:00:00');

$start->diffInSeconds($end); // 388800
$start->diffInMinutes($end); // 6480.0
$start->diffInHours($end);   // 108.0
$start->diffInDays($end);    // 4.5
$start->diffInWeeks($end);   // ~0.64
$start->diffInMonths($end);  // Float month difference
$start->diffInYears($end);   // Float year difference

7. Formatting & JSON Serialization

$tarikh = Tarikh::parse('2025-07-20 18:30:45', 'Asia/Tokyo');

// Standard outputs
$tarikh->toDateString();       // "2025-07-20"
$tarikh->toTimeString();       // "18:30:45"
$tarikh->toDateTimeString();   // "2025-07-20 18:30:45"
$tarikh->toIso8601String();    // "2025-07-20T18:30:45+09:00"
$tarikh->toRfc3339String();    // "2025-07-20T18:30:45+09:00"
$tarikh->format('l, F j, Y');  // "Sunday, July 20, 2025"

// Debug inspection
$tarikh->explain();
// [
//   'datetime'  => '2025-07-20 18:30:45',
//   'timezone'  => 'Asia/Tokyo',
//   'timestamp' => 1753003845,
// ]

// Automatic JSON serialization (implements JsonSerializable)
json_encode(['event_at' => $tarikh]);

8. Macroable & Custom Extensibility

Extend Tarikh at runtime using the Macroable trait:

use Tarikh\Tarikh;

// Define a macro
Tarikh::macro('isIndependenceDay', function () {
    return $this->format('m-d') === '03-26';
});

$day = Tarikh::parse('2025-03-26');
echo $day->isIndependenceDay(); // true

9. Laravel Integration

Tarikh automatically hooks into Laravel. If you prefer using the Facade:

use Tarikh\Laravel\Facades\Tarikh;

$now = Tarikh::now();
$deadline = Tarikh::parse($request->input('due_date'))->endOfDay();

🧪 Testing

Run test suite via Pest:

composer test

Or run static analysis and code styling:

vendor/bin/phpstan analyse
vendor/bin/pint --test

🤝 Let's Connect & Collaborate

I am open to Senior Remote Full-Stack Roles, AI Platform Architecture Contracts, and Enterprise Technical Advisory.

  • Timezone: UTC+6 (Dhaka / Rangpur, Bangladesh) — Flexible overlap with US, UK, and European business hours.
  • Delivery Mode: Async-ready, Slack, Discord, Jira, GitHub, and production-first accountability.
Channel Address / Handle Quick Action
🌐 Primary Portfolio imrandev.bd Visit Site ↗
📦 Packagist Packages packagist.org/packages/imrandevbd/ View Packages ↗
💼 LinkedIn Profile linkedin.com/in/imranbru99 Connect ↗
🐙 GitHub Profile github.com/imranbru99 Follow ↗
💬 WhatsApp Direct +880 1576-918420 Chat Now ↗
📧 Direct Email me@imrandev.bd Send Email ↗
🐦 X (Twitter) @imrandev_bd Follow ↗
📺 YouTube Tech @ImranDevBD Subscribe ↗

📄 License

The MIT License (MIT). Please see License File for more information.