Python Dates

Tutorial 26 of 65 · pythondeck.com Python course

The datetime module models dates, times, datetimes, durations and time zones. Combine with zoneinfo (3.9+) for IANA time zones and with strftime/strptime for formatting and parsing.

Real software must handle calendars, durations, and time zones—not just "now" timestamps. The datetime module provides naive and aware datetimes, timedelta arithmetic, and formatting. Mixing naive and aware values or ignoring DST causes production incidents around billing, logging, and scheduling.

Store and transmit instants in UTC; convert to local time only for display. Python 3.9+ includes zoneinfo for IANA time zones; older code often uses pytz or dateutil.

date, time, datetime, and timedelta types.

strftime / strptime for human-readable strings (mind locale and format codes).

Aware datetimes: timezone.utc and zoneinfo.ZoneInfo.

Comparing and ordering: never compare naive and aware datetimes.

ISO 8601 strings via .isoformat() and datetime.fromisoformat().

Calendar math: date.replace, timedelta, and third-party relativedelta for months.

Wall-clock time is not linear: daylight saving jumps create ambiguous and nonexistent local times. Schedule recurring local events with a timezone library, not by adding 24 hours to a naive datetime.

For "how long did this take", use time.perf_counter() or datetime.now(timezone.utc) deltas—not time.time() alone for sub-second precision across platforms.

Parsing user-entered dates needs validation and explicit format strings; prefer ISO 8601 in APIs and databases to avoid US vs EU day/month confusion.

Using datetime.now() without a timezone for server-side persistence.

Assuming a day is always 86,400 seconds (DST and leap seconds break that).

Parsing locale-specific strings without a fixed format code.

Using timestamp() on naive datetimes (interpreted as local, platform-dependent).

Storing formatted date strings instead of normalized UTC instants in databases.

Persist UTC-aware datetime or integer epoch seconds; convert for UI only.

Use zoneinfo (or tested equivalents) for named time zones, not fixed offsets alone.

Validate parsed input and reject impossible local times during DST transitions.

Document API date formats as ISO 8601 with explicit offset or Z for UTC.

Re-read the examples below with these ideas in mind; change variable names and inputs to match your own project.

The program below demonstrates now / today. Read the comments on each line, run the code, then change names or values to see how the output shifts.

# Example: Now / today
# Run in the REPL or save as a .py file and execute with python.
from datetime import datetime, date
print(date.today())
print(datetime.now())

This sample walks through format / parse in a small, runnable script. Paste it into the REPL or save it as a .py file before you continue to the next block.

# Example: Format / parse
# Run in the REPL or save as a .py file and execute with python.
from datetime import datetime
fmt = "%Y-%m-%d %H:%M"
s = datetime.now().strftime(fmt)
print(s)
print(datetime.strptime(s, fmt))

Here is a hands-on illustration of timedelta. Follow the inline comments first; only then execute the snippet and compare the result with what you expected.

# Example: Timedelta
# Run in the REPL or save as a .py file and execute with python.
from datetime import date, timedelta
deadline = date.today() + timedelta(days=14)
print(deadline, "is in 2 weeks")

The program below demonstrates datetime math. Read the comments on each line, run the code, then change names or values to see how the output shifts.

# datetime combines date and time; timedelta represents durations
from datetime import datetime, timedelta, timezone  # core types
now = datetime.now(timezone.utc)  # aware UTC timestamp
later = now + timedelta(days=2, hours=3)  # shift forward
print(later - now)  # timedelta difference
print(now.strftime("%Y-%m-%d"))  # formatted date string
parsed = datetime.strptime("2025-06-04", "%Y-%m-%d")  # parse text
print(parsed.year, parsed.month)  # 2025 6
weekday = parsed.isoweekday()  # 1=Monday .. 7=Sunday
print(weekday)  # depends on calendar day

This sample walks through iso timestamps in a small, runnable script. Paste it into the REPL or save it as a .py file before you continue to the next block.

# Store ISO-8601 strings for logs; convert at boundaries
from datetime import datetime, timezone  # reuse imports
stamp = datetime(2025, 6, 4, 12, 30, tzinfo=timezone.utc)  # fixed instant
iso = stamp.isoformat()  # serialize to standard text
print(iso)  # includes timezone offset
roundtrip = datetime.fromisoformat(iso.replace("Z", "+00:00"))  # parse back
print(roundtrip == stamp)  # True when tz-aware
epoch = stamp.timestamp()  # seconds since 1970-01-01 UTC
back = datetime.fromtimestamp(epoch, tz=timezone.utc)  # reconstruct
print(back.date())  # date component only

« Python Modules All tutorials Python Math »