Python Dates and Times: datetime, timedelta, strftime, strptime

Last edited Oct 17, 2026 · 4 min read

Python's built-in datetime module handles dates, times, differences between them, and conversion to and from text. Four pieces cover most beginner needs: date and datetime for a moment on the calendar, timedelta for a length of time, strftime() to turn a date into text, and strptime() to turn text into a date. Every example here was run in Python 3.13, and the output shown is what it printed. The module reference was read in October 2026.

1. Making a date

from datetime import date, datetime, timedelta

launch = date(2026, 3, 14)
print(launch)
print(launch.year, launch.month, launch.day)
print(launch.weekday())
print(launch.strftime("%A"))
2026-03-14
2026 3 14
5
Saturday

date(year, month, day) creates a date. date.today() returns the current local date, but these examples use fixed dates so the output never changes. The reference says weekday() returns Monday as 0 and Sunday as 6, so 5 is Saturday.

2. Differences and adding days

Subtracting one date from another gives a timedelta, which the reference defines as a duration. Adding a timedelta to a date moves it forward or backward.

deadline = date(2026, 4, 30)
gap = deadline - launch
print(gap)
print(gap.days)
print(launch + timedelta(days=30))
print(launch - timedelta(weeks=2))
print(launch < deadline)
47 days, 0:00:00
47
2026-04-13
2026-02-28
True

March 14 to April 30 is 47 days. Dates also compare with < and >. A timedelta accepts days, weeks, hours, minutes and seconds as keyword arguments. It does not accept months or years, because their length varies. To move by "one month," you have to decide what that means for your case. Adding 30 days to January 31 lands on March 2, not on the end of February:

print(date(2026, 1, 31) + timedelta(days=30))
2026-03-02

3. Dates with a time of day

datetime adds hours and minutes. Adding a timedelta carries over correctly:

d = datetime(2026, 3, 14, 9, 30)
print(d)
print(d + timedelta(hours=5, minutes=45))
2026-03-14 09:30:00
2026-03-14 15:15:00

4. Date to text: strftime

strftime() takes a format string made of codes. The ones used most often are %Y (four-digit year), %m (month number), %d (day), %H and %M (hour on a 24-hour clock, minute), %B (full month name) and %A (full weekday name). The reference lists the full set.

print(d.strftime("%Y-%m-%d %H:%M"))
print(d.strftime("%B %d, %Y"))
print(d.strftime("%d/%m/%y"))
print(d.isoformat())
2026-03-14 09:30
March 14, 2026
14/03/26
2026-03-14T09:30:00

Note the third line. 14/03/26 is day-first, while 03/14/26 would be month-first. Pick one format on purpose, because readers in different countries read the same digits differently. isoformat() gives the year-month-day standard form.

5. Text to date: fromisoformat and strptime

If your text is already in ISO form, fromisoformat() is the simplest way back:

print(date.fromisoformat("2026-03-14"))
2026-03-14

For any other layout, datetime.strptime(text, format) parses the text using the same codes. The format has to describe the text exactly:

parsed = datetime.strptime("03/14/2026 18:05", "%m/%d/%Y %H:%M")
print(parsed)
print(repr(parsed))
2026-03-14 18:05:00
datetime.datetime(2026, 3, 14, 18, 5)

If the text does not match the format, you get a ValueError, as the reference says:

datetime.strptime("14/03/2026", "%m/%d/%Y")
ValueError: time data '14/03/2026' does not match format '%m/%d/%Y'

Here the "14" cannot be a month, so parsing fails. That is often the first sign that day and month are in the opposite order from what you assumed.

6. days is not the whole duration

A timedelta stores days and seconds separately. The reference warns about a common bug of reading .seconds when the total was intended, and points to total_seconds() instead.

start = datetime(2026, 3, 14, 9, 0)
end = datetime(2026, 3, 16, 17, 30)
span = end - start
print(span)
print(span.days, span.seconds)
print(span.total_seconds())
print(span.total_seconds() / 3600)
2 days, 8:30:00
2 30600
203400.0
56.5

The span is 2 days and 8.5 hours. .seconds shows only the 30,600 seconds (8.5 hours) left over after the 2 days, while total_seconds() gives the whole duration, 203,400 seconds or 56.5 hours.

7. Naive and aware

Everything above is "naive," meaning there is no time zone attached. The reference explains that a naive object cannot tell you which zone it is in; it is up to your program to remember whether it means UTC or local time. If your data crosses time zones, use aware objects, and see the reference for timezone, and the zoneinfo module, which the standard library describes as IANA time zone support. The reference also says datetime.utcnow() is deprecated since Python 3.12 and recommends datetime.now() with a time zone instead.

8. Key takeaways

  • date(y, m, d) and datetime(y, m, d, h, mi) build values; date.today() gives the current local date.
  • Subtracting two dates gives a timedelta; adding a timedelta shifts a date. There is no month or year unit.
  • strftime() formats a date as text; strptime() and fromisoformat() parse text into dates.
  • A text/format mismatch raises ValueError; check day-first versus month-first.
  • Use total_seconds() for the whole duration, not .seconds.
  • Naive values carry no time zone; do not mix them with aware ones.

Sources

  1. Python Software Foundation, datetime, Basic date and time types
  2. Python Software Foundation, zoneinfo, IANA time zone support
CategoriesCoding From Zeropythondatetimedatesbeginners

More on work & tech from other topics