Python Dates and Times

Work with dates and times using the datetime module: today's date, formatting with strftime, reading dates with strptime, timedelta arithmetic and time zones.

Lesson 33 of 107Intermediate17 min read

Dates appear in almost every real program. An online shop shows when an order will arrive, a to-do app highlights overdue tasks, a booking system counts the nights in a stay, and a report groups sales by month. Doing these calculations by hand is surprisingly tricky: months have different lengths, leap years add a day, and people write dates in different orders around the world.

Python's built-in datetime module handles all of that. It gives you objects for dates, times and both together, lets you add and subtract periods of time, compare dates, and convert between dates and text in any format you need.

In this lesson you'll get today's date, build specific dates, format them for display, read dates typed by users or stored in files, calculate differences such as "days until" and ages, and learn the basics of time zones.

date, time and datetime

Python
from datetime import date, datetime

today = date.today()            # 2025-03-05
now = datetime.now()            # 2025-03-05 14:32:10.481203
launch = date(2025, 12, 1)      # year, month, day
meeting = datetime(2025, 3, 7, 9, 30)
  • A date holds a year, month and day.
  • A datetime adds hours, minutes, seconds and microseconds.
  • Each part is available as an attribute: today.year, now.hour, launch.month.
  • today.weekday() gives 0 for Monday up to 6 for Sunday.

Printing a date gives the international ISO format, YYYY-MM-DD, which sorts correctly as text and is the safest format for files and databases.

Formatting with strftime

strftime() ("string format time") turns a date into text using format codes:

CodeMeaningExample
%dDay, two digits05
%mMonth number03
%B / %bMonth name, full / shortMarch / Mar
%YFour-digit year2025
%A / %aWeekday, full / shortWednesday / Wed
%H:%M24-hour time14:32
%I:%M %p12-hour time02:32 PM

So today.strftime("%A %d %B %Y") gives Wednesday 05 March 2025. The same codes work inside f-strings: f"{today:%d/%m/%Y}".

Reading dates with strptime

strptime() ("string parse time") does the opposite: it reads text into a datetime, using the same codes to describe the text's layout:

Python
text = "25/12/2025"
christmas = datetime.strptime(text, "%d/%m/%Y")

If the text doesn't match the format, Python raises a ValueError, so wrap user input in try and except. For ISO text, date.fromisoformat("2025-12-25") is simpler.

Date arithmetic with timedelta

A timedelta is a length of time. Add or subtract it to move dates, and subtract two dates to get one:

Python
from datetime import timedelta
due = date.today() + timedelta(days=14)
gap = date(2025, 12, 25) - date(2025, 3, 5)
print(gap.days)    # 295

Dates compare with <, > and ==, so if due < today: checks for overdue items. Timedelta supports days, seconds, minutes, hours and weeks, but not months, because months vary in length.

Timestamps and ISO strings

Many systems store time as a Unix timestamp: the number of seconds since 1 January 1970 UTC. Convert in either direction with timestamp() and fromtimestamp():

Python
from datetime import datetime, timezone

stamp = 1735689600
moment = datetime.fromtimestamp(stamp, tz=timezone.utc)
print(moment)                 # 2025-01-01 00:00:00+00:00
print(int(moment.timestamp()))   # 1735689600

Passing tz=timezone.utc gives a time-zone-aware result. Without it, Python converts to your computer's local time, which differs between machines.

For text, ISO 8601 is the format web APIs and databases expect. moment.isoformat() produces 2025-01-01T00:00:00+00:00, and datetime.fromisoformat() reads it back. From Python 3.11 onward, fromisoformat() also accepts the trailing Z that many APIs use for UTC.

Converting between time zones

A time zone-aware datetime knows its offset from UTC, so it can be converted to any other zone with astimezone(). The zoneinfo module, available from Python 3.9, uses the standard IANA zone names:

Python
from datetime import datetime
from zoneinfo import ZoneInfo

call = datetime(2025, 6, 2, 15, 0, tzinfo=ZoneInfo("Europe/London"))
print(call.astimezone(ZoneInfo("America/New_York")))
# 2025-06-02 10:00:00-04:00

Both zones are on summer time in June, so the gap is five hours. zoneinfo applies daylight-saving rules automatically. On Windows you may need to pip install tzdata to supply the zone database.

Python Dates and Times Syntax

datetime essentials

from datetime import date, datetime, timedelta, timezone
date.today()
datetime.now()
date(2025, 12, 25)
d.strftime("%d %B %Y")
datetime.strptime("25/12/2025", "%d/%m/%Y")
d + timedelta(days=7)
(d2 - d1).days
date.fromisoformat("2025-12-25")
datetime.now(timezone.utc)

Python Dates and Times Summary

  • Import date, datetime and timedelta from the datetime module.
  • date.today() and datetime.now() give the current date and time.
  • strftime() formats dates as text; strptime() reads text into dates.
  • Add a timedelta to move a date; subtract dates to get the gap, and use .days.
  • Store shared times in UTC and convert with zoneinfo for display.

Python Dates and Times Examples

Each example shows the code, the output it produces and what each part does.

Example 1

Due dates for a library

Python
from datetime import date, timedelta

borrowed = date(2025, 3, 5)
due = borrowed + timedelta(weeks=3)
print("Borrowed:", borrowed.strftime("%a %d %b"))
print("Due back:", due.strftime("%A %d %B %Y"))

returned = date(2025, 3, 31)
late = (returned - due).days
if late > 0:
    print(f"Returned {late} days late. Fine: £{late * 0.25:.2f}")
Output
Borrowed: Wed 05 Mar
Due back: Wednesday 26 March 2025
Returned 5 days late. Fine: £1.25
Line-by-line explanation
  1. Line 4Three weeks after 5 March is 26 March.
  2. Line 9Subtracting two dates gives a timedelta, and .days is a whole number.
  3. Lines 10 to 11Dates make conditions like "late" simple to check.
Example 2

Calculating an age

Python
from datetime import date

def age_on(birthday, on_date):
    years = on_date.year - birthday.year
    if (on_date.month, on_date.day) < (birthday.month, birthday.day):
        years -= 1
    return years

born = date(2008, 9, 14)
print(age_on(born, date(2025, 3, 5)))
print(age_on(born, date(2025, 9, 14)))
Output
16
17
Line-by-line explanation
  1. Line 4Start with the difference in years.
  2. Lines 5 to 6If this year's birthday hasn't happened yet, subtract one. Comparing (month, day) tuples checks the month first, then the day.
  3. Line 11On the birthday itself, the age goes up.
Example 3

Reading dates from text

Python
from datetime import datetime

entries = ["2025-03-01 08:15", "2025-03-01 17:45", "not a date"]
times = []
for text in entries:
    try:
        times.append(datetime.strptime(text, "%Y-%m-%d %H:%M"))
    except ValueError:
        print("Skipping:", text)

worked = times[1] - times[0]
print("Hours worked:", worked.total_seconds() / 3600)
Output
Skipping: not a date
Hours worked: 9.5
Line-by-line explanation
  1. Line 7The format string describes the text exactly, including the space and colon.
  2. Lines 8 to 9Text that doesn't match raises ValueError, which we catch.
  3. Lines 11 to 12total_seconds() converts the timedelta into seconds, then divide by 3600 for hours.

Common Python Dates and Times Mistakes

Mixing up %m and %M

Don't
d.strftime("%d/%M/%Y")     # %M is minutes!
Do
d.strftime("%d/%m/%Y")     # %m is the month

Adding months with timedelta

Don't
next_month = today + timedelta(months=1)   # TypeError
Do
next_month = today + timedelta(days=30)    # if 30 days is what you mean

For true calendar months, use a helper such as the dateutil package's relativedelta.

Comparing a date with a string

Don't
if date.today() > "2025-12-25":    # TypeError
Do
if date.today() > date(2025, 12, 25):

Python Dates and Times in Real Projects

Dates in real projects

Booking sites calculate nights between check-in and check-out, subscription services work out renewal dates, log analysis scripts parse timestamps from millions of lines, and reports group results by week or month. Every web framework stores dates in ISO format and UTC, then formats them for each user's language and time zone.

Python Dates and Times FAQ

How do I get the current date and time in Python?

date.today() gives today's date, and datetime.now() gives the local date and time. For a value you will store or share, use datetime.now(timezone.utc), which includes the time zone and can't be misread.

What is the difference between naive and aware datetimes?

A naive datetime has no time zone attached, so 14:00 could be in any country. An aware datetime carries its UTC offset. Python won't compare or subtract a naive and an aware datetime, raising TypeError, which protects you from mixing them by accident.

How do I get the name of the weekday?

Use strftime("%A") for the full name, such as Monday, or "%a" for Mon. weekday() returns a number from 0 (Monday) to 6 (Sunday) if you need to calculate with it. Day names follow the computer's locale settings.

How do I find the last day of a month?

calendar.monthrange(year, month) returns a pair whose second value is the number of days in that month, so calendar.monthrange(2024, 2)[1] is 29. That handles leap years for you.

Why does strptime raise ValueError: time data does not match format?

The format codes must describe the text exactly, including separators. "2025-03-05" needs "%Y-%m-%d", not "%d/%m/%Y". Check for extra spaces, two-digit versus four-digit years (%y versus %Y), and %m (month) versus %M (minute).

Python Dates and Times Exercises

Answer each one and check it instantly. If you get stuck, open the hint before the answer.

Fill in the blankseasy

Complete the code so it prints today's date.

from datetime import date
print(date.())
Predict the outputeasy

What does this print?

from datetime import date
d = date(2025, 7, 4)
print(d.strftime("%d/%m/%Y"))
Predict the outputmedium

What does this print?

from datetime import date
print((date(2025, 3, 10) - date(2025, 2, 28)).days)
Multiple choicemedium

Which call reads "31-01-2025" into a datetime?

Multiple choicehard

Why store times in UTC?

Python Dates and Times Quiz

5 questions to check what you learned.

  1. What does date.today().year give?

    • The current month
    • The date as text
    • The current year as a number
    • The day of the week
  2. What does timedelta(days=7) represent?

    • A specific date
    • A length of time: one week
    • The seventh day of the month
    • Seven o'clock
  3. What does %B show?

    • The short month name
    • The month number
    • The full month name, such as March
    • The weekday
  4. What does strptime raise if the text doesn't match the format?

    • ValueError
    • TypeError
    • KeyError
    • Nothing, it returns None
  5. What does date(2025, 3, 5).weekday() return, given that 5 March 2025 is a Wednesday?

    • 3
    • 4
    • "Wednesday"
    • 2