Python course menu
Python Date and Time: datetime, timedelta, strftime and Time Zones
Learn Python's datetime module: create dates and times, get today's date, format with strftime, parse strings with strptime, add days with timedelta, calculate differences and ages, and handle time zones.
On this page
Dates and times appear in almost every real program: order dates, deadlines, birthdays, log timestamps. Python's built-in datetime module represents them as proper objects you can compare, format, and do arithmetic with.
The main types#
from datetime import date, datetime, timedeltaCreating dates and times#
d = date(2026, 10, 23)
print(d, d.year, d.month, d.day)
print(d.weekday(), d.isoweekday())2026-10-23 2026 10 23
4 5weekday() counts Monday as 0; isoweekday() counts Monday as 1. Invalid dates are rejected:
date(2026, 2, 30)ValueError: day is out of range for monthmoment = datetime(2026, 10, 23, 14, 30, 5)
print(moment)
print(moment.date(), moment.time())2026-10-23 14:30:05
2026-10-23 14:30:05For the current date and time, use date.today() and datetime.now(). (Their output changes every time you run them, which is why these examples use fixed dates.)
Formatting with strftime#
strftime ("string format time") turns a date into text using format codes:
print(d.strftime("%A, %d %B %Y"))
print(moment.strftime("%d/%m/%Y %I:%M %p"))Friday, 23 October 2026
23/10/2026 02:30 PMParsing text with strptime#
strptime ("string parse time") does the reverse, reading text in a known format:
parsed = datetime.strptime("23-10-2026 09:15", "%d-%m-%Y %H:%M")
print(parsed, type(parsed).__name__)
print(datetime.fromisoformat("2026-10-23T09:15:00"))2026-10-23 09:15:00 datetime
2026-10-23 09:15:00fromisoformat() is the quickest way to read ISO-formatted strings, which is what most APIs and databases produce.
Date arithmetic with timedelta#
Add or subtract a timedelta to move through time:
d = date(2026, 10, 23)
print(d + timedelta(days=30))
print(d - timedelta(weeks=1))2026-11-22
2026-10-16Subtracting two dates gives a timedelta:
start = date(2026, 1, 1)
end = date(2026, 10, 23)
gap = end - start
print(gap, gap.days, type(gap).__name__)295 days, 0:00:00 295 timedeltaDates also compare naturally:
d1 = date(2026, 10, 23)
d2 = date(2026, 12, 25)
print(d1 < d2, (d2 - d1).days)True 63Calculating age#
Subtract the years, then subtract one more if this year's birthday has not happened yet:
birthday = date(2005, 3, 15)
today = date(2026, 10, 23)
age = today.year - birthday.year - ((today.month, today.day) < (birthday.month, birthday.day))
print(age)21The comparison of (month, day) tuples is True (counted as 1) when the birthday is still to come.
Time zones#
A datetime without time zone information is naive. For anything involving users in different places, store times in UTC and convert for display:
from datetime import datetime, timezone
from zoneinfo import ZoneInfo
utc_time = datetime(2026, 10, 23, 9, 0, tzinfo=timezone.utc)
print(utc_time.astimezone(ZoneInfo("Asia/Kolkata")))2026-10-23 14:30:00+05:30zoneinfo (Python 3.9+) knows the world's time zones and their daylight-saving rules. On Windows you may need to pip install tzdata for it to find the time zone database.
Common mistakes#
Practice#
Practice exercise
A loan starts on 23 October 2026 with a payment due every 30 days. Print the first four due dates (counting the start date as payment 1) in the format 23 Oct 2026.
Show hint
Loop for i in range(4) and add timedelta(days=30 * i). Format with "%d %b %Y".
Show solution
from datetime import date, timedelta
start = date(2026, 10, 23)
for i in range(4):
due = start + timedelta(days=30 * i)
print(i + 1, due.strftime("%d %b %Y"))1 23 Oct 2026
2 22 Nov 2026
3 22 Dec 2026
4 21 Jan 2027Because months have 30 or 31 days, "every 30 days" slowly drifts earlier in the month.
Key takeaway#
Finished this lesson?