Dates & Times

Python · Lesson 33 of 56 6 min read Updated

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:

TypeHoldsExample
dateA calendar date15 August 2026
timeA time of day09:30
datetimeA date and a time together15 August 2026, 09:30
timedeltaA length of time3 days and 4 hours

You create a date by giving the year, month and day as numbers, in that order.

PythonRun it yourself
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)
Output
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:

PythonRun it yourself
from datetime import date, datetime

print(date.today())
print(datetime.now())
Output
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 %.

CodeMeaningExample
%dDay, two digits05
%mMonth number, two digits08
%YYear, four digits2026
%B / %bMonth name, full / shortAugust / Aug
%A / %aWeekday name, full / shortSaturday / Sat
%H / %IHour, 24-hour / 12-hour22 / 10
%MMinutes45
%pAM or PMPM
PythonRun it yourself
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())
Output
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.

PythonRun it yourself
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)
Output
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.

PythonRun it yourself
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))
Output
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:

Python
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)
Output
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.

PythonRun it yourself
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"))
Output
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 %m and %M. %m is the month, %M is minutes.
  • Writing date(2026, 08, 15). Numbers with a leading zero are a SyntaxError in Python. Write date(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, datetime and timedelta from the datetime module cover most needs.
  • strftime() formats a date as text using codes such as %d, %m, %Y; strptime() parses text back.
  • Use isoformat() and fromisoformat() to save and load dates.
  • Adding a timedelta moves a date; subtracting dates gives a timedelta with .days.
  • Use aware datetimes with ZoneInfo("Asia/Kolkata") for real times; on Windows install tzdata.

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
Python
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))
Output
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?

2. Which format code gives the full month name, such as August?

3. Which function turns the text "26/01/2027" into a datetime?

4. Why might ZoneInfo("Asia/Kolkata") fail on Windows?

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