laravel-time-craft maintained by omaralalwi
Laravel Time Craft
A simple trait and a set of helper functions that let you effortlessly manage date and time queries in Laravel apps — with pre-built Eloquent scopes and formatting helpers, ready to use out of the box.
Table of Contents
- Features
- Requirements
- Installation
- Configuration
- Usage
- Helper Functions
- Testing
- Changelog
- Contributing
- License
- More Open Source Packages
Features
- Flexible date scopes — filter records by common time frames (today, yesterday, current week, last month, last N days, and more).
- Helper functions — utilities for formatting dates, times, and human-readable "time ago" representations.
- Dynamic field support — every scope can target any date/time column, configurable globally, per model, or per call.
Requirements
- PHP
>= 7.4 - Laravel (Eloquent / Carbon) — the scopes rely on Laravel's query builder and the
now()/today()helpers.
Installation
Install the package via Composer:
composer require omaralalwi/laravel-time-craft
The service provider and the LaravelTimeCraft facade are auto-discovered — no manual registration needed.
(Optional) publish the configuration file:
php artisan vendor:publish --tag=laravel-time-craft
Configuration
Publishing creates config/laravel-time-craft.php:
return [
// The default column used by all scopes when no field is given.
'default_field' => 'created_at',
];
When a scope needs to know which column to filter on, it resolves the field through a three-level fallback (first match wins):
- The field passed directly to the scope call.
- The model's
protected $dateFieldproperty. - The
default_fieldvalue from the config (created_atby default).
See Customizing the Date Field for examples.
Usage
The HasDateTimeScopes Trait
Add the trait to any Eloquent model:
use Illuminate\Database\Eloquent\Model;
use Omaralalwi\LaravelTimeCraft\Traits\HasDateTimeScopes;
class Order extends Model
{
use HasDateTimeScopes;
}
Available Scopes
Heads up: the
*Agoscopes (oneWeekAgo,oneMonthAgo,oneYearAgo) match a single, exact day in the past — not a range. To filter everything since a point in time, use thelastNDaysrange scopes instead.
Day
| Scope | Description | Example |
|---|---|---|
today() |
Records dated today. | Order::today()->get(); |
yesterday() |
Records dated yesterday. | Order::yesterday()->get(); |
Exact day in the past (*Ago)
| Scope | Description | Example |
|---|---|---|
oneWeekAgo() |
Records dated exactly 7 days ago. | Order::oneWeekAgo()->get(); |
oneMonthAgo() |
Records dated exactly 30 days ago. | Order::oneMonthAgo()->get(); |
oneYearAgo() |
Records dated exactly one year ago. | Order::oneYearAgo()->get(); |
Last N days (range, from N days ago until now)
| Scope | Description | Example |
|---|---|---|
last7Days() |
Records from the last 7 days. | Order::last7Days()->get(); |
last10Days() |
Records from the last 10 days. | Order::last10Days()->get(); |
last14Days() |
Records from the last 14 days. | Order::last14Days()->get(); |
last15Days() |
Records from the last 15 days. | Order::last15Days()->get(); |
last21Days() |
Records from the last 21 days. | Order::last21Days()->get(); |
last30Days() |
Records from the last 30 days. | Order::last30Days()->get(); |
lastDays($field = null, $days = 7) |
Records from the last $days days. |
Order::lastDays(null, 12)->get(); |
Argument order for
lastDays: the field comes first, the number of days second. Passnullfor the field to use the default. Example:Order::lastDays(null, 5)->get();filters the last 5 days on the default field;Order::lastDays('updated_at', 5)->get();filters onupdated_at.
Week
| Scope | Description | Example |
|---|---|---|
currentWeek() |
Records in the current calendar week. | Order::currentWeek()->get(); |
lastWeek() |
Records in the previous calendar week. | Order::lastWeek()->get(); |
Month
| Scope | Description | Example |
|---|---|---|
currentMonth() |
Records in the current month. | Order::currentMonth()->get(); |
lastMonth() |
Records in the previous month. | Order::lastMonth()->get(); |
Year
| Scope | Description | Example |
|---|---|---|
currentYear() |
Records in the current year. | Order::currentYear()->get(); |
lastYear() |
Records in the previous year. | Order::lastYear()->get(); |
Custom range
| Scope | Description | Example |
|---|---|---|
betweenDates($start, $end, $field = null) |
Records within an inclusive date range. Accepts Carbon instances or Y-m-d strings. |
Order::betweenDates('2024-01-01', '2024-01-31')->get(); |
Customizing the Date Field
All scopes use created_at by default. You can override the field in three ways:
1. Globally, for every model, via the config file:
'default_field' => 'your_specific_field',
2. Per model, by adding a $dateField property:
class Order extends Model
{
use HasDateTimeScopes;
protected $dateField = 'updated_at';
}
3. Per call, by passing the field name directly:
$lastWeekOrders = Order::lastWeek('updated_at')->get();
A Note on Timezones
Scopes are built on Laravel's now() / today() helpers, so "today", "this week", etc. are evaluated against your application timezone (config('app.timezone')). Make sure your app timezone and the stored timestamps are consistent to get the results you expect.
Helper Functions
These globally-available functions can be used anywhere (Blade files, classes, controllers). Each accepts a \DateTime/Carbon instance or a date string.
| Function | Description | Example | Output |
|---|---|---|---|
formatDate($date) |
Format a date as Y-m-d. |
formatDate($order->created_at) |
2024-08-25 |
formatTime($time) |
Format a time as h:i:s A. |
formatTime($order->created_at) |
10:38:12 PM |
formatDateTime($dateTime) |
Format date + time as Y-m-d H:i:s A. Parses strings too. |
formatDateTime($order->created_at) |
2017-02-15 10:38:12 PM |
getHumanDateTime($createdAt) |
Format a Carbon instance as Y-m-d H:i:s A. Returns the input unchanged if it is not a Carbon instance. |
getHumanDateTime($order->created_at) |
2017-02-15 10:38:12 PM |
formatTimeAgo($dateTime) |
Human-readable "time ago". | formatTimeAgo($order->created_at) |
2 days ago |
startOfDay($date) |
Start of the given day. | startOfDay($order->created_at) |
2024-08-23 00:00:00 |
endOfDay($date) |
End of the given day. | endOfDay($order->created_at) |
2024-08-23 23:59:59 |
isWeekend($date) |
Whether the date falls on Sat/Sun. | isWeekend($order->created_at) |
true / false |
addDays($date, $days) |
Add days, returns Y-m-d. |
addDays($order->created_at, 10) |
2024-09-02 |
subtractDays($date, $days) |
Subtract days, returns Y-m-d. |
subtractDays($order->created_at, 10) |
2024-08-13 |
getHumanDateTimeandformatDateTimeproduce the same format, but differ in input handling:getHumanDateTimeonly formatsCarboninstances (anything else is returned as-is), whileformatDateTimealso parses date strings.
Testing
composer install # install dev dependencies first
composer test # run the PHPUnit suite
composer test-coverage # run with an HTML coverage report in ./coverage
The package uses Orchestra Testbench to boot a minimal Laravel app for testing.
Changelog
Please see CHANGELOG for details on what has changed recently.
Contributing
Contributions are welcome! Please read our contributing guidelines before submitting a pull request.
License
The MIT License (MIT). Please see the License File for more information.
📚 More Open Source Packages
-
Lexi Translate simplify managing translations for multilingual Eloquent models with the power of morph relationships and caching.
-
Gpdf Open Source HTML to PDF converter for PHP & Laravel applications, supports Arabic content out-of-the-box and other languages.
-
Laravel Taxify a set of helper functions and classes to simplify tax (VAT) calculations within Laravel applications.
-
Laravel Deployer Streamlined deployment for Laravel and Node.js apps, with zero-downtime across various environments and branches.
-
Laravel Trash Cleaner clean logs and debug files for debugging packages.
-
Laravel Startkit Laravel Admin Dashboard & Admin Template with a frontend template, for scalable Laravel projects.