MySQL CURDATE() returns the current date for the MySQL session, without a time component.
SELECT CURDATE();
Current output from MySQL:
| CURDATE() |
|---|
| 2026-09-09 |
The result uses MySQL's date format YYYY-MM-DD, for example 2026-09-09.
CURDATE(), CURRENT_DATE, and CURRENT_DATE() are synonyms in MySQL. They return the current date; NOW() returns both date and time.SELECT CURDATE();
The following forms return the same current date:
SELECT CURDATE();
SELECT CURRENT_DATE;
SELECT CURRENT_DATE();
Use whichever form is clearest in your codebase. CURDATE() is common in MySQL-specific examples.
| Function | Typical result | Contains time? |
|---|---|---|
CURDATE() | 2026-09-09 | No |
NOW() | 2026-09-09 10:52:00 | Yes |
SELECT CURDATE() AS today,
NOW() AS current_date_time;
Use CURDATE() when only the calendar date is needed. Use NOW() when the time of day is also required.
CURDATE() uses the current MySQL session time zone. The database server's date can therefore differ from a visitor's local date when the application and user are in different time zones.
You can inspect the session and global MySQL time-zone settings:
SELECT @@session.time_zone AS session_time_zone,
@@global.time_zone AS global_time_zone;
SELECT CURDATE() - INTERVAL 1 DAY AS yesterday,
CURDATE() AS today,
CURDATE() + INTERVAL 1 DAY AS tomorrow;
| Yesterday | Today | Tomorrow |
|---|---|---|
| 2026-09-08 | 2026-09-09 | 2026-09-10 |
The same arithmetic can be written with DATE_ADD() and DATE_SUB(), but INTERVAL syntax is concise for simple date offsets.
To move the current date one month backward or forward:
SELECT CURDATE() - INTERVAL 1 MONTH AS previous_month_date,
CURDATE() AS today,
CURDATE() + INTERVAL 1 MONTH AS next_month_date;
| Previous month date | Today | Next month date |
|---|---|---|
| 2026-08-09 | 2026-09-09 | 2026-10-09 |
First day:
SELECT DATE_FORMAT(
CURDATE() - INTERVAL 1 MONTH,
'%Y-%m-01'
) AS first_day;
Last day:
SELECT LAST_DAY(
CURDATE() - INTERVAL 1 MONTH
) AS last_day;
Both values together:
SELECT DATE_FORMAT(
CURDATE() - INTERVAL 1 MONTH,
'%Y-%m-01'
) AS first_day,
LAST_DAY(
CURDATE() - INTERVAL 1 MONTH
) AS last_day;
| Previous month first day | Previous month last day |
|---|---|
| 2026-08-01 | 2026-08-31 |
SELECT DATE_FORMAT(
CURDATE(),
'%Y-%m-01'
) AS first_day,
LAST_DAY(CURDATE()) AS last_day;
For filtering records, the first day of this month and the first day of next month are often even more useful than an inclusive last-day boundary.
SELECT DATE_FORMAT(
CURDATE() + INTERVAL 1 MONTH,
'%Y-%m-01'
) AS first_day,
LAST_DAY(
CURDATE() + INTERVAL 1 MONTH
) AS last_day;
For the month after next, change the interval to 2 MONTH.
If date is a MySQL DATE column, an index-friendly current-month filter is:
SELECT id,
date
FROM dt_table
WHERE date >= DATE_FORMAT(
CURDATE(),
'%Y-%m-01'
)
AND date < DATE_FORMAT(
CURDATE() + INTERVAL 1 MONTH,
'%Y-%m-01'
)
ORDER BY date;
This uses a half-open range: from the first day of the current month, inclusive, to the first day of the next month, exclusive.
BETWEEN first_day AND CURDATE(), which means "month-to-date through today," not the full current month. Use the range that matches the actual reporting requirement.For more range examples, see date range queries.
For a DATE column, if you deliberately want records from the first of the month through today:
SELECT id,
date
FROM dt_table
WHERE date >= DATE_FORMAT(
CURDATE(),
'%Y-%m-01'
)
AND date < CURDATE() + INTERVAL 1 DAY
ORDER BY date;
For a DATETIME or TIMESTAMP column, avoid an inclusive final date such as BETWEEN '2026-09-01' AND '2026-09-30', because the upper value represents midnight at the start of the final day unless a time is supplied.
Use a half-open range instead:
SELECT id,
created_at
FROM orders
WHERE created_at >= DATE_FORMAT(
CURDATE(),
'%Y-%m-01'
)
AND created_at < DATE_FORMAT(
CURDATE() + INTERVAL 1 MONTH,
'%Y-%m-01'
)
ORDER BY created_at;
This safely includes every time on every day of the current month.
Use DATE_FORMAT() when a formatted text representation is required:
SELECT DATE_FORMAT(
CURDATE(),
'%d-%m-%Y'
) AS display_date;
09-09-2026 in a VARCHAR column.MySQL can automatically populate date/time columns with the current timestamp when a row is inserted.
CREATE TABLE log_entry (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
message VARCHAR(255) NOT NULL,
PRIMARY KEY (id)
);
See default and automatically updated date/time columns.
A static current-date query does not contain user input, so PDO query() is sufficient:
<?php
$sql="SELECT CURDATE() AS today,
CURDATE() - INTERVAL 1 DAY AS yesterday,
CURDATE() + INTERVAL 1 DAY AS tomorrow";
$stmt=$dbo->query($sql);
$row=$stmt->fetch(PDO::FETCH_ASSOC);
if($row){
echo '<p>Today: '
.htmlspecialchars(
$row['today'],
ENT_QUOTES,
'Windows-1252'
)
.'</p>';
}
See PDO connection. If an application adds external date values, use a prepared statement and bind those values.
When filtering an indexed date or datetime column, prefer direct range comparisons on the column:
WHERE created_at >= '2026-09-01'
AND created_at < '2026-10-01'
rather than wrapping the indexed column in a function:
-- Often less index-friendly for ordinary indexes
WHERE MONTH(created_at) = MONTH(CURDATE())
AND YEAR(created_at) = YEAR(CURDATE())
The boundary expressions can use CURDATE(); the important point is to leave the filtered column itself available for a range lookup.
EXPLAIN when date-range performance matters on large tables.CURDATE() returns only the date. Use NOW() or CURRENT_TIMESTAMP when time is required.
It uses the MySQL session time zone, which may differ from the user's local zone.
An upper boundary such as '2026-09-30' means midnight at the start of that date when converted to a datetime. Prefer >= start AND < next_boundary.
First-of-month through CURDATE() stops at today. A full calendar-month query should normally use the first day of next month as the exclusive upper boundary.
Direct ranges are usually easier for normal indexes to use.
Store actual date/time datatypes and format only for display.
Download CURDATE() SQL examples
It returns the current date for the MySQL session without a time component, normally in YYYY-MM-DD format.
Yes. CURDATE(), CURRENT_DATE, and CURRENT_DATE() are synonyms in MySQL.
CURDATE() returns only the current date. NOW() returns the current date and time.
Use CURDATE() - INTERVAL 1 DAY.
Use CURDATE() + INTERVAL 1 DAY.
Use a half-open range from the first day of this month inclusive to the first day of next month exclusive.
It uses the current MySQL session time zone.
Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.