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

Chronos Laravel Package

cakephp/chronos

Chronos provides immutable date/time objects for PHP, helping prevent accidental mutations and side effects. Includes ChronosDate for calendar dates fixed at 00:00:00, plus convenient APIs inspired by Carbon but no longer extending DateTime.

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup
1. **Installation**:
   ```bash
   composer require cakephp/chronos

Ensure PHP 8.1+ is used (check version map).

  1. First Use Case: Replace native DateTime with Chronos for immutability:

    use Cake\Chronos\Chronos;
    
    $now = Chronos::now(); // Immutable DateTime
    $tomorrow = $now->addDay(); // Returns new instance
    
  2. Key Classes:

    • Chronos: Immutable datetime (extends DateTimeImmutable).
    • ChronosDate: Calendar-only (time frozen to 00:00:00).
    • ChronosTime: Time-only (date irrelevant).
  3. Where to Look First:

    • API Docs for method signatures.
    • Book for conceptual guides.
    • Chronos::now() and ChronosDate::today() for common entry points.

Implementation Patterns

Core Workflows

1. Immutable DateTime Operations

  • Pattern: Chain methods to avoid side effects.
    $deadline = Chronos::now()
        ->addDays(7)
        ->setTime(23, 59, 59);
    
  • Key Methods:
    • add*()/sub*() (e.g., addHours(2)).
    • modify() (returns new instance; assign to variable).
    • set*() (e.g., setYear(2025)).

2. Calendar-Only Logic

  • Use ChronosDate for date arithmetic (ignores time):
    $eventDate = new ChronosDate('2024-12-25');
    $nextWeek = $eventDate->addWeek(); // '2025-01-01'
    
  • Use Case: Scheduling, date comparisons, or UI displays.

3. Time-Only Logic

  • Use ChronosTime for recurring schedules:
    $openingTime = ChronosTime::create(9, 0, 0);
    $closingTime = $openingTime->addHours(8);
    
  • Use Case: Business hours, time ranges, or time-based validations.

4. Testing with Frozen Time

  • Scoped Mocking:
    Chronos::setTestNow('2024-01-15 10:00:00');
    // All Chronos instances return this time.
    Chronos::setTestNow(null); // Reset.
    
  • Contextual Mocking (v3.4+):
    Chronos::withTestNow('2024-01-15 10:00:00', fn() => {
        $now = Chronos::now(); // Only affected inside closure.
    });
    

5. Dependency Injection (PSR-20 Clock)

  • Service Container Setup:
    $clock = new Cake\Chronos\ClockFactory('UTC');
    
  • Service Usage:
    class OrderService {
        public function __construct(private Cake\Chronos\ClockInterface $clock) {}
        public function createOrder() {
            return new Order(createdAt: $this->clock->now());
        }
    }
    
  • Benefits: Decouples time logic; mockable in tests.

6. Date Ranges and Periods

  • Iterate Over Dates:
    $period = ChronosDate::today()->period('P1D', 7); // 7 days
    foreach ($period as $date) {
        // Process each date.
    }
    
  • Recurring Events:
    $recurrence = Chronos::now()->nextOccurrenceOf('next Monday');
    

7. Time Zone Handling

  • Shift Time Zones:
    $utcTime = Chronos::now()->shiftTimezone('UTC');
    $localTime = $utcTime->shiftTimezone('America/New_York');
    
  • DST-Safe Arithmetic (v3.5+):
    $elapsed = $start->addElapsedHours(2); // Avoids DST pitfalls.
    

8. Data Conversion

  • To Arrays:
    $data = Chronos::now()->toArray(); // ['year' => 2024, ...]
    
  • To Native PHP:
    $native = Chronos::now()->toDateTimeImmutable();
    

Integration Tips

Laravel-Specific Patterns

  1. Eloquent Models:

    • Cast attributes to Chronos:
      protected $casts = [
          'created_at' => Chronos::class,
      ];
      
    • Accessors:
      public function getFormattedDateAttribute() {
          return $this->created_at->format('Y-m-d');
      }
      
  2. Request Handling:

    • Parse dates from input:
      use Cake\Chronos\Chronos;
      
      $date = Chronos::createFromFormat('Y-m-d', request('event_date'));
      
  3. Jobs/Queues:

    • Use ClockInterface for time-aware jobs:
      class SendReminderJob implements ShouldQueue {
          public function __construct(private ClockInterface $clock) {}
          public function handle() {
              $dueTime = $this->clock->now()->addHours(1);
              // ...
          }
      }
      
  4. API Responses:

    • Serialize Chronos to ISO strings:
      return response()->json(['event' => $event->date->toIso8601String()]);
      
  5. Validation:

    • Custom rules for date ranges:
      use Illuminate\Validation\Rule;
      
      $validator->addRules([
          'end_date' => [
              'required',
              Rule::unique('events')->ignore($event),
              function ($attribute, $value, $fail) {
                  if ($value < Chronos::now()->toDateTimeImmutable()) {
                      $fail('Date must be in the future.');
                  }
              },
          ],
      ]);
      

Gotchas and Tips

Pitfalls

  1. Mutability Missteps:

    • Anti-Pattern:
      $date = Chronos::now();
      $date->modify('+1 day'); // Silent failure (no effect).
      
    • Fix: Reassign the result:
      $date = $date->modify('+1 day');
      
  2. Time Zone Confusion:

    • Chronos::now() uses the server’s default timezone unless specified.
    • Solution: Explicitly set timezone:
      $utcTime = Chronos::now('UTC');
      
  3. DST Transitions:

    • Problem: addHours() may skip/duplicate hours during DST changes.
    • Solution: Use DST-safe methods (v3.5+):
      $safeTime = $start->addElapsedHours(1); // Uses Unix timestamps.
      
  4. TestNow Leaks:

    • Risk: Forgetting to reset setTestNow() can cause flaky tests.
    • Solution: Use withTestNow() for scoped freezing.
  5. DatePeriod Edge Cases:

    • Issue: Zero-interval periods (e.g., P0D) cause infinite loops.
    • Fix: Validate intervals:
      if ($interval === 'P0D') {
          throw new InvalidArgumentException('Invalid interval');
      }
      
  6. Carbon Compatibility:

    • Warning: Chronos does not extend Carbon or DateTime. Avoid mixing APIs.
    • Example: Carbon::parse() won’t work with Chronos instances.

Debugging Tips

  1. Inspect Objects:

    • Use toArray() for debugging:
      dd(Chronos::now()->toArray());
      
    • Check timezone:
      Chronos::now()->getTimezone()->getName();
      
  2. Format Strings:

    • Common formats:
      $date->format('Y-m-d H:i:s'); // ISO-like
      $date->format('D, M j, Y');   // "Mon, Jan 1, 2024"
      
  3. Time Zone Issues:

    • Force UTC for consistency:
      $utcTime = Chronos::now('UTC');
      
  4. Performance:

    • Avoid: Repeated Chronos::now() calls in loops (cache the result).
    • Optimize: Use `Chr
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.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
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
christhompsontldr/laravel-inky
spatie/mailcoach-vapor