Laravel - Get data last 24 hours, 1 week or 1 month

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company

Mastering Temporal Queries in Laravel: Getting Data for the Last 24 Hours, Week, or Month

As developers working with databases and time-series data, one of the most common hurdles is accurately defining dynamic date ranges. When you try to pull "the last week" of data, subtle errors in calculating the start and end points can lead to off-by-one errors, missing critical records, or including irrelevant ones. This often boils down to correctly manipulating time intervals using tools like Carbon within the Laravel framework.

The confusion you described—where subtracting a fixed interval seems to behave inconsistently depending on the reference point—is very common. It highlights the need to understand how Eloquent interacts with database timestamps and how Carbon handles temporal arithmetic relative to the current moment.

This post will dive deep into the correct, idiomatic way to handle these time-based queries in Laravel, ensuring your data filtering is precise and efficient.

The Core Principle: Time vs. Date Comparisons

The key to solving this lies in understanding that database queries operate on raw timestamps (usually stored as UTC). When you use Carbon to calculate a cutoff point, you must ensure that the comparison operator (>, <, >=) correctly reflects what "last 24 hours" means relative to Carbon::now().

If we want data created within the last 24 hours, we need to find the exact moment 24 hours ago and select everything after that point.

The Correct Approach Using Carbon Intervals

Your initial attempt using subtraction is fundamentally correct, but relying on manually calculating minutes or seconds can become cumbersome and error-prone. Carbon provides powerful methods that abstract this complexity away, making your code cleaner and more readable.

Instead of calculating Carbon::now() - subMinutes(1440), we should use the built-in interval methods provided by Carbon. This approach is much safer because it directly translates human language into precise time calculations.

Here is how you can correctly implement these dynamic filters:

use Carbon\Carbon;
use App\Models\Deposit; // Assuming your model is named Deposit

// Define the cutoff points dynamically
$now = Carbon::now();

// 1. Last 24 Hours (1 Day)
$twentyFourHoursAgo = $now->copy()->subHours(24);
$getItemsOneDay = Deposit::where('steam_user_id', 0)
    ->where('status', Deposit::STATUS_ACTIVE)
    ->where('created_at', '>=', $twentyFourHoursAgo) // Use >= for inclusive boundary
    ->get();

// 2. Last 7 Days (1 Week)
$oneWeekAgo = $now->copy()->subWeeks(1);
$getItemsOneWeek = Deposit::where('steam_user_id', 0)
    ->where('status', Deposit::STATUS_ACTIVE)
    ->where('created_at', '>=', $oneWeekAgo)
    ->get();

// 3. Last 30 Days (1 Month Approximation)
$oneMonthAgo = $now->copy()->subMonths(1);
$getItemsOneMonth = Deposit::where('steam_user_id', 0)
    ->where('status', Deposit::STATUS_ACTIVE)
    ->where('created_at', '>=', $oneMonthAgo)
    ->get();

// Example usage:
// dd($getItemsOneDay->count());

Why This is Better Practice

  1. Readability: Using methods like subHours(24) or subWeeks(1) clearly communicates the intent of the query to anyone reading your code, which is a core principle in maintainable Laravel applications, as promoted by resources like those found on laravelcompany.com.
  2. Precision: Carbon handles time zone awareness and DST transitions automatically, preventing the kind of off-by-one errors that manual minute calculations can introduce.
  3. Database Efficiency: By comparing created_at directly against calculated timestamp values (which Laravel translates into efficient SQL WHERE clauses), you ensure the database handles the heavy lifting, which is crucial for performance on large datasets.

Moving Towards Eloquent Query Scopes

While the above method works perfectly for ad-hoc queries, if you find yourself repeating this logic across many controllers or services, the next logical step is to encapsulate this logic into Local Query Scopes. This keeps your models clean and ensures that every time you query a Deposit model, the temporal filtering is applied consistently.

For instance, you could add these scopes directly to your Deposit model:

// In Deposit Model
public function scopeRecent(Builder $query, $hours)
{
    $cutoff = Carbon::now()->subHours($hours);
    $query->where('created_at', '>=', $cutoff);
}

Then, querying becomes incredibly simple:

// Using the new scope
$recentDeposits = Deposit::where('steam_user_id', 0)
    ->where('status', Deposit::STATUS_ACTIVE)
    ->recent(24) // This automatically applies the correct date logic!
    ->get();

Conclusion

Mastering temporal data filtering in Laravel is less about complex mathematical subtraction and more about leveraging the robust time manipulation tools provided by Carbon. By favoring explicit interval methods (subHours, subMonths) over manual minute calculations, you write code that is not only functional but also highly readable and resilient to time zone shifts. For building scalable applications, adopting patterns like Eloquent Scopes ensures that these powerful filtering concepts become a standard part of your Laravel development workflow.