today
Returns a Carbon instance for the current date with the time set to 00:00:00.
today($tz = null): CarbonInterfaceParameters
| Parameter | Type | Description |
|---|---|---|
$$tzoptional | DateTimeZone|string|int|BackedEnum|null= null | Timezone used to decide which calendar date it currently is, and carried by the returned instance. Defaults to the application timezone. |
Return value
CarbonInterfaceAn Illuminate\Support\Carbon instance for the current date with the time zeroed to 00:00:00.000000.
Errors
Throws Carbon\Exceptions\InvalidTimeZoneException when the timezone string is not a recognised identifier.
Changelog
- PHP 12.xDeclared as returning CarbonInterface and delegates to Date::today(), so a custom date class registered with Date::use() is honoured.
today() is now() with the time cleared: same calendar date, time 00:00:00.000000. It is the value you want whenever a comparison should be about the day rather than the moment — filtering rows created today, checking whether a due date has passed, or building the lower bound of a date range.
Why not just use now()
A where('due_at', '<=', now()) filter silently excludes anything due later today, because now() carries the current time of day. With today() the boundary sits at midnight and the result stops depending on when the query runs — which also makes it deterministic in tests.
The timezone decides the date
The argument does more than tag the instance: it decides which calendar date it is. At 23:30 UTC, today() and today('Australia/Sydney') are a day apart. If users pick dates in their own timezone, pass that timezone in rather than converting afterwards.
Ranges
For a whole day, pair it with the start of tomorrow — whereBetween('created_at', [today(), today()->addDay()]) is inclusive at both ends, so prefer a half-open range or today()->endOfDay(), remembering that end-of-day carries 999999 microseconds.
Example
When to use it
- Filtering records created since midnight without a hard-coded date string.
- Comparing a due date against the current day, ignoring the time of day.
- Building the lower bound of a report range that runs on a schedule.
Frequently asked questions
What is the difference between today() and now()?
today() returns the current date with the time set to 00:00:00, while now() keeps the current time of day. Use today() when a comparison is about the calendar day, and now() when the exact moment matters.
How do I get tomorrow or yesterday?
Call today()->addDay() and today()->subDay(), which stay at midnight. Carbon also exposes Carbon::tomorrow() and Carbon::yesterday(), which accept the same optional timezone argument.
Does today() use the user's timezone?
No — it uses your application's configured timezone unless you pass one, so pass the user's identifier such as today('Australia/Sydney') when the calendar date should be theirs. The timezone determines which date it is, not just how the value is displayed.
More examples
Scoping a query to the current day
The half-open range [today, tomorrow) catches every row from the day without the double-counting an inclusive whereBetween would risk at the boundary. Using today() instead of now() keeps the query's meaning the same whether it runs at 09:00 or 23:00.
<?php
use App\Models\Order;
// Everything placed since midnight, exclusive of tomorrow.
$todaysOrders = Order::query()
->where('created_at', '>=', today())
->where('created_at', '<', today()->addDay())
->orderBy('created_at')
->get();
// Anything still open whose due date is in the past.
$overdue = Order::query()
->whereNull('completed_at')
->whereDate('due_on', '<', today())
->count();
echo $todaysOrders->count(), ' orders today, ', $overdue, ' overdue', PHP_EOL;Day arithmetic reads cleanly from midnight
Starting from midnight makes diffInDays return a whole number instead of a fraction, because there is no leftover time-of-day to account for. The same calculation from now() would give 30 minus a fraction of a day.
<?php
use Carbon\Carbon;
Carbon::setTestNow('2026-03-14 09:41:07');
$yesterday = today()->subDay();
$weekStart = today()->startOfWeek();
$in30Days = today()->addDays(30);
echo $yesterday->toDateString(), "\n"; // 2026-03-13
echo $weekStart->toDateString(), "\n"; // 2026-03-09
echo $in30Days->toDateString(), "\n"; // 2026-04-13
var_dump(today()->diffInDays($in30Days)); // float(30)
Carbon::setTestNow();A user's day, not the server's
today($zone) picks the calendar date as the user experiences it, then ->utc() converts both boundaries back for a UTC-stored column. Without the timezone argument, users east or west of the server see the wrong day near midnight.
<?php
use App\Models\Entry;
use Illuminate\Http\Request;
public function index(Request $request)
{
$zone = $request->user()->timezone ?? config('app.timezone');
$start = today($zone);
$end = $start->copy()->addDay();
return Entry::query()
->whereBetween('logged_at', [$start->utc(), $end->utc()])
->get();
}
Discussion