Python
DateTime
Date Difference
Python Programming
Time Calculation

Difference between two dates in Python

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

To calculate the difference between two dates in Python, subtract one datetime.date or datetime.datetime object from another. The result is a timedelta object that stores the difference in days, seconds, and microseconds. Access the total difference in days with .days or in seconds with .total_seconds(). For more human-readable differences (years, months), use the dateutil.relativedelta module. The built-in datetime module handles most use cases without external dependencies.

Basic Date Difference

python
1from datetime import date
2
3date1 = date(2025, 1, 1)
4date2 = date(2025, 3, 15)
5
6diff = date2 - date1
7print(diff)           # 73 days, 0:00:00
8print(diff.days)      # 73
9print(type(diff))     # <class 'datetime.timedelta'>
10
11# Absolute difference (order doesn't matter)
12diff2 = date1 - date2
13print(diff2.days)     # -73
14print(abs(diff2).days)  # 73

Subtracting two date objects returns a timedelta. The .days attribute gives the difference as an integer number of days.

DateTime Difference (With Time)

python
1from datetime import datetime
2
3dt1 = datetime(2025, 1, 1, 8, 0, 0)
4dt2 = datetime(2025, 1, 3, 14, 30, 45)
5
6diff = dt2 - dt1
7print(diff)                    # 2 days, 6:30:45
8print(diff.days)               # 2
9print(diff.seconds)            # 23445 (6*3600 + 30*60 + 45)
10print(diff.total_seconds())    # 196245.0 (total including days)
11
12# Convert to hours, minutes
13total_hours = diff.total_seconds() / 3600
14print(f"{total_hours:.1f} hours")  # 54.5 hours
15
16total_minutes = diff.total_seconds() / 60
17print(f"{total_minutes:.0f} minutes")  # 3271 minutes

For datetime objects, the timedelta includes both days and time components. Use .total_seconds() to get the complete difference as a single number, including the days portion.

Parsing Date Strings

python
1from datetime import datetime
2
3# Parse date strings with strptime
4date_str1 = "2025-01-15"
5date_str2 = "2025-03-20"
6
7dt1 = datetime.strptime(date_str1, "%Y-%m-%d")
8dt2 = datetime.strptime(date_str2, "%Y-%m-%d")
9
10diff = dt2 - dt1
11print(f"Difference: {diff.days} days")  # 64 days
12
13# Other common formats
14datetime.strptime("15/01/2025", "%d/%m/%Y")
15datetime.strptime("Jan 15, 2025", "%b %d, %Y")
16datetime.strptime("2025-01-15 14:30:00", "%Y-%m-%d %H:%M:%S")

strptime converts a date string to a datetime object using format codes (%Y = year, %m = month, %d = day, %H = hour, %M = minute, %S = second).

Difference in Years and Months (dateutil)

python
1from datetime import date
2from dateutil.relativedelta import relativedelta
3
4date1 = date(2020, 3, 15)
5date2 = date(2025, 7, 22)
6
7diff = relativedelta(date2, date1)
8print(f"{diff.years} years, {diff.months} months, {diff.days} days")
9# 5 years, 4 months, 7 days
10
11# Calculate age
12birthday = date(1990, 5, 20)
13today = date.today()
14age = relativedelta(today, birthday)
15print(f"Age: {age.years} years")

The built-in timedelta only stores days and seconds — it cannot express differences in months or years (because months have variable lengths). dateutil.relativedelta handles calendar-aware differences.

Working with Timezones

python
1from datetime import datetime, timezone, timedelta
2
3# UTC datetime
4utc_time = datetime(2025, 1, 15, 12, 0, 0, tzinfo=timezone.utc)
5
6# Eastern time (UTC-5)
7eastern = timezone(timedelta(hours=-5))
8eastern_time = datetime(2025, 1, 15, 7, 0, 0, tzinfo=eastern)
9
10# Difference accounts for timezone
11diff = utc_time - eastern_time
12print(diff)  # 0:00:00 (same moment in time)
13
14# Using zoneinfo (Python 3.9+)
15from zoneinfo import ZoneInfo
16
17tokyo = datetime(2025, 1, 15, 21, 0, 0, tzinfo=ZoneInfo("Asia/Tokyo"))
18london = datetime(2025, 1, 15, 12, 0, 0, tzinfo=ZoneInfo("Europe/London"))
19
20diff = tokyo - london
21print(diff)  # 0:00:00 (same moment: Tokyo is UTC+9, London is UTC+0)

When both datetimes are timezone-aware, subtraction correctly accounts for the UTC offset. Mixing timezone-aware and naive datetimes raises TypeError.

Business Days Difference

python
1import numpy as np
2from datetime import date
3
4date1 = date(2025, 1, 6)   # Monday
5date2 = date(2025, 1, 17)  # Friday
6
7# numpy.busday_count counts weekdays between two dates
8business_days = np.busday_count(date1, date2)
9print(f"Business days: {business_days}")  # 9
10
11# Excluding holidays
12holidays = ['2025-01-13']  # MLK Day
13business_days = np.busday_count(date1, date2, holidays=holidays)
14print(f"Business days (excl holidays): {business_days}")  # 8

Common Date Calculations

python
1from datetime import date, timedelta
2
3today = date.today()
4
5# Days until a future date
6target = date(2025, 12, 31)
7days_left = (target - today).days
8print(f"Days until end of year: {days_left}")
9
10# Days since a past date
11start = date(2025, 1, 1)
12days_elapsed = (today - start).days
13print(f"Days since Jan 1: {days_elapsed}")
14
15# Add/subtract days
16tomorrow = today + timedelta(days=1)
17last_week = today - timedelta(weeks=1)
18in_90_days = today + timedelta(days=90)
19
20# Check if a date is within a range
21deadline = date(2025, 6, 30)
22is_overdue = today > deadline
23days_until = max(0, (deadline - today).days)

Formatting the Difference

python
1from datetime import datetime
2
3dt1 = datetime(2025, 1, 1)
4dt2 = datetime(2025, 3, 15, 14, 30)
5
6diff = dt2 - dt1
7
8# Custom formatting
9total_seconds = int(diff.total_seconds())
10days = diff.days
11hours = (total_seconds % 86400) // 3600
12minutes = (total_seconds % 3600) // 60
13seconds = total_seconds % 60
14
15print(f"{days}d {hours}h {minutes}m {seconds}s")  # 73d 14h 30m 0s
16
17# Human-readable function
18def format_timedelta(td):
19    days = td.days
20    hours, remainder = divmod(td.seconds, 3600)
21    minutes, seconds = divmod(remainder, 60)
22
23    parts = []
24    if days: parts.append(f"{days} day{'s' if days != 1 else ''}")
25    if hours: parts.append(f"{hours} hour{'s' if hours != 1 else ''}")
26    if minutes: parts.append(f"{minutes} minute{'s' if minutes != 1 else ''}")
27    return ", ".join(parts) or "0 minutes"
28
29print(format_timedelta(diff))  # 73 days, 14 hours, 30 minutes

Common Pitfalls

  • Using .seconds instead of .total_seconds(): timedelta.seconds only returns the seconds component (0-86399), ignoring the days. For a 3-day difference, .seconds is 0 while .total_seconds() is 259200. Always use .total_seconds() for the complete difference.
  • Mixing timezone-aware and naive datetimes: Subtracting a timezone-aware datetime from a naive one raises TypeError: can't subtract offset-naive and offset-aware datetimes. Either make both aware or both naive before comparing.
  • Assuming months have fixed length: timedelta does not support months because months have 28-31 days. timedelta(months=1) is not valid. Use dateutil.relativedelta(months=1) for calendar-aware month arithmetic.
  • Negative timedelta confusion: date(2025, 1, 1) - date(2025, 3, 1) returns a negative timedelta with .days = -59. Use abs() to get the absolute difference regardless of order.
  • Forgetting strptime format mismatches: datetime.strptime("15/01/2025", "%Y-%m-%d") raises ValueError because the format does not match the string. The format string must exactly match the input pattern.

Summary

  • Subtract two date or datetime objects to get a timedelta with the difference
  • Use .days for whole days and .total_seconds() for the complete difference in seconds
  • Use dateutil.relativedelta for differences in years, months, and days
  • Parse date strings with datetime.strptime() before performing arithmetic
  • Use abs() to get a positive difference regardless of date order
  • Make both datetimes timezone-aware or both naive to avoid TypeError

Course illustration
Course illustration

All Rights Reserved.