label84/laravel-hours-helper
Generate Laravel collections of time/date intervals for any period: build dropdown-ready schedules with custom formatting, exclusions, support for past-midnight ranges, and multi-day spans. Simple facade API to create evenly spaced slots like 08:00–09:30 every 30 minutes.
Install via Composer:
composer require label84/laravel-hours-helper
First Use Case: Generate a time dropdown for appointment scheduling.
use Label84\HoursHelper\Facades\HoursHelper;
// Basic 30-minute intervals between 8 AM and 9:30 AM
$slots = HoursHelper::create('08:00', '09:30', 30);
// Pass to Blade for a dropdown
return view('appointments.create', ['slots' => $slots]);
Key Files to Review:
vendor/label84/laravel-hours-helper/src/Facades/HoursHelper.php (API reference)tests/HoursHelperTest.php (edge cases and examples)Generate Slots:
$slots = HoursHelper::create(
start: '09:00',
end: '17:00',
interval: 60, // minutes
format: 'g:i A',
exclusions: [['12:00', '13:00']] // lunch break
);
Blade Integration:
<select name="appointment_time">
@foreach($slots as $slot)
<option>{{ $slot }}</option>
@endforeach
</select>
API Response:
return response()->json(['slots' => $slots]);
$excludedRanges = DB::table('blocked_slots')
->where('user_id', auth()->id())
->pluck('range');
$slots = HoursHelper::create('08:00', '18:00', 30, 'H:i', $excludedRanges);
// Generate slots for a 3-day event
$slots = HoursHelper::create(
'2024-06-01 09:00',
'2024-06-03 17:00',
60,
'Y-m-d g:i A'
);
public function mount() {
$this->slots = HoursHelper::create('08:00', '18:00', 30);
}
public function updateExclusions($exclusions) {
$this->slots = HoursHelper::create('08:00', '18:00', 30, 'H:i', $exclusions);
}
// Dispatch a job for each slot
foreach (HoursHelper::create('09:00', '17:00', 60) as $slot) {
SendReminderJob::dispatch($slot);
}
$slots = HoursHelper::create('08:00', '18:00', 30)
->map(fn ($time) => Carbon::parse($time)->format('h \o\'clock'));
Timezone Assumptions:
$slots = HoursHelper::create('08:00', '18:00', 30, 'H:i', [], 'America/New_York');
Exclusion Overlaps:
[09:00,10:00] and [09:30,10:30]) may produce unexpected gaps. Normalize exclusions first:
$normalizedExclusions = array_merge(...$exclusions);
Past-Midnight Edge Cases:
$slots = HoursHelper::create('23:00', '01:00', 60); // Includes '00:00'
Large Ranges:
$slots->chunk(1000); // Process in batches
Invalid Inputs:
$start = Carbon::parse($request->start)->format('H:i');
Verify Output:
dd($slots->all()); // Inspect raw values
Check Exclusions:
$slots->filter(fn ($time) => !collect($exclusions)->contains(fn ($range) => ...));
Performance Profiling:
Custom Interval Logic:
// app/Providers/HoursHelperServiceProvider.php
public function register() {
$this->app->extend('hours-helper', function ($helper) {
$helper->addCustomInterval('custom', function ($start, $end, $step) {
// Implement logic
});
return $helper;
});
}
Database Backed Exclusions:
HoursHelper::macro('withDatabaseExclusions', function ($query) {
$exclusions = $query->get()->pluck('range');
return $this->create($this->start, $this->end, $this->interval, $this->format, $exclusions);
});
Timezone-Aware Helper:
HoursHelper::macro('inTimezone', function ($timezone) {
return $this->setTimezone($timezone);
});
Facade vs. Class:
// Facade (Blade)
@php
$slots = \Label84\HoursHelper\Facades\HoursHelper::create(...);
@endphp
// Class (Tests)
$helper = new \Label84\HoursHelper\HoursHelper();
$slots = $helper->create(...);
Format Overrides:
format parameter uses PHP’s DateTime::format(). Test with:
$slots = HoursHelper::create('08:00', '18:00', 30, 'g:i A'); // '8:00 AM'
Interval Units:
15 (15-minute slots)30 (30-minute slots)60 (hourly slots)How can I help you explore Laravel packages today?