Dates & Times
Due dates, birthdays, train timings, exam schedules, the time an order was placed: almost every real program deals with dates and times. Python's datetime module gives you objects that understand calendars, so you never have to count days in February yourself.
In this lesson you will create dates and times, turn them into text and back, calculate differences with timedelta, and handle time zones correctly with zoneinfo and Asia/Kolkata.
Dates, times and datetimes
The datetime module has a few main types:
| Type | Holds | Example |
|---|---|---|
date | A calendar date | 15 August 2026 |
time | A time of day | 09:30 |
datetime | A date and a time together | 15 August 2026, 09:30 |
timedelta | A length of time | 3 days and 4 hours |
You create a date by giving the year, month and day as numbers, in that order.
from datetime import date, datetime
independence_day = date(2026, 8, 15)
print(independence_day)
print(independence_day.year, independence_day.month, independence_day.day)
print(independence_day.weekday()) # Monday is 0, Sunday is 6
train = datetime(2026, 12, 24, 22, 45)
print(train)
print(train.date(), train.hour, train.minute)2026-08-15 2026 8 15 5 2026-12-24 22:45:00 2026-12-24 22 45
Python prints dates in the international ISO 8601 format, year-month-day. It sorts correctly as text and nobody confuses 04-05 with 05-04.
For the current date and time use date.today() and datetime.now(). Their output changes every time you run the code; here is a sample:
from datetime import date, datetime
print(date.today())
print(datetime.now())2026-10-29 2026-10-29 18:42:07.531204
Formatting dates as text
strftime() (string format time) turns a date into text in any layout. You describe the layout with format codes that start with %.
| Code | Meaning | Example |
|---|---|---|
%d | Day, two digits | 05 |
%m | Month number, two digits | 08 |
%Y | Year, four digits | 2026 |
%B / %b | Month name, full / short | August / Aug |
%A / %a | Weekday name, full / short | Saturday / Sat |
%H / %I | Hour, 24-hour / 12-hour | 22 / 10 |
%M | Minutes | 45 |
%p | AM or PM | PM |
from datetime import datetime
train = datetime(2026, 12, 24, 22, 45)
print(train.strftime("%d/%m/%Y"))
print(train.strftime("%A, %d %B %Y"))
print(train.strftime("Departs at %I:%M %p"))
print(f"Booked for {train:%d %b, %H:%M}")
print(train.isoformat())24/12/2026 Thursday, 24 December 2026 Departs at 10:45 PM Booked for 24 Dec, 22:45 2026-12-24T22:45:00
The fourth line shows that f-strings accept the same codes after a colon. isoformat() gives the standard ISO text, ideal for saving dates in files and JSON.
Reading dates from text
The opposite of strftime() is strptime() (string parse time). You give it the text and the format it is written in, and it returns a datetime. For ISO text, fromisoformat() is simpler.
from datetime import date, datetime
form_value = "26/01/2027"
parade = datetime.strptime(form_value, "%d/%m/%Y")
print(parade)
print(parade.date())
saved = date.fromisoformat("2026-11-14")
print(saved.strftime("%d %B"))
try:
datetime.strptime("31/02/2027", "%d/%m/%Y")
except ValueError as error:
print("Invalid date:", error)2027-01-26 00:00:00 2027-01-26 14 November Invalid date: day 31 must be in range 1..28 for month 2 in year 2027
Python knows February never has 31 days, so strptime() rejects the date with a ValueError. Use this to check dates typed by users.
Date arithmetic with timedelta
A timedelta is a length of time. Add it to a date to move forward, subtract it to move back. Subtracting one date from another gives you a timedelta, and its .days attribute tells you how many days apart they are.
from datetime import date, timedelta
issued = date(2026, 10, 29)
due = issued + timedelta(days=14)
print("Library book due:", due)
republic_day = date(2027, 1, 26)
gap = republic_day - issued
print("Days until Republic Day:", gap.days)
born = date(2004, 3, 18)
today = date(2026, 10, 29)
age = today.year - born.year - ((today.month, today.day) < (born.month, born.day))
print("Age:", age)
print(timedelta(hours=26, minutes=90))Library book due: 2026-11-12 Days until Republic Day: 89 Age: 22 1 day, 3:30:00
The age line subtracts 1 when the birthday has not come yet this year: the comparison (10, 29) < (3, 18) is False, which counts as 0. The last line shows that timedelta tidies up for you: 26 hours and 90 minutes become 1 day, 3 hours and 30 minutes.
Time zones and Asia/Kolkata
A datetime without time zone information is called naive. It cannot say whether 9:00 means 9:00 in Pune or in London. An aware datetime carries a time zone, so Python can convert it correctly. For anything users see across cities or countries, use aware datetimes.
The zoneinfo module provides real time zones by their official names, such as Asia/Kolkata for Indian Standard Time:
from datetime import datetime
from zoneinfo import ZoneInfo
ist = ZoneInfo("Asia/Kolkata")
webinar = datetime(2026, 11, 20, 19, 30, tzinfo=ist)
print(webinar)
print(webinar.astimezone(ZoneInfo("Europe/London")))
print(webinar.astimezone(ZoneInfo("America/New_York")))
print(datetime.now(ist).tzinfo)2026-11-20 19:30:00+05:30 2026-11-20 14:00:00+00:00 2026-11-20 09:00:00-05:00 Asia/Kolkata
astimezone() converts to another zone, including any daylight saving rules that apply on that date. datetime.now(ist) gives the current time in India, wherever your server is.
from datetime import datetime, timedelta, timezone
IST = timezone(timedelta(hours=5, minutes=30), "IST")
server_time = datetime(2026, 10, 29, 6, 0, tzinfo=timezone.utc)
local = server_time.astimezone(IST)
print(local)
print(local.strftime("%d %b %Y, %I:%M %p %Z"))2026-10-29 11:30:00+05:30 29 Oct 2026, 11:30 AM IST
India has no daylight saving time, so a fixed offset is safe for IST. Other countries change their clocks, so for them always use ZoneInfo.
Common mistakes
- Mixing naive and aware datetimes. Comparing them raises
TypeError: can't compare offset-naive and offset-aware datetimes. Make both aware. - Confusing
%mand%M.%mis the month,%Mis minutes. - Writing
date(2026, 08, 15). Numbers with a leading zero are aSyntaxErrorin Python. Writedate(2026, 8, 15). - Storing dates as text like
"15/08/26". Store ISO text (isoformat()) and convert to friendly formats only when displaying.
Key points
date,time,datetimeandtimedeltafrom thedatetimemodule cover most needs.strftime()formats a date as text using codes such as%d,%m,%Y;strptime()parses text back.- Use
isoformat()andfromisoformat()to save and load dates. - Adding a
timedeltamoves a date; subtracting dates gives atimedeltawith.days. - Use aware datetimes with
ZoneInfo("Asia/Kolkata")for real times; on Windows installtzdata.
Exercise
A gym in Lucknow sells memberships of 30, 90 and 365 days. Write a function membership_end(start_text, days) that takes a start date as text in the format DD-MM-YYYY and returns the last day of the membership as text like Sunday, 28 Feb 2027 (a 30-day plan starting on 1 March covers 1 to 30 March). Test it with "29-01-2027" and each plan.
Show solution
from datetime import datetime, timedelta
def membership_end(start_text, days):
start = datetime.strptime(start_text, "%d-%m-%Y").date()
end = start + timedelta(days=days - 1)
return end.strftime("%A, %d %b %Y")
for plan in [30, 90, 365]:
print(plan, "days:", membership_end("29-01-2027", plan))30 days: Saturday, 27 Feb 2027 90 days: Wednesday, 28 Apr 2027 365 days: Friday, 28 Jan 2028
The start day counts as day 1, so we add days - 1. timedelta handles the short month of February and the change of year without any extra code.
Quick Quiz
1. What does date(2027, 1, 26) - date(2026, 10, 29) give?
Subtracting two dates gives a timedelta; read its .days for the number of days.
2. Which format code gives the full month name, such as August?
%B is the full month name; %b is the short name and %m is the month number.
3. Which function turns the text "26/01/2027" into a datetime?
strptime() parses text using a format; strftime() does the opposite.
4. Why might ZoneInfo("Asia/Kolkata") fail on Windows?
zoneinfo needs the IANA time zone database, which Windows does not ship; tzdata provides it.
Learn Python with a mentor
Free lessons get you started. Our Python Programming training adds real projects and code reviews from working developers.
- Project-based learning
- Mentor code reviews
- Free counselling call
