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

Date Time Laravel Package

php-standard-library/date-time

Immutable, timezone-aware DateTime types for PHP. Provides Duration, Period, and Interval helpers for safer date/time arithmetic and ranges, designed as a standard-library style package with clear docs and contribution links.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation

    composer require php-standard-library/date-time
    

    Add to composer.json under require if production, or require-dev for testing.

  2. First Use Case: Immutable DateTime Creation

    use PhpStandardLibrary\DateTime\DateTime;
    
    $date = DateTime::fromIsoString('2026-05-20T12:00:00+00:00');
    // or
    $now = DateTime::now('America/Chicago');
    
  3. Key Classes to Explore

    • DateTime: Immutable, timezone-aware wrapper (like Carbon but stricter).
    • Duration: Represents a span of time (e.g., Duration::fromHours(2.5)).
    • Period: Fixed intervals (e.g., Period::months(3) for billing cycles).
    • Interval: Dynamic ranges (e.g., Interval::fromStartEnd($start, $end)).
  4. Where to Look First

    • Laravel Integration: Check tests/ for examples of timezone-aware operations.
    • API Docs: Use PHPDoc annotations (if available) or IDE autocompletion.
    • Laravel-Specific: Pair with Carbon via adapters (e.g., Carbon::instance($dateTime)).

Implementation Patterns

1. Laravel Model Integration

Pattern: Use accessors/mutators for Eloquent models.

use PhpStandardLibrary\DateTime\DateTime;

class Order extends Model
{
    protected $casts = [
        'created_at' => DateTime::class,
        'due_date' => DateTime::class,
    ];

    // Accessor for formatted output
    public function getDueDateFormattedAttribute(): string
    {
        return $this->due_date->format('Y-m-d H:i');
    }
}

2. Timezone-Aware API Responses

Pattern: Normalize all timestamps to UTC or user’s timezone.

use PhpStandardLibrary\DateTime\DateTime;

public function show(Order $order)
{
    $userTimezone = auth()->user()->timezone ?? 'UTC';
    $dueDate = $order->due_date->inTimezone($userTimezone);

    return response()->json([
        'due_date' => $dueDate->toIsoString(),
    ]);
}

3. Recurring Tasks with Periods

Pattern: Replace CarbonPeriod with Period for subscriptions/billing.

use PhpStandardLibrary\DateTime\Period;

$subscription = Subscription::create([
    'period' => Period::months(3), // Immutable, testable
    'ends_at' => DateTime::now()->add($subscription['period']),
]);

// Validate renewal
if ($subscription->ends_at->isPast()) {
    $subscription->renew();
}

4. Duration-Based Job Scheduling

Pattern: Use Duration for dynamic delays (e.g., retries, queues).

use PhpStandardLibrary\DateTime\Duration;
use Illuminate\Support\Facades\Bus;

Bus::dispatch(new ProcessOrder($order))
    ->delay(Duration::fromMinutes(5)); // Laravel 9+ compatible

5. Validation with Custom Rules

Pattern: Extend Laravel’s validation to use Duration/Period.

use PhpStandardLibrary\DateTime\Duration;
use Illuminate\Validation\Rule;

$validator = Validator::make($data, [
    'duration' => [
        'required',
        function ($attribute, $value, $fail) {
            if (!Duration::tryFromString($value)) {
                $fail('Invalid duration format (e.g., "2 hours").');
            }
        },
    ],
]);

6. Testing Time Manipulation

Pattern: Mock DateTime in unit tests.

use PhpStandardLibrary\DateTime\DateTime;
use PhpStandardLibrary\DateTime\Duration;

public function test_order_expiry()
{
    $fixedTime = DateTime::fromIsoString('2026-01-01T00:00:00+00:00');
    $order = new Order(['due_date' => $fixedTime->add(Duration::fromDays(7))]);

    $this->assertTrue($order->isDue());
}

7. Laravel Echo/Pusher Integration

Pattern: Convert DateTime to JS-compatible timestamps.

use PhpStandardLibrary\DateTime\DateTime;

Broadcast::channel('orders', function ($user) {
    return [
        'timezone' => $user->timezone,
        'last_updated' => DateTime::now()->getTimestamp(),
    ];
});

Gotchas and Tips

Pitfalls

  1. Immutability Overhead

    • Issue: Every "modification" returns a new object (e.g., $newDate = $date->add(...)).
    • Fix: Cache intermediate results or use Duration/Period for bulk operations.
      $dates = collect(range(1, 10))->map(fn ($i) =>
          $baseDate->add(Duration::fromDays($i))
      );
      
  2. Timezone Defaults

    • Issue: DateTime::now() defaults to UTC (unlike Carbon’s local timezone).
    • Fix: Explicitly set timezone:
      $now = DateTime::now('UTC'); // or user’s timezone
      
  3. Serialization Quirks

    • Issue: JSON/API responses may fail without custom handling.
    • Fix: Implement JsonSerializable or use Laravel’s toJson():
      $date->toJson(); // Returns ISO string
      
  4. Method Naming Differences

    • Issue: Duration::add() vs. Carbon::addDays().
    • Fix: Create a cheat sheet or wrapper:
      class CarbonAdapter {
          public static function fromDateTime(DateTime $dateTime): Carbon
          {
              return Carbon::instance($dateTime);
          }
      }
      
  5. Database Casting

    • Issue: Eloquent’s $casts may not auto-convert timestamps.
    • Fix: Use accessors or custom casts:
      protected $casts = [
          'created_at' => [DateTime::class, 'datetime:Y-m-d H:i:s'],
      ];
      
  6. Lack of Laravel-Specific Helpers

    • Issue: No built-in parse() like Carbon::parse().
    • Fix: Extend the class:
      DateTime::macro('parse', function ($time, $format = null) {
          return $format ? DateTime::fromFormat($format, $time)
                         : DateTime::fromIsoString($time);
      });
      
  7. Performance in Loops

    • Issue: Immutable objects may slow down bulk operations.
    • Fix: Benchmark and optimize:
      // Slow: Creates 1000 new objects
      collect(range(1, 1000))->map(fn ($i) => $date->add(Duration::fromDays($i)));
      
      // Faster: Reuse base object
      $base = $date;
      $dates = collect(range(1, 1000))->map(fn ($i) => $base->add(Duration::fromDays($i)));
      

Debugging Tips

  1. Log Timezones Explicitly

    \Log::debug('Timezone:', ['date' => $date->getTimezone()->getName()]);
    
  2. Use toIsoString() for Consistency

    $date->toIsoString(); // Always UTC-based, debug-friendly
    
  3. Validate with Period/Duration

    if (!$duration instanceof Duration) {
        throw new \InvalidArgumentException('Expected Duration');
    }
    
  4. Check for Mixed Carbon/DateTime Usage

    • Use PHPStan rules to detect:
      # phpstan.neon
      parameters:
          level: 7
      rules:
          PhpStandardLibrary\DateTime\Rules\NoMixedCarbonDateTime: true
      

Extension Points

  1. Custom Formatters

    DateTime::macro('toLaravelFormat', function () {
        return $this->format('Y-m-d H:i:s.uP');
    });
    
  2. Business Logic Extensions

    DateTime::macro('isBusinessDay', function () {
        $day = (int) $this->format('N');
        return $day !== 6 && $day !== 7
    
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.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope