Every program that schedules, logs or reports needs to represent moments and calendar days.
The module has three main value types:
date(2025, 3, 1)a calendar day:year,month,day.time(14, 30)a time of day:hour,minute,second,microsecond.datetime(2025, 3, 1, 14, 30)both together. It is a subclass ofdate.
Get the current values with date.today() and datetime.now(). For a timestamp you'll store or compare across machines, use datetime.now(timezone.utc) (or datetime.now(UTC), since 3.11), which attaches a time zone; the time zone lessons explain why.
All these objects are immutable and hashable. To change a field, d.replace(day=1) returns a new object. Comparisons (<, ==) work chronologically, and they sort naturally.
Useful methods:
d.weekday()Monday = 0 to Sunday = 6;d.isoweekday()Monday = 1.dt.date()anddt.time()split a datetime;datetime.combine(d, t)joins them.date.fromisoformat("2025-03-01")parses an ISO date.
Invalid values raise ValueError immediately: date(2025, 2, 30) fails, which makes the constructor a handy validator. The supported range is year 1 to 9999.
Import style matters: from datetime import datetime shadows the module name, so datetime.datetime no longer works. Pick one style per file.
Example
from datetime import UTC, date, datetime, time
d = date(2025, 3, 1)
print(d.year, d.month, d.day) # 2025 3 1
print(d.weekday()) # 5 (Saturday)
print(d.replace(day=31)) # 2025-03-31
dt = datetime(2025, 3, 1, 14, 30)
print(dt.date(), dt.time()) # 2025-03-01 14:30:00
print(datetime.combine(d, time(9))) # 2025-03-01 09:00:00
print(date(2024, 12, 31) < d) # True
now = datetime.now(UTC)
print(now.tzinfo) # UTC
try:
date(2025, 2, 30)
except ValueError as e:
print(e) # day is out of range for monthRemember
date,timeanddatetimeare immutable values; usereplacefor changesdatetime.now(UTC)gives a time-zone-aware current timestamp- Invalid dates raise ValueError at construction
Watch out for
- Mixing
import datetimeandfrom datetime import datetimein one file.