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

Laravel Hours Helper Laravel Package

label84/laravel-hours-helper

Generate Laravel Collections of time/date intervals between start and end with a given step. Customize output formatting, handle ranges crossing midnight or spanning days, and exclude specific intervals—ideal for meeting schedulers, calendars, and dropdown time selectors.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require label84/laravel-hours-helper
    

    No additional configuration or service provider registration is required.

  2. First Use Case: Generate a collection of time slots between two times with a specified interval:

    use Label84\HoursHelper\Facades\HoursHelper;
    
    $slots = HoursHelper::create('09:00', '17:00', 30);
    // Returns: ['09:00', '09:30', '10:00', ..., '17:00']
    
  3. Where to Look First:

    • Facade API: HoursHelper is the primary entry point.
    • Test Suite: tests/HoursHelperTest.php demonstrates edge cases (e.g., midnight transitions, exclusions).
    • Examples in README: Quick-start patterns for formatting, exclusions, and multi-day ranges.

Implementation Patterns

Core Workflows

1. Time Slot Dropdowns (UI Integration)

// Generate 15-minute slots for a booking form
$timeSlots = HoursHelper::create('08:00', '18:00', 15, 'H:i');
return view('bookings.create', compact('timeSlots'));
  • Blade Integration:
    <select name="time_slot">
        @foreach($timeSlots as $slot)
            <option>{{ $slot }}</option>
        @endforeach
    </select>
    

2. Excluding Unavailable Slots

// Block lunch breaks (12:00–13:00) and a meeting (14:30–15:00)
$availableSlots = HoursHelper::create(
    '09:00', '17:00', 30,
    'H:i', [
        ['12:00', '12:59'],
        ['14:30', '15:00']
    ]
);

3. Multi-Day Scheduling

// Generate slots for a 2-day event (custom format for APIs)
$eventSlots = HoursHelper::create(
    '2024-01-01 09:00', '2024-01-02 17:00', 60,
    'Y-m-d H:i:s'
);

4. Dynamic Intervals (e.g., for APIs)

// Generate intervals for a range picker API endpoint
$request->validate(['start_time' => 'required', 'end_time' => 'required']);
$intervals = HoursHelper::create(
    $request->start_time,
    $request->end_time,
    $request->interval_minutes ?? 30
);
return response()->json($intervals);

5. Livewire/Inertia Integration

// Livewire component property
public function getTimeSlotsProperty() {
    return HoursHelper::create('08:00', '18:00', 30, 'H:i');
}
  • Inertia: Pass the collection directly to the frontend for dynamic rendering.

Integration Tips

  1. Validation: Combine with Laravel’s validation to ensure start < end and valid intervals:

    use Illuminate\Validation\Rule;
    
    $request->validate([
        'start_time' => ['required', 'date_format:H:i'],
        'end_time' => ['required', 'date_format:H:i', Rule::unique('events')->whereFn(function ($query) use ($request) {
            return $query->where('start_time', '<=', $request->end_time)
                        ->where('end_time', '>=', $request->start_time);
        })],
        'interval' => ['required', 'integer', 'min:1'],
    ]);
    
  2. Caching Static Ranges: Cache frequently used ranges (e.g., business hours) to avoid recomputation:

    $businessHours = Cache::remember('business_hours', now()->addHours(1), function () {
        return HoursHelper::create('09:00', '17:00', 30);
    });
    
  3. Extending for Timezones: Wrap calls with timezone-aware Carbon parsing:

    $slots = HoursHelper::create(
        Carbon::parse($request->start_time, config('app.timezone')),
        Carbon::parse($request->end_time, config('app.timezone')),
        $request->interval
    );
    
  4. Database Integration: Store generated slots as JSON in a database for complex scheduling:

    $event->time_slots = HoursHelper::create(
        $event->start_time,
        $event->end_time,
        $event->interval
    )->toJson();
    
  5. Testing: Mock the facade in unit tests:

    HoursHelper::shouldReceive('create')
               ->once()
               ->with('09:00', '17:00', 30)
               ->andReturn(collect(['09:00', '09:30']));
    

Gotchas and Tips

Pitfalls

  1. Midnight Transitions:

    • Issue: Ranges spanning midnight (e.g., 23:00 to 01:00) may not behave as expected if not explicitly handled.
    • Fix: Use the built-in support:
      $overnightSlots = HoursHelper::create('23:00', '01:00', 60);
      // Returns: ['23:00', '00:00', '01:00']
      
  2. Exclusion Overlaps:

    • Issue: Overlapping exclusion ranges (e.g., ['09:00', '10:00'] and ['09:30', '10:30']) may produce inconsistent results.
    • Fix: Pre-sort and merge exclusion ranges in application code:
      $exclusions = [['09:00', '10:00'], ['09:30', '10:30']];
      $mergedExclusions = $this->mergeOverlappingRanges($exclusions);
      
  3. Timezone Assumptions:

    • Issue: The package defaults to UTC. Localized apps may generate incorrect slots.
    • Fix: Parse inputs with the app’s timezone:
      $slots = HoursHelper::create(
          Carbon::parse($startTime, config('app.timezone')),
          Carbon::parse($endTime, config('app.timezone')),
          $interval
      );
      
  4. Performance with Large Ranges:

    • Issue: Generating thousands of slots (e.g., 00:00 to 23:59 with 1-minute intervals) may impact memory.
    • Fix: Implement lazy loading or chunking:
      $generator = function () use ($start, $end, $interval) {
          $current = Carbon::parse($start);
          while ($current->lte($end)) {
              yield $current->format('H:i');
              $current->addMinutes($interval);
          }
      };
      
  5. Invalid Input Handling:

    • Issue: The package does not validate start < end or positive intervals.
    • Fix: Add application-layer validation:
      if ($start >= $end) {
          throw new \InvalidArgumentException("Start time must be before end time.");
      }
      

Debugging Tips

  1. Inspect Collections: Use dd() to debug generated collections:

    $slots = HoursHelper::create('09:00', '17:00', 30);
    dd($slots->all());
    
  2. Check Exclusion Logic: Verify exclusions by logging intermediate steps:

    $exclusions = [['12:00', '13:00']];
    $slots = HoursHelper::create('09:00', '17:00', 30, 'H:i', $exclusions);
    logger()->debug('Generated slots:', ['slots' => $slots->all()]);
    
  3. Time Format Issues: Ensure the format string matches your expectations (e.g., H:i vs. h:i A):

    // 24-hour format
    HoursHelper::create('09:00', '17:00', 30, 'H:i');
    // 12-hour format with AM/PM
    HoursHelper::create('09:00', '17:00', 30, '
    
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport