Dates and Times
Birthdays, deadlines, timestamps, opening hours: dates and times are everywhere. Python's built-in datetime module handles them, including the tricky parts like month lengths and leap years.
The main types
The datetime module has a few classes you'll use all the time:
| Type | Holds | Example |
|---|---|---|
date |
year, month, day | 2026-10-05 |
time |
hour, minute, second | 14:30:00 |
datetime |
date and time | 2026-10-05 14:30:00 |
timedelta |
a duration | 3 days, 4 hours |
Today and now
from datetime import date, datetime today = date.today() now = datetime.now() print(today) print(now) print(today.year, today.month, today.day) print(now.hour, now.minute)
Your output depends on when, and in which time zone, you run it.
Going deeper: Time zones optional
datetime.now() gives a naive datetime: it has no idea which time zone it's in (tzinfo is None). That's fine for a program that only runs in one place. Once you deal with users or servers in different places, use aware datetimes, which carry their time zone with them:
from datetime import datetime, timezone, timedelta local = datetime.now() print(local.tzinfo) # None: naive utc_now = datetime.now(timezone.utc) print(utc_now) # ends in +00:00 india = timezone(timedelta(hours=5, minutes=30)) print(utc_now.astimezone(india)) # the same moment, Indian time
A common rule is to store times in UTC and convert to the user's time zone only when you display them.
Fixed offsets like +05:30 don't know about daylight saving time. For real place names such as "Europe/London", use ZoneInfo from the zoneinfo module on your own computer: datetime.now(ZoneInfo("Europe/London")).
Creating a specific date
from datetime import date, datetime moon_landing = date(1969, 7, 20) meeting = datetime(2026, 3, 14, 15, 30) print(moon_landing) print(meeting) print(moon_landing.weekday()) # Monday is 0, Sunday is 6 print(moon_landing.isoweekday()) # Monday is 1, Sunday is 7
Python checks that dates are real:
from datetime import date date(2026, 2, 30)
Formatting dates with strftime
strftime() turns a date into text using format codes:
from datetime import datetime
moment = datetime(2026, 3, 14, 15, 9, 26)
print(moment.strftime("%d/%m/%Y"))
print(moment.strftime("%A, %d %B %Y"))
print(moment.strftime("%I:%M %p"))
print(moment.strftime("%Y-%m-%d %H:%M:%S"))
print(f"{moment:%b %d, %Y}") # format codes work in f-strings tooThe most useful codes:
| Code | Meaning | Example |
|---|---|---|
%Y |
4-digit year | 2026 |
%m |
month number | 03 |
%d |
day of month | 14 |
%B / %b |
month name / short | March / Mar |
%A / %a |
weekday name / short | Saturday / Sat |
%H |
hour (24-hour) | 15 |
%I |
hour (12-hour) | 03 |
%M |
minute | 09 |
%S |
second | 26 |
%p |
AM or PM | PM |
Parsing text into dates with strptime
strptime() does the opposite: it reads a date from text, using the same codes to describe the layout:
from datetime import datetime
text = "25/12/2026 18:30"
christmas_dinner = datetime.strptime(text, "%d/%m/%Y %H:%M")
print(christmas_dinner)
print(christmas_dinner.strftime("%A"))If the text doesn't match the format, you get a ValueError. The ISO format YYYY-MM-DD has a shortcut:
from datetime import date
print(date.fromisoformat("2026-07-04"))Date arithmetic with timedelta
A timedelta is a length of time. Add it to or subtract it from dates:
from datetime import date, timedelta start = date(2026, 1, 28) print(start + timedelta(days=7)) print(start + timedelta(weeks=2)) print(start - timedelta(days=30))
Month lengths and leap years are handled for you. Notice how adding a week to January 28 lands in February.
Subtracting two dates gives a timedelta:
from datetime import date start = date(2026, 1, 1) end = date(2026, 12, 25) gap = end - start print(gap) print(gap.days, "days")
With datetime values, durations can include hours and minutes:
from datetime import datetime check_in = datetime(2026, 5, 1, 14, 0) check_out = datetime(2026, 5, 4, 11, 30) stay = check_out - check_in print(stay) print(stay.total_seconds() / 3600, "hours")
Comparing dates
Dates compare naturally with <, > and ==, and they sort correctly:
from datetime import date
deadline = date(2026, 6, 30)
submitted = date(2026, 7, 2)
if submitted > deadline:
late = (submitted - deadline).days
print(f"Late by {late} days")
dates = [date(2026, 5, 1), date(2025, 12, 31), date(2026, 1, 15)]
print(sorted(dates))Timing your code
To measure how long something takes, subtract two datetime.now() values, or use time.perf_counter():
import time
start = time.perf_counter()
total = sum(i * i for i in range(1_000_000))
elapsed = time.perf_counter() - start
print(f"Result {total:,} in {elapsed:.3f} seconds")Exercises
Exercise 1: Day of the week
Print the day of the week you were born, or of any date you like, as a full name such as Thursday.
from datetime import date birthday = date(2000, 1, 1)
strftime() turns a date into text using format codes.
The code for the full weekday name is %A.
Exercise 2: Due date
A library book is borrowed on 2026-03-25 and is due 21 days later. Print the due date as Due: Wednesday 15 April 2026.
from datetime import date, timedelta borrowed = date(2026, 3, 25)
Add timedelta(days=21) to the borrowed date.
Format it with "Due: %A %d %B %Y".
Exercise 3: Days until an event
Parse the event date from the string and print how many days there are between today and the event: Days to go: 81.
from datetime import date, datetime today = date(2026, 10, 5) event_text = "December 25, 2026"
Parse with datetime.strptime(event_text, "%B %d, %Y") and add .date() to get a date.
Subtract today from the event date and print the .days of the result.
Exercise 4: Age calculator
Write age_on(birth, on_date) that returns a person's age in whole years on a given date. Remember: if their birthday hasn't happened yet that year, subtract one.
from datetime import date
def age_on(birth, on_date):
pass
print(age_on(date(1990, 8, 15), date(2026, 8, 14))) # 35
print(age_on(date(1990, 8, 15), date(2026, 8, 15))) # 36Start with the difference in years: on_date.year - birth.year.
If the birthday hasn't come yet that year, subtract 1. Comparing (month, day) tuples does this neatly.
Date and time tools at a glance
A quick reference for later. The examples use d = date(2026, 3, 15) and from datetime import date, datetime, timedelta. Results marked "e.g." depend on when you run them. The strftime codes, such as %d and %B, are in the table earlier in this lesson.
| Tool | What it does | Example | Result |
|---|---|---|---|
date.today() |
Today's date | date.today() |
e.g. 2026-10-06 |
datetime.now() |
The current date and time | datetime.now() |
e.g. 2026-10-06 14:30:05.123456 |
date(y, m, d) |
A specific date | date(2026, 3, 15) |
2026-03-15 |
datetime(y, m, d, h, min) |
A specific date and time | datetime(2026, 3, 15, 9, 30) |
2026-03-15 09:30:00 |
.year, .month, .day |
The parts of a date | d.month |
3 |
.weekday() |
Day of the week: Monday is 0, Sunday is 6 |
d.weekday() |
6 |
.strftime(format) |
Formats a date as text | d.strftime("%d %b %Y") |
'15 Mar 2026' |
datetime.strptime(text, format) |
Reads a date from text | datetime.strptime("15/03/2026", "%d/%m/%Y") |
2026-03-15 00:00:00 |
.isoformat() |
The standard YYYY-MM-DD text form |
d.isoformat() |
'2026-03-15' |
date.fromisoformat(text) |
Reads a YYYY-MM-DD date |
date.fromisoformat("2026-03-15") |
2026-03-15 |
timedelta(...) |
A length of time: days, hours, minutes, seconds, weeks |
d + timedelta(days=30) |
2026-04-14 |
date2 - date1 |
The time between two dates, as a timedelta |
(date(2026, 12, 25) - d).days |
285 |
.total_seconds() |
A timedelta in seconds |
timedelta(hours=1, minutes=30).total_seconds() |
5400.0 |
.replace(...) |
A copy with some parts changed | d.replace(year=2027) |
2027-03-15 |
time.perf_counter() |
A precise clock for timing code (import time) |
time.perf_counter() |
e.g. 1234.5678 |
Summary
- Import what you need:
from datetime import date, datetime, timedelta. date.today()anddatetime.now()give the current date and time.strftime()formats a date as text, andstrptime()parses text into a date. Both use codes like%Y,%mand%d.- Add or subtract a
timedeltato move dates. Subtracting two dates gives atimedelta. - Dates compare and sort naturally.