Mathew K Analytics

Lesson 3 · Python standard library deep dive

Python datetime Explained: Dates, Times & Time Zones | Standard Library #3

Video three of the twenty-five-part series: datetime, for representing and manipulating dates, times, and timezones. The four core classes, arithmetic with…

⬇ Download notebookOpen in Colab ↗

What you'll learn

Data

No separate download needed — the notebook creates or downloads everything it uses.

📓 Full notebook

Download .ipynb

Python Standard Library Deep-Dive, Video 3: datetime#

  • Video three of the twenty-five-part series: datetime, for representing and manipulating dates, times, and timezones.
  • The four core classes, arithmetic with timedelta, formatting and parsing, and timezone-aware datetimes.
  • Let's get into it.

Part 1: What datetime Offers#

from datetime import date, time, datetime, timedelta
today = date.today()
print(today)
print(type(today))
now = datetime.now()
print(now)
print(type(now))
2026-08-23
<class 'datetime.date'>
2026-08-23 13:41:32.931166
<class 'datetime.datetime'>

Part 2: date Objects#

birthday = date(1995, 6, 15)
print(birthday)
print(birthday.year, birthday.month, birthday.day)
print(birthday.weekday())
print(birthday.isoweekday())
print(birthday.isoformat())
print(birthday.strftime('%A, %B %d, %Y')  )
1995-06-15
1995 6 15
3
4
1995-06-15
Thursday, June 15, 1995

Part 3: time Objects#

meeting_time = time(14, 30, 0)
print(meeting_time)
print(meeting_time.hour, meeting_time.minute, meeting_time.second)
precise_time = time(9, 15, 30, 500000)
print(precise_time)
print(precise_time.microsecond)
14:30:00
14 30 0
09:15:30.500000
500000

Part 4: datetime Objects#

meeting = datetime(2026, 3, 15, 14, 30)
print(meeting)
print(meeting.date())
print(meeting.time())
combined = datetime.combine(date(2026, 3, 15), time(14, 30))
print(combined)
print(combined == meeting)
2026-03-15 14:30:00
2026-03-15
14:30:00
2026-03-15 14:30:00
True

Part 5: timedelta - Arithmetic with Dates#

today = date(2026, 3, 15)
one_week = timedelta(weeks=1)
print(today + one_week)
print(today - one_week)
ninety_days = timedelta(days=90)
print(today + ninety_days)
deadline = date(2026, 6, 1)
remaining = deadline - today
print(remaining)
print(type(remaining))
print(remaining.days)
2026-03-22
2026-03-08
2026-06-13
78 days, 0:00:00
<class 'datetime.timedelta'>
78
duration = timedelta(hours=2, minutes=30)
print(duration)
print(duration.total_seconds())
meeting_start = datetime(2026, 3, 15, 9, 0)
meeting_end = meeting_start + duration
print(meeting_end)
double_duration = duration * 2
print(double_duration)
2:30:00
9000.0
2026-03-15 11:30:00
5:00:00

Part 6: Formatting with strftime()#

moment = datetime(2026, 3, 15, 14, 30, 0)
print(moment.strftime('%Y-%m-%d'))
print(moment.strftime('%m/%d/%Y'))
print(moment.strftime('%B %d, %Y'))
print(moment.strftime('%A'))
print(moment.strftime('%I:%M %p'))
print(moment.strftime('%H:%M:%S'))
print(moment.strftime('%Y-%m-%d %H:%M:%S'))
2026-03-15
03/15/2026
March 15, 2026
Sunday
02:30 PM
14:30:00
2026-03-15 14:30:00

Part 7: Parsing with strptime()#

text = '2026-03-15'
parsed = datetime.strptime(text, '%Y-%m-%d')
print(parsed)
print(type(parsed))
text2 = 'March 15, 2026 2:30 PM'
parsed2 = datetime.strptime(text2, '%B %d, %Y %I:%M %p')
print(parsed2)
try:
    datetime.strptime('15/03/2026', '%Y-%m-%d')
except ValueError as e:
    print(f'Caught: {e}')
2026-03-15 00:00:00
<class 'datetime.datetime'>
2026-03-15 14:30:00
Caught: time data '15/03/2026' does not match format '%Y-%m-%d'

Part 8: ISO Format: isoformat() and fromisoformat()#

moment = datetime(2026, 3, 15, 14, 30, 45)
iso_string = moment.isoformat()
print(iso_string)
print(moment.isoformat(sep=' '))
restored = datetime.fromisoformat(iso_string)
print(restored)
print(restored == moment)
2026-03-15T14:30:45
2026-03-15 14:30:45
2026-03-15 14:30:45
True

Part 9: Comparing Dates and Datetimes#

d1 = date(2026, 1, 1)
d2 = date(2026, 6, 15)
print(d1 < d2)
print(d1 == date(2026, 1, 1))
dates = [date(2026, 6, 1), date(2026, 1, 15), date(2026, 3, 20)]
print(sorted(dates))
print(max(dates))
print(min(dates))
True
True
[datetime.date(2026, 1, 15), datetime.date(2026, 3, 20), datetime.date(2026, 6, 1)]
2026-06-01
2026-01-15

Part 10: Timezones: Naive vs Aware Datetimes#

from datetime import timezone
naive = datetime(2026, 3, 15, 12, 0)
print(naive.tzinfo)
aware = datetime(2026, 3, 15, 12, 0, tzinfo=timezone.utc)
print(aware.tzinfo)
print(aware)
eastern = timezone(timedelta(hours=-5))
aware_eastern = datetime(2026, 3, 15, 12, 0, tzinfo=eastern)
print(aware_eastern)
try:
    naive < aware
except TypeError as e:
    print(f'Caught: {e}')
None
UTC
2026-03-15 12:00:00+00:00
2026-03-15 12:00:00-05:00
Caught: can't compare offset-naive and offset-aware datetimes
from zoneinfo import ZoneInfo
ny_time = datetime(2026, 7, 15, 12, 0, tzinfo=ZoneInfo('America/New_York'))
tokyo_time = ny_time.astimezone(ZoneInfo('Asia/Tokyo'))
print(ny_time)
print(tokyo_time)
print(ny_time == tokyo_time)
utc_now = datetime.now(timezone.utc)
print(utc_now)
2026-07-15 12:00:00-04:00
2026-07-16 01:00:00+09:00
True
2026-08-23 04:26:07.550180+00:00

Part 11: Common Patterns#

def calculate_age(birthdate, on_date=None):
    on_date = on_date or date.today()
    age = on_date.year - birthdate.year
    had_birthday = (on_date.month, on_date.day) >= (birthdate.month, birthdate.day)
    if not had_birthday:
        age -= 1
    return age
birthdate = date(1995, 8, 20)
print(calculate_age(birthdate, date(2026, 8, 19)))
print(calculate_age(birthdate, date(2026, 8, 20)))
30
31
start = date(2026, 3, 1)
end = date(2026, 3, 7)
current = start
date_range = []
while current <= end:
    date_range.append(current)
    current += timedelta(days=1)
print(date_range)
print(len(date_range))
[datetime.date(2026, 3, 1), datetime.date(2026, 3, 2), datetime.date(2026, 3, 3), datetime.date(2026, 3, 4), datetime.date(2026, 3, 5), datetime.date(2026, 3, 6), datetime.date(2026, 3, 7)]
7

Wrap-Up: What You Learned#

  • Four core classes: date, time, datetime, and timedelta.
  • Building and inspecting date and time objects, and combining them into a datetime.
  • timedelta arithmetic: adding, subtracting, scaling, and finding a duration between two dates.
  • Formatting with strftime and parsing with strptime, using shared format codes.
  • ISO 8601 as the standard interchange format, via isoformat and fromisoformat.
  • Comparing and sorting dates chronologically.
  • Naive versus aware datetimes, fixed offsets, zoneinfo, and astimezone.
  • Two real patterns: correct age calculation and generating a date range.
  • That wraps up datetime. Next up: collections, for specialized container types.

Found this useful?

All lessons, notebooks and datasets here are free. If they helped you, a coffee keeps new lessons coming.