Date & Time Functions
Work with dates using YEAR, MONTH, DATE_ADD, DATEDIFF, and more.
Introduction to Date Functions
Dates and times are crucial in databases - order dates, employee hire dates, event timestamps, deadlines, and more. But working with dates can be tricky:
- Calculate age from birthdate
- Find records from last month
- Extract year or day of week
- Add or subtract days/months
- Format dates for display
Date functions in SQL make these operations simple and powerful!
Built-in SQL functions that operate on DATE, DATETIME, and TIMESTAMP values. They extract parts of dates, perform calculations, format output, and handle time zones - essential for any time-based data analysis.
Why use date functions?
- Calculate time differences (days between orders)
- Filter by time periods (last quarter, this year)
- Extract components (year, month, day, weekday)
- Format dates for reports
- Handle time zones
- Schedule and track events
Let's work with an orders table:
order_id | customer_name | order_date | ship_date | total |
|---|---|---|---|---|
| 1 | Alice Smith | 2024-01-15 | 2024-01-18 | 299.99 |
| 2 | Bob Johnson | 2024-02-20 | 2024-02-22 | 150.00 |
| 3 | Carol White | 2024-03-10 | 2024-03-15 | 450.50 |
| 4 | David Brown | 2024-03-25 | 2024-03-28 | 89.99 |
CURRENT_DATE, CURRENT_TIME, NOW() - Current Date/Time
Get the current date and time from the database server:
-- Get current date and time
SELECT
CURRENT_DATE AS today,
CURRENT_TIME AS right_now_time,
NOW() AS right_now_datetime,
CURRENT_TIMESTAMP AS timestamp_now;-- Find orders placed today
SELECT
order_id,
customer_name,
order_date
FROM orders
WHERE order_date = CURRENT_DATE;Use cases:
- Record when records are created:
created_at TIMESTAMP DEFAULT NOW() - Find recent activity
- Calculate current age from birthdate
YEAR(), MONTH(), DAY() - Extracting Date Parts
Extract specific components from dates:
-- Extract year, month, and day
SELECT
order_id,
order_date,
YEAR(order_date) AS year,
MONTH(order_date) AS month,
DAY(order_date) AS day
FROM orders;-- Find orders from March 2024
SELECT
order_id,
customer_name,
order_date
FROM orders
WHERE YEAR(order_date) = 2024
AND MONTH(order_date) = 3;Additional extraction functions:
HOUR(datetime)- extract hour (0-23)MINUTE(datetime)- extract minute (0-59)SECOND(datetime)- extract second (0-59)QUARTER(date)- quarter of year (1-4)WEEK(date)- week number of year
DAYNAME() and MONTHNAME() - Text Names
Get the name of the day or month:
-- Get day and month names
SELECT
order_id,
order_date,
DAYNAME(order_date) AS day_of_week,
MONTHNAME(order_date) AS month_name
FROM orders;-- Find orders placed on weekends
SELECT
order_id,
customer_name,
order_date,
DAYNAME(order_date) AS day
FROM orders
WHERE DAYNAME(order_date) IN ('Saturday', 'Sunday');Alternative: DAYOFWEEK() Returns a number (1=Sunday, 2=Monday, ..., 7=Saturday):
WHERE DAYOFWEEK(order_date) IN (1, 7) -- Weekends
DATE_ADD() and DATE_SUB() - Adding/Subtracting Time
Add or subtract intervals from dates:
Syntax:
DATE_ADD(date, INTERVAL value unit)
DATE_SUB(date, INTERVAL value unit)
Common units: DAY, MONTH, YEAR, HOUR, MINUTE, WEEK
-- Add time to dates
SELECT
order_id,
order_date,
DATE_ADD(order_date, INTERVAL 7 DAY) AS week_later,
DATE_ADD(order_date, INTERVAL 1 MONTH) AS month_later,
DATE_ADD(order_date, INTERVAL 1 YEAR) AS year_later
FROM orders
WHERE order_id = 1;-- Subtract time from dates
SELECT
order_id,
order_date,
DATE_SUB(order_date, INTERVAL 30 DAY) AS thirty_days_ago,
DATE_SUB(order_date, INTERVAL 3 MONTH) AS three_months_ago
FROM orders
WHERE order_id = 3;-- Find orders from the last 30 days
SELECT
order_id,
customer_name,
order_date
FROM orders
WHERE order_date >= DATE_SUB(CURRENT_DATE, INTERVAL 30 DAY);Alternative syntax (some databases):
order_date + INTERVAL 7 DAY
order_date - INTERVAL 1 MONTH
DATEDIFF() - Calculate Days Between Dates
Calculate the difference in days between two dates:
Syntax: DATEDIFF(date1, date2)
Returns: date1 - date2 in days
-- Calculate shipping time (days between order and ship)
SELECT
order_id,
customer_name,
order_date,
ship_date,
DATEDIFF(ship_date, order_date) AS shipping_days
FROM orders;-- Calculate days since order
SELECT
order_id,
customer_name,
order_date,
DATEDIFF(CURRENT_DATE, order_date) AS days_since_order
FROM orders;-- Find orders with slow shipping (>3 days)
SELECT
order_id,
customer_name,
DATEDIFF(ship_date, order_date) AS shipping_days
FROM orders
WHERE DATEDIFF(ship_date, order_date) > 3;TIMESTAMPDIFF() - Difference in Any Unit
Calculate difference in specific units (days, months, years, hours):
Syntax: TIMESTAMPDIFF(unit, start_date, end_date)
Units: SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, QUARTER, YEAR
-- Calculate age from birthdate
SELECT
'Alice' AS name,
'1990-05-15' AS birthdate,
TIMESTAMPDIFF(YEAR, '1990-05-15', CURRENT_DATE) AS age_years,
TIMESTAMPDIFF(MONTH, '1990-05-15', CURRENT_DATE) AS age_months,
TIMESTAMPDIFF(DAY, '1990-05-15', CURRENT_DATE) AS age_days;-- Calculate months between dates
SELECT
order_id,
order_date,
TIMESTAMPDIFF(MONTH, order_date, CURRENT_DATE) AS months_ago,
TIMESTAMPDIFF(WEEK, order_date, CURRENT_DATE) AS weeks_ago
FROM orders;DATE_FORMAT() - Formatting Dates
Format dates for display using format codes:
Common format codes:
%Y- 4-digit year (2024)%y- 2-digit year (24)%M- full month name (March)%m- 2-digit month (03)%D- day with suffix (15th)%d- 2-digit day (15)%W- weekday name (Monday)%H- hour 24h (14)%i- minutes (35)
-- Format dates in various ways
SELECT
order_id,
order_date,
DATE_FORMAT(order_date, '%M %d, %Y') AS format1,
DATE_FORMAT(order_date, '%W, %D %M %Y') AS format2,
DATE_FORMAT(order_date, '%m/%d/%y') AS format3,
DATE_FORMAT(order_date, '%Y-%m-%d') AS iso_format
FROM orders;Note: PostgreSQL uses TO_CHAR() instead:
TO_CHAR(order_date, 'Month DD, YYYY')
Common Mistakes to Avoid
Don't make these mistakes:
-
Comparing dates with strings incorrectly: ❌
WHERE order_date = '15-01-2024'(wrong format)- Always use ISO format:
'2024-01-15'(YYYY-MM-DD)
-
Using functions in WHERE with indexes: ⚠️
WHERE YEAR(order_date) = 2024can't use indexes efficiently- Better:
WHERE order_date >= '2024-01-01' AND order_date < '2025-01-01'
-
Forgetting about time zones: ⚠️
NOW()uses server timezone- Consider storing timestamps in UTC
-
Wrong DATEDIFF argument order: ❌
DATEDIFF(date1, date2)returns date1 - date2- Be consistent with which is first
-
Mixing DATE and DATETIME comparisons: ❌
WHERE datetime_col = '2024-01-15'won't match times other than 00:00:00- Use
DATE(datetime_col) = '2024-01-15'or range comparison
-
Not handling NULLs: ❌
- Date functions on NULL return NULL
- Check for NULL before applying functions
-
Assuming all years have 365 days: ❌
- Leap years have 366 days
- Use DATE_ADD/DATE_SUB instead of manual calculations
Key Takeaways
What you learned:
✅ CURRENT_DATE, NOW() - get current date/time
✅ YEAR(), MONTH(), DAY() - extract date components
✅ DAYNAME(), MONTHNAME() - get text names
✅ DATE_ADD(), DATE_SUB() - add/subtract intervals
✅ DATEDIFF() - calculate days between dates
✅ TIMESTAMPDIFF() - calculate difference in any unit
✅ DATE_FORMAT() - format dates for display
✅ Date ranges with BETWEEN and comparisons
Real-world applications:
- Calculate ages and tenure
- Track time between events (order to ship)
- Filter by time periods (last month, this quarter)
- Format dates for reports
- Identify trends by weekday/month
- Schedule reminders (birthdays, renewals)
Practice Exercise: Using the orders table:
- Find all orders from the last 30 days
- Calculate average shipping days per month
- List orders placed on Mondays
- Find the oldest order and how many days ago it was
- Group orders by quarter and count them
- Format order dates as "Monday, March 25th, 2024"
- Find orders where shipping took more than 3 days
- Calculate how many months ago each order was placed