datetime.date
The simplest of the five types: three validated integers. Dates subtract to a timedelta, add whole days from a timedelta, sort and hash — and never mix with datetime.
Common call
date(2026, 9, 29)
Returns
datetime.date(2026, 9, 29)
Replaces
(year, month, day) tuples and "YYYY-MM-DD" strings
Watch out
date + timedelta ignores the hours part
date(yearyear — MINYEAR (1) to MAXYEAR (9999).type: int · required, monthmonth — 1 to 12.type: int · required, dayday — 1 to the number of days in that month (29 February only in leap years).type: int · required)
→ date
Demo
Live evaluation
Build a date and look at it three ways: repr, ISO text, and the weekday (0 = Monday).
Try:
Inputs
yearintyear
monthintmonth
dayintday
Code
from datetime import date d = date(2026, 9, 29) (d, d.isoformat(), d.strftime('%A'))
Result
(datetime.date(2026, 9, 29), '2026-09-29', 'Tuesday')
The checks run in argument order, so year 10000 reports the year before anything else. 2100 is divisible by 4 but also by 100 and not by 400, so it is not a leap year. Going past 9999-12-31 raises OverflowError: date value out of range.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| year | int | yes | MINYEAR (1) to MAXYEAR (9999). |
| month | int | yes | 1 to 12. |
| day | int | yes | 1 to the number of days in that month (29 February only in leap years). |
Return value
date — An immutable, hashable calendar date in the proleptic Gregorian calendar.
Common patterns
Days until an event
date - date → timedelta; .days is the count.
from datetime import date days_left = (date(2026, 12, 25) - date.today()).days
Iterate over a date range
timedelta steps; the end is exclusive here.
from datetime import timedelta day = start while day < end: print(day) day += timedelta(days=1)
Dates as dict keys
Dates are hashable and compare by value.
from collections import Counter per_day = Counter(event.at.date() for event in events)
Examples
1. Construct
from datetime import date
date(2026, 9, 29)
Returns
datetime.date(2026, 9, 29)2. Gap between two dates
from datetime import date
date(2026, 9, 29) - date(2026, 1, 1)
Returns
datetime.timedelta(days=271)3. Adding days crosses months
from datetime import date, timedelta
date(2026, 3, 31) + timedelta(days=30)
Returns
datetime.date(2026, 4, 30)4. Only whole days are used
from datetime import date, timedelta
date(2026, 9, 29) + timedelta(days=1, hours=23)
Returns
datetime.date(2026, 9, 30)5. Sorting and max
from datetime import date
sorted([date(2026, 12, 25), date(2026, 1, 1), date(2026, 9, 29)])
Returns
[datetime.date(2026, 1, 1), datetime.date(2026, 9, 29), datetime.date(2026, 12, 25)]6. str() is ISO
from datetime import date
str(date(2026, 9, 29))
Returns
'2026-09-29'7. A string is not a date
from datetime import date
date('2026-09-29')
Returns
TypeError: 'str' object cannot be interpreted as an integerPitfalls
1. Adding an int
Dates do not know what unit an int would be. Say days explicitly.
date + 1
from datetime import date date(2026, 9, 29) + 1
TypeError: unsupported operand type(s) for +: 'datetime.date' and 'int'
+ timedelta(days=1)
from datetime import date, timedelta date(2026, 9, 29) + timedelta(days=1)
datetime.date(2026, 9, 30)
2. Comparing a date with a datetime
Although datetime subclasses date, ordering them raises TypeError (== is simply False). Convert one side first.
date < datetime
from datetime import date, datetime date(2026, 9, 29) < datetime(2026, 9, 1)
TypeError: '<' not supported between instances of 'datetime.date' and 'datetime.datetime'
.date()
from datetime import date, datetime date(2026, 9, 29) < datetime(2026, 9, 1).date()
False
3. "Same date next year" with 365 days
A year that contains 29 February is 366 days long, so +365 lands a day early. Change the year field instead (and decide what 29 February itself should become).
+ 365 days
from datetime import date, timedelta date(2027, 3, 1) + timedelta(days=365)
datetime.date(2028, 2, 29)
replace(year=…)
from datetime import date date(2027, 3, 1).replace(year=2028)
datetime.date(2028, 3, 1)
When to use
Use it
- Birthdays, due dates, holidays, report days — anything without a time of day
- Grouping timestamps by day (dt.date())
Reach for something else
- A moment in time → datetime (aware)
- Dates before year 1 or after 9999 → store ordinals or use another library
Notes
CPython impl
PyDateTime_Date in Modules/_datetimemodule.c — 4 bytes of data plus a cached hash
Calendar
Proleptic Gregorian: the Gregorian rules applied backwards to year 1; ordinal 1 is 0001-01-01
Arithmetic
date ± timedelta (days only), date - date → timedelta; everything else with an int raises TypeError
Ordering
date vs datetime: == is False and < raises TypeError
FAQ
(later - earlier).days — subtracting dates gives a timedelta, and .days is the whole-day difference (negative if the first date is earlier).