Lesson 20 — Date and Time

Working with Dates

Python's datetime module handles dates, times, timedeltas, and timezone-aware computation. It is essential for financial, HR, and scheduling applications.

PYTHON — Basics
from datetime import date, datetime, timedelta
import calendar

# Today and now:
today = date.today()          # date only: 2025-04-01
now   = datetime.now()        # date and time: 2025-04-01 14:30:00

print(today)
print(now)
print(f"Year: {now.year}, Month: {now.month}, Day: {now.day}")
print(f"Hour: {now.hour}, Minute: {now.minute}")
PYTHON — Formatting and parsing
# Formatting — strftime:
print(now.strftime("%A, %d %B %Y"))      # Tuesday, 01 April 2025
print(now.strftime("%Y-%m-%d"))           # 2025-04-01
print(now.strftime("%d/%m/%Y %H:%M"))    # 01/04/2025 14:30

# Parsing a string — strptime:
date_str  = "15/03/1999"
parsed    = datetime.strptime(date_str, "%d/%m/%Y").date()
print(parsed)      # 1999-03-15
print(type(parsed)) # <class 'datetime.date'>

# ISO format:
print(today.isoformat())            # 2025-04-01
birth = date.fromisoformat("1999-03-15")
PYTHON — timedelta
# timedelta — representing durations:
from datetime import timedelta

one_week   = timedelta(weeks=1)
thirty_days = timedelta(days=30)

deadline   = today + thirty_days
print(f"Deadline: {deadline}")

days_until  = (deadline - today).days
print(f"Days until deadline: {days_until}")

# Age in years:
birth_date = date(1999, 3, 15)
today_date = date.today()
age = today_date.year - birth_date.year
if (today_date.month, today_date.day) < (birth_date.month, birth_date.day):
    age -= 1
print(f"Age: {age}")

# Days until end of year:
end_of_year = date(today.year, 12, 31)
days_remaining = (end_of_year - today).days
print(f"Days remaining in {today.year}: {days_remaining}")

Timezone-Aware Datetime

PYTHON — Timezones
from datetime import timezone
from zoneinfo import ZoneInfo  # Python 3.9+

# UTC:
now_utc = datetime.now(timezone.utc)
print(now_utc)

# South Africa Standard Time (SAST = UTC+2, no daylight saving):
sast = ZoneInfo("Africa/Johannesburg")
now_sast = datetime.now(sast)
print(f"SAST: {now_sast.strftime("%Y-%m-%d %H:%M %Z")}")

Practice Task

Your Turn

Write a function learner_report(name, birth_date_str, enrol_date_str, mark) that: parses both date strings (format dd/mm/yyyy), calculates the learner's age, calculates days since enrolment, calculates days until their next birthday, and returns a formatted report string. Test with three learners.

Common Mistakes

  • Mixing date and datetime objects in arithmetic — they are different types.
  • Wrong strftime/strptime codes: %m is month (01-12), %M is minutes. %d is day, %D is locale date.
  • Timezone-naive and timezone-aware datetime cannot be compared or subtracted.
  • Birthday comparison for age — months and days must be compared as a tuple, not separately.

Professional Tip

Always store datetimes as UTC in your database and convert to local time only for display. This prevents a whole class of bugs when systems operate across time zones.

Mini Quiz

Which class represents a duration between two datetimes?