Working with Dates and Times in Python
Python's datetime module provides date, time, datetime, and timedelta. A datetime is either naive (no timezone information) or aware (it has a tzinfo object that can locate it in time). Do not mix the two models silently.
Dates and times
from datetime import date, time
release_date = date(2026, 10, 6)
start_time = time(14, 30)
print(release_date.isoformat()) # 2026-10-06
print(start_time.isoformat()) # 14:30:00
date.today() and datetime.now() depend on the computer's clock, so examples that need reproducible output should use fixed values.
Creating and formatting datetimes
from datetime import datetime
observed_at = datetime(2026, 10, 11, 9, 30, 45)
print(observed_at.strftime("%Y-%m-%d %H:%M:%S"))
parsed = datetime.strptime("2026-10-11 09:30", "%Y-%m-%d %H:%M")
print(parsed.isoformat()) # 2026-10-11T09:30:00
For machine-readable data, ISO 8601 forms are often clearer than locale-dependent formats. datetime.fromisoformat() parses the formats produced by datetime.isoformat().
from datetime import datetime
value = datetime.fromisoformat("2026-10-11T09:30:00+02:00")
print(value.isoformat())
Date arithmetic
timedelta represents a duration. Subtracting two compatible datetimes also produces a timedelta.
from datetime import datetime, timedelta
start = datetime(2026, 10, 11, 9, 0)
finish = start + timedelta(days=2, hours=3)
print(finish) # 2026-10-13 12:00:00
print(finish - start) # 2 days, 3:00:00
Time zones with zoneinfo
For real-world regions, use the standard-library zoneinfo.ZoneInfo class and IANA zone names. A fixed offset is not a substitute for a region because daylight-saving and historical rules can change its UTC offset.
from datetime import datetime
from zoneinfo import ZoneInfo
berlin = ZoneInfo("Europe/Berlin")
new_york = ZoneInfo("America/New_York")
meeting = datetime(2026, 1, 15, 15, 0, tzinfo=berlin)
print(meeting.isoformat())
print(meeting.astimezone(new_york).isoformat())
zoneinfo reads system timezone data. On systems without an IANA database, install the first-party tzdata package. Store timestamps as aware values when they represent real instants, and convert to a user's region only at the display boundary.
Ambiguous and nonexistent local times
Clock changes can repeat or skip local times. Constructing a local wall time does not validate every transition. When ingesting local timestamps, retain the source zone and define how ambiguous or nonexistent values should be handled instead of guessing.