LearnContact
Lesson 4420 min read

Date & Time Functions

Learn how to work with dates and times in MySQL using NOW, CURDATE, DATE_FORMAT, DATEDIFF, DATE_ADD, and DATE_SUB.

Introduction

Dates and times show up everywhere in real data — birthdates, order dates, sign-up dates, appointment times. MySQL provides dedicated functions to read the current date and time, format dates for display, measure the gap between two dates, and shift a date forward or backward.

In this lesson we will use a "students" table with a birthdate column, and an "orders" table with an order_date column, to explore NOW(), CURDATE(), CURTIME(), DATE_FORMAT(), DATEDIFF(), DATE_ADD(), and DATE_SUB().

setup.sql
CREATE TABLE students (
    id INT PRIMARY KEY,
    name VARCHAR(50),
    birthdate DATE
);

INSERT INTO students (id, name, birthdate) VALUES
(1, 'Alex', '2008-03-15'),
(2, 'Priya', '2007-11-02');

CREATE TABLE orders (
    id INT PRIMARY KEY,
    student_id INT,
    order_date DATE
);

INSERT INTO orders (id, student_id, order_date) VALUES
(1, 1, '2026-07-10'),
(2, 2, '2026-06-28');
What You Will Learn
  • How to read the current date and time with NOW(), CURDATE(), and CURTIME().
  • How to format a date for display with DATE_FORMAT().
  • How to find the number of days between two dates with DATEDIFF().
  • How to add or subtract time from a date with DATE_ADD() and DATE_SUB().

Why Date Functions Matter

Storing a raw date like 2008-03-15 is useful for the database, but applications usually need to display it more readably, calculate an age from it, or find out how long ago something happened. Date functions let you do all of this directly inside SQL.

NOW(), CURDATE(), CURTIME()

NOW() returns the current date and time together. CURDATE() returns only the current date. CURTIME() returns only the current time.

SELECT NOW() AS current_datetime, CURDATE() AS current_date, CURTIME() AS current_time;
Result
+---------------------+---------------+---------------+
| current_datetime    | current_date  | current_time  |
+---------------------+---------------+---------------+
| 2026-07-26 09:15:42 | 2026-07-26    | 09:15:42      |
+---------------------+---------------+---------------+
Tip

These functions always return the server's current date and time, so their output changes every time you run the query.

DATE_FORMAT()

DATE_FORMAT() converts a date into a custom text format using format specifiers, which is ideal for displaying dates in a friendlier way than the default YYYY-MM-DD.

SELECT name, birthdate, DATE_FORMAT(birthdate, '%W, %M %e, %Y') AS formatted_birthdate
FROM students;
Result
+-------+------------+-------------------------------+
| name  | birthdate  | formatted_birthdate           |
+-------+------------+-------------------------------+
| Alex  | 2008-03-15 | Saturday, March 15, 2008      |
| Priya | 2007-11-02 | Friday, November 2, 2007      |
+-------+------------+-------------------------------+
SpecifierMeaningExample
%YFour-digit year2026
%MFull month nameJuly
%dDay of month, zero-padded05
%eDay of month, no padding5
%WFull weekday nameSunday

DATEDIFF()

DATEDIFF() returns the number of days between two dates. It subtracts the second date from the first, so the order of arguments determines whether the result is positive or negative.

SELECT order_date, DATEDIFF(CURDATE(), order_date) AS days_since_order
FROM orders;
Result
+------------+-------------------+
| order_date | days_since_order  |
+------------+-------------------+
| 2026-07-10 | 16                |
| 2026-06-28 | 28                |
+------------+-------------------+

DATE_ADD() and DATE_SUB()

DATE_ADD() adds a given interval of time to a date, and DATE_SUB() subtracts a given interval of time from a date. Both accept an INTERVAL expression such as INTERVAL 7 DAY or INTERVAL 1 MONTH.

SELECT
    order_date,
    DATE_ADD(order_date, INTERVAL 7 DAY) AS expected_delivery,
    DATE_SUB(order_date, INTERVAL 1 MONTH) AS one_month_before
FROM orders;
Result
+------------+--------------------+-------------------+
| order_date | expected_delivery  | one_month_before  |
+------------+--------------------+-------------------+
| 2026-07-10 | 2026-07-17         | 2026-06-10        |
| 2026-06-28 | 2026-07-05         | 2026-05-28        |
+------------+--------------------+-------------------+

Reference Table

Here is a quick reference for the date and time functions covered in this lesson.

FunctionPurposeExample
NOW()Current date and timeNOW()
CURDATE()Current date onlyCURDATE()
CURTIME()Current time onlyCURTIME()
DATE_FORMAT()Formats a date as textDATE_FORMAT(d, '%M %e, %Y')
DATEDIFF()Days between two datesDATEDIFF(d1, d2)
DATE_ADD()Adds an interval to a dateDATE_ADD(d, INTERVAL 7 DAY)
DATE_SUB()Subtracts an interval from a dateDATE_SUB(d, INTERVAL 1 MONTH)

Worked Example: Age and Days Since Order

Let's calculate each student's current age from their birthdate, and how many days ago their most recent order was placed.

worked_example.sql
SELECT
    s.name,
    DATE_FORMAT(s.birthdate, '%M %e, %Y') AS formatted_birthdate,
    FLOOR(DATEDIFF(CURDATE(), s.birthdate) / 365) AS age,
    DATEDIFF(CURDATE(), o.order_date) AS days_since_order
FROM students s
JOIN orders o ON s.id = o.student_id;
Result
+-------+------------------------------+-----+-------------------+
| name  | formatted_birthdate          | age | days_since_order  |
+-------+------------------------------+-----+-------------------+
| Alex  | March 15, 2008                | 18  | 16                |
| Priya | November 2, 2007              | 18  | 28                |
+-------+------------------------------+-----+-------------------+

This query uses DATEDIFF() to find the total number of days a student has been alive, divides that by 365 and rounds down with FLOOR() to approximate their age in whole years, formats the birthdate nicely with DATE_FORMAT(), and separately calculates how many days have passed since their order.

Note

Dividing days by 365 is a simple approximation for age. For precise age calculations that correctly account for leap years and whether a birthday has occurred yet this year, more advanced date logic (or TIMESTAMPDIFF(YEAR, ...)) is typically used.

Common Mistakes

Avoid These Mistakes
  • Mixing up the argument order in DATEDIFF(), which flips the sign of the result.
  • Forgetting the INTERVAL keyword when using DATE_ADD() or DATE_SUB().
  • Assuming NOW() and CURDATE() return the same thing — NOW() includes the time portion.
  • Hardcoding format strings without checking MySQL's DATE_FORMAT() specifier table.

Best Practices

  • Store dates using the DATE, DATETIME, or TIMESTAMP types, never as plain text.
  • Use DATE_FORMAT() only when displaying dates, and keep raw DATE values for calculations.
  • Prefer DATEDIFF() over manual date subtraction for readability.
  • Use DATE_ADD() and DATE_SUB() instead of manually calculating days in a month or year.

Frequently Asked Questions

What is the difference between NOW() and CURDATE()?

NOW() returns both the date and the time, while CURDATE() returns only the date portion.

Can DATE_ADD() subtract time instead of adding it?

Yes, by using a negative interval, e.g. DATE_ADD(d, INTERVAL -7 DAY), though DATE_SUB() is usually clearer for this.

Does DATEDIFF() count partial days?

No, DATEDIFF() only compares the date portion of each value and always returns a whole number of days.

What interval units does DATE_ADD() support?

Common units include DAY, WEEK, MONTH, YEAR, HOUR, MINUTE, and SECOND, among others.

Key Takeaways

  • NOW() returns the current date and time; CURDATE() and CURTIME() return just one part.
  • DATE_FORMAT() converts a date into a custom display format.
  • DATEDIFF() calculates the number of days between two dates.
  • DATE_ADD() and DATE_SUB() shift a date forward or backward by an interval.
  • These functions can be combined to calculate ages, deadlines, and elapsed time.

Summary

Date and time functions let you read the current date, format stored dates nicely, measure the gap between two dates, and shift dates forward or backward — all directly inside SQL.

In this lesson, you learned NOW(), CURDATE(), CURTIME(), DATE_FORMAT(), DATEDIFF(), DATE_ADD(), and DATE_SUB(), and used them together to calculate a student's age and days since an order. Next, you will learn the CASE statement for inline conditional logic.

Lesson 44 Completed
  • You can read and format dates and times.
  • You can calculate the difference between two dates.
  • You are ready to move on to the CASE statement.
Next Lesson →

CASE Statement