Working with Dates and Times
Use Python's datetime types for dates, clock times, durations, parsing, formatting, and timezone-aware values.
Intermediate
A date, a clock time, a date-and-time value, and a duration represent different things. Python’s datetime module provides date, time, datetime, and timedelta types so you can calculate with calendar values instead of relying on loosely formatted strings.
Choose the right date/time type
Use date for a calendar day, time for a wall-clock time without a date, datetime for a combined value, and timedelta for a difference or duration. Construct values from their components when those components are already available.
Output
Ready to run.
Quick check
Which type represents a calendar day without a clock time?
from datetime import date
print(date(2026, 10, 12).isoformat())
Calculate with durations
Adding or subtracting a timedelta produces a new date or datetime; the original value is unchanged. Subtracting two dates gives a timedelta. A timedelta stores days, seconds, and microseconds, not calendar months or years, so a month should not be treated as a fixed number of days.
Output
Ready to run.
Quick check
What is the result of subtracting one date from another?
from datetime import date
first = date(2026, 10, 12)
second = date(2026, 10, 19)
print((second - first).days)
Parse and format deliberately
Use fromisoformat() for supported ISO 8601 date/time strings, isoformat() for a stable machine-readable representation, strptime() when an input follows a known explicit format, and strftime() for display formatting. Parsing can fail; catch ValueError at the input boundary when malformed user data is expected.
Output
Ready to run.
Quick check
Which method parses text that follows a specified format string?
from datetime import datetime
parsed = datetime.strptime("12/10/2026", "%d/%m/%Y")
print(parsed.date().isoformat())
Distinguish naive and aware datetimes
A naive datetime has no usable timezone offset and cannot identify a unique instant by itself. An aware datetime has timezone information that supplies an offset. Comparing a naive datetime with an aware one raises TypeError. For timestamps that represent real-world instants, prefer aware values and state the timezone explicitly.
Output
Ready to run.
Quick check
What happens when a naive datetime is ordered against an aware datetime?
from datetime import datetime, timezone
naive = datetime(2026, 10, 12)
aware = datetime(2026, 10, 12, tzinfo=timezone.utc)
try:
naive < aware
except TypeError as error:
print(type(error).__name__)
Use UTC and named time zones
datetime.now(timezone.utc) produces an aware current UTC value. For a real geographic timezone, use zoneinfo.ZoneInfo and convert an aware instant with astimezone(). Do not use replace(tzinfo=...) as a conversion: it attaches timezone metadata without converting the clock fields. ZoneInfo uses the system IANA timezone database; platforms without that data may need the first-party tzdata package. Regional offsets can change with daylight-saving rules, so avoid hard-coding a fixed offset for a named place.
Output
Ready to run.
Quick check
Which operation converts an aware datetime to another timezone?
from datetime import datetime, timezone
from zoneinfo import ZoneInfo
instant = datetime(2026, 7, 15, 12, tzinfo=timezone.utc)
paris = instant.astimezone(ZoneInfo("Europe/Paris"))
print(paris.strftime("%H:%M %z"))
Keep calendar rules separate from elapsed time
A calendar day and 24 elapsed hours are not always interchangeable when timezone transitions are involved. For elapsed-time measurements, compare aware instants after converting both to UTC. For a recurring local appointment, preserve its local wall-clock intent and use a named timezone. Repeated or nonexistent local times around daylight-saving changes need an explicit policy; ZoneInfo supports the fold attribute for ambiguous times.
Output
Ready to run.
Key takeaways
- Use date for a calendar day, time for a clock reading, datetime for a combined value, and timedelta for a duration.
- Use ISO parsing/formatting for well-defined interchange and explicit format strings for other input/display formats.
- Prefer aware datetime values for real instants; use timezone.utc and ZoneInfo rather than guessing regional offsets.
- Local wall-clock scheduling and elapsed-time measurement are different problems around timezone transitions.
Quick check recap
Check your understanding by selecting the right type for a calendar value, calculating a date difference, parsing a timestamp, explaining the naive/aware comparison rule, and converting an instant to a named timezone. Finish with the programming challenge and quiz.
Thanks for your feedback.
Mark this learning resource complete to track your learning progress.