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.

datetime classPython 2.3+Live demo
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

NameTypeRequiredDescription
yearintyesMINYEAR (1) to MAXYEAR (9999).
monthintyes1 to 12.
dayintyes1 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 integer

Pitfalls

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).