Date Calculations: DATEADD, DATEDIFF, ISDATE
Add or subtract time with DATEADD, measure gaps with DATEDIFF (boundary counting), and validate messy input with ISDATE.
"The next match is in 10 days." "How many years since Dhoni's debut?" "Is this value even a real date?" These are date calculations and validation.
Definition
DATEADD(part, interval, date) returns a new date obtained by adding
intervalunits ofpart(year, month, day, hour …) todate. A negative interval subtracts.
DATEDIFF(part, start_date, end_date) returns an INT: the number of
partboundaries crossed betweenstart_dateandend_date. Ifend_dateis earlier, the result is negative.
ISDATE(value) returns 1 if the value can be converted to a valid date/time, otherwise 0.
"Boundaries crossed" is the key idea of DATEDIFF: DATEDIFF(year, …) counts how many times you pass 1 January, not how many full 365-day years have passed.
Syntax
sql
DATEADD(part, interval, date) -- interval: positive = add, negative = subtract
DATEDIFF(part, start_date, end_date) -- result = end - start, in whole "part" units
ISDATE(value) -- 1 = valid date, 0 = not a date| Argument | Meaning |
|---|---|
part | the unit: year, quarter, month, week, day, hour, minute, second (no quotes) |
interval | how many units to add (use a negative number to go back) |
start_date, end_date | DATEDIFF subtracts start from end — order matters |
Example — DATEADD
sql
SELECT
DATEADD(year, 2, '2025-08-20') AS plus_2_years,
DATEADD(month, -4, '2025-08-20') AS minus_4_months,
DATEADD(day, 10, '2025-08-20') AS next_match,
DATEADD(hour, 3, '2025-08-20 18:55:45') AS plus_3_hours;| plus_2_years | minus_4_months | next_match | plus_3_hours |
|---|---|---|---|
| 2027-08-20 | 2025-04-20 | 2025-08-30 | 2025-08-20 21:55:45 |
Note: In SQL Server a string literal like
'2025-08-20'is treated asDATETIME, so the results display with a time, e.g.2027-08-20 00:00:00.000. On aDATEcolumn the result stays a plain date.
Example — DATEDIFF
sql
SELECT
DATEDIFF(year, '2008-04-20', '2025-08-20') AS years,
DATEDIFF(month, '2008-04-20', '2025-08-20') AS months,
DATEDIFF(day, '2008-04-20', '2025-08-20') AS days;| years | months | days |
|---|---|---|
| 17 | 208 | 6331 |
How long since Virat Kohli's debut (2008-04-20) on 2025-08-20? 17 year boundaries, 208 month boundaries, 6331 days.
The boundary trap
sql
SELECT
DATEDIFF(year, '2024-12-31', '2025-01-01') AS years,
DATEDIFF(day, '2024-12-31', '2025-01-01') AS days;| years | days |
|---|---|
| 1 | 1 |
Only one day passed, but DATEDIFF(year) says 1 because a year boundary (1 January) was crossed. For an exact age, compare the day too, or use DATEDIFF(day, …) / 365 as an approximation.
Example — next match and days since debut
sql
SELECT
name,
debut,
DATEADD(year, 10, debut) AS ten_year_mark,
DATEDIFF(day, debut, '2025-08-20') AS days_since
FROM player_profiles;| name | debut | ten_year_mark | days_since |
|---|---|---|---|
| Virat Kohli | 2008-04-20 | 2018-04-20 | 6331 |
| Rohit Sharma | 2008-04-22 | 2018-04-22 | 6329 |
| Jos Buttler | 2016-04-09 | 2026-04-09 | 3420 |
| MS Dhoni | 2008-04-19 | 2018-04-19 | 6332 |
| David Warner | 2009-04-18 | 2019-04-18 | 5968 |
| Jasprit Bumrah | 2013-04-06 | 2023-04-06 | 4519 |
Example — ISDATE
sql
SELECT
ISDATE('2025-08-20') AS valid_date,
ISDATE('2025-13-45') AS bad_month,
ISDATE('hello') AS not_a_date;| valid_date | bad_month | not_a_date |
|---|---|---|
| 1 | 0 | 0 |
Use ISDATE to clean dirty data first — for example, to find rows in an imported text column that would break a CAST(... AS DATE): WHERE ISDATE(raw_date) = 0. SQL Server also rejects impossible days such as '2025-02-30' (returns 0); the browser playground's emulation is more lenient on such edge cases.
Common mistakes
- ❌
DATEDIFF(day, '2025-08-20', '2008-04-20')→ a negative number. ✅ Start date first, end date second. - ❌ Using
DATEDIFF(year, birth, today)as an exact age — it can be 1 too high before the birthday. - ❌
debut + 10to add days. ✅DATEADD(day, 10, debut)— explicit and works on every date type. - ❌ Putting quotes around the part:
DATEADD('day', 10, d). ✅DATEADD(day, 10, d).
SQL Server vs MySQL / PostgreSQL
| Task | SQL Server | MySQL | PostgreSQL |
|---|---|---|---|
| Add 10 days | DATEADD(day, 10, d) | DATE_ADD(d, INTERVAL 10 DAY) | d + INTERVAL '10 days' |
| Days between | DATEDIFF(day, d1, d2) | DATEDIFF(d2, d1) (no part, reversed order!) | d2 - d1 |
| Valid date? | ISDATE(v) | — | — (use a safe cast) |
Interview tip
Q: What does DATEDIFF(month, '2025-01-31', '2025-02-01') return?
1 — only one day passed, but a month boundary was crossed. DATEDIFF counts boundaries, not full periods.
Key points to remember
- DATEADD(part, interval, date) adds time; a negative interval subtracts.
- DATEDIFF(part, start, end) returns an INT = end − start in whole units of part.
- DATEDIFF counts boundaries crossed: DATEDIFF(year, '2024-12-31', '2025-01-01') = 1.
- Argument order matters: start date first, end date second, otherwise the result is negative.
- ISDATE(value) returns 1 for a valid date and 0 otherwise — use it to clean data before casting.
- Date parts (year, month, day, hour …) are written without quotes in SQL Server.
Try it yourself
DATEADD forwards and backwards
Runs on a fresh IPL practice database in your browser · edit the query and press Ctrl + Enter
Years, months and days since debut
Runs on a fresh IPL practice database in your browser · edit the query and press Ctrl + Enter
Find invalid dates in imported data
This example runs a small setup step first — click to see it
CREATE TABLE raw_matches (id INT, match_on VARCHAR(20)); INSERT INTO raw_matches VALUES (1, '2025-03-22'), (2, '2025-13-45'), (3, 'TBD'), (4, '2025-04-05');
Runs on a fresh IPL practice database in your browser · edit the query and press Ctrl + Enter
Practice: next match in 7 days
Runs on a fresh IPL practice database in your browser · edit the query and press Ctrl + Enter
Revision Flashcards
Tap a card to flip it and see the answer.
