Python timedelta: Calculating Durations & Date Arithmetic

The timedelta class from the datetime module represents an exact duration expressing the difference between two date or time instances.

Normalized Duration Units: While timedelta accepts weeks, days, hours, minutes, seconds, milliseconds, and microseconds, Python internally converts and stores only days, seconds, and microseconds. For calendar-aware operations spanning variable months or years, use relativedelta. To inspect tuple components, see date.timetuple().

Timedelta Arithmetic
date / datetime
+ / −
timedelta(days, sec, μs)
=
New Target Datetime

1. Syntax & Constructor Parameters

The timedelta constructor takes optional duration arguments that default to zero:

# Formal constructor signature of datetime.timedelta
from datetime import timedelta

delta = timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)
Parameter Accepted Type Default Internal Storage & Conversion
days int, float 0 Stored directly as integer days.
seconds int, float 0 Normalized: 0 ≤ seconds < 86400 (overflow increments days).
microseconds int, float 0 Normalized: 0 ≤ microseconds < 1000000.
weeks int, float 0 Converted into 7 days.

2. Date Arithmetic: Adding & Subtracting Days

Adding or subtracting a timedelta to a date object returns a new date, adjusting for leap years and month boundaries:

# 1. Basic date arithmetic: adding and subtracting days
from datetime import date, timedelta

today = date(2026, 10, 18)
five_days_ahead = today + timedelta(days=5)
three_weeks_ago = today - timedelta(weeks=3)

print("Baseline Date:   ", today)
print("5 Days Ahead:    ", five_days_ahead)
print("3 Weeks in Past: ", three_weeks_ago)

Terminal Output:

Baseline Date:    2026-10-18
5 Days Ahead:     2026-10-23
3 Weeks in Past:  2026-09-27

3. Datetime Arithmetic with Combined Time Units

When working with timestamps, you can combine hours, minutes, and seconds into a single duration:

# 2. Combined time units (hours, minutes, seconds)
from datetime import datetime, timedelta

start = datetime(2026, 10, 18, 9, 30, 0)
duration = timedelta(days=1, hours=4, minutes=45)
end = start + duration

print("Session Start: ", start)
print("Session End:   ", end)

Terminal Output:

Session Start:  2026-10-18 09:30:00
Session End:    2026-10-19 14:15:00

4. Subtracting Datetime Instances to Measure Differences

Subtracting two datetime instances yields a timedelta measuring elapsed duration:

# 3. Calculating duration between two datetime objects
from datetime import datetime

t1 = datetime(2026, 10, 18, 8, 0, 0)
t2 = datetime(2026, 10, 20, 14, 30, 15)
diff = t2 - t1

print("Difference object:", diff)
print("Days component:   ", diff.days)
print("Seconds component:", diff.seconds)
print("Total seconds:    ", diff.total_seconds())

Terminal Output:

Difference object: 2 days, 6:30:15
Days component:    2
Seconds component: 23415
Total seconds:     196215.0

5. CPython Internal Normalization Mechanics

CPython normalizes all inputs into three canonical attributes: days, seconds, and microseconds:

# 4. Internal normalization (days, seconds, microseconds)
from datetime import timedelta

# Hours, minutes, and milliseconds normalize into days, seconds, microseconds
d = timedelta(hours=25, minutes=90, milliseconds=1500)
print("Days:        ", d.days)
print("Seconds:     ", d.seconds)
print("Microseconds:", d.microseconds)
print("String:      ", d)

Terminal Output:

Days:         1
Seconds:      9001
Microseconds: 500000
String:       1 day, 2:30:01.500000

6. Duration Scaling: Multiplication & Division

Timedelta instances support scalar multiplication, float division, and unit ratios:

# 5. Multiplication, division, and slot counts
from datetime import timedelta

slot = timedelta(hours=2, minutes=30)
doubled = slot * 2
half = slot / 2

# Ratio of two timedeltas returns float count
total_time = timedelta(days=3)
unit = timedelta(hours=6)
slots_count = total_time / unit

print("Doubled duration:   ", doubled)
print("Half duration:      ", half)
print("Task slot count:    ", slots_count)

Terminal Output:

Doubled duration:    5:00:00
Half duration:       1:15:00
Task slot count:     12.0

7. Production Recipes

Session token validator with TTL expiration:

# 6. Production Recipe: Session Token Expiration Validator
from datetime import datetime, timedelta

class CacheToken:
    def __init__(self, key: str, ttl_seconds: int):
        self.key = key
        self.created_at = datetime.now()
        self.ttl = timedelta(seconds=ttl_seconds)

    def is_expired(self, at_time: datetime = None) -> bool:
        now = at_time or datetime.now()
        return (now - self.created_at) > self.ttl

token = CacheToken("session_key", ttl_seconds=3600)
t_45m = token.created_at + timedelta(minutes=45)
t_75m = token.created_at + timedelta(minutes=75)

print("Expired at 45m?", token.is_expired(t_45m))
print("Expired at 75m?", token.is_expired(t_75m))

Terminal Output:

Expired at 45m? False
Expired at 75m? True

Generating day-by-day schedules using stepping generators:

# 7. Production Recipe: Step-by-Step Date Range Generator
from datetime import date, timedelta

def date_range(start_date: date, count: int):
    step = timedelta(days=1)
    curr = start_date
    for _ in range(count):
        yield curr
        curr += step

start = date(2026, 10, 18)
dates = [d.strftime('%Y-%m-%d') for d in date_range(start, 4)]
print("Consecutive dates:", dates)

Terminal Output:

Consecutive dates: ['2026-10-18', '2026-10-19', '2026-10-20', '2026-10-21']

8. Common Developer Pitfalls & Traps

Use total_seconds() instead of .seconds for durations > 24 hours. Note that months are unsupported:

# 8. Common Traps: .seconds vs .total_seconds()
from datetime import timedelta

# TRAP: .seconds only returns partial-day seconds!
two_days = timedelta(days=2, hours=3)
print(".seconds:       ", two_days.seconds)        # 10800 (only the 3 hours)
print(".total_seconds():", two_days.total_seconds())  # 183600.0 (full duration)

# TRAP: timedelta does NOT accept 'months' or 'years'
try:
    timedelta(months=1)
except TypeError as err:
    print("Caught TypeError:", err)

Terminal Output:

.seconds:        10800
.total_seconds(): 183600.0
Caught TypeError: 'months' is an invalid keyword argument for __new__()

9. Interactive Notebook & Practice Exercises

Practice date arithmetic, duration normalization, and cache TTL validation in our interactive companion Jupyter Notebook:

Interactive Companion Jupyter Notebook

Explore interactive code cells, benchmark duration operations, test token expiry logic, and run self-validating assertions.

View on GitHub Run in Google Colab

Self-Verifying Assertion Suite

Run these unit checks directly in Python or your local environment to verify timedelta mechanics:

# 9. Self-verifying unit test suite for datetime.timedelta
from datetime import date, datetime, timedelta

# Test 1: Addition and subtraction equality
base = datetime(2026, 10, 18, 12, 0, 0)
d1 = timedelta(days=1, hours=2)
assert (base + d1) - d1 == base

# Test 2: Normalization verification
d2 = timedelta(hours=24)
assert d2.days == 1 and d2.seconds == 0

# Test 3: total_seconds() accuracy
d3 = timedelta(days=1, minutes=1)
assert d3.total_seconds() == 86400 + 60

# Test 4: Division ratio
assert timedelta(days=1) / timedelta(hours=12) == 2.0

print("All datetime.timedelta unit assertions successfully verified!")

Terminal Output:

All datetime.timedelta unit assertions successfully verified!

10. Frequently Asked Questions (FAQ)

Why is there no 'months' argument in timedelta?

Months have variable durations (28 to 31 days). A fixed duration object like timedelta cannot represent variable months. Use relativedelta instead.

What is the difference between .seconds and .total_seconds()?

The .seconds attribute returns only the remainder seconds for the partial day (0 to 86399). The .total_seconds() method returns the entire duration converted to seconds.

Can a timedelta be negative?

Yes. Subtracting a future date from a past date results in a negative timedelta, internally normalized with negative days and positive seconds.

What is timedelta.resolution?

timedelta.resolution represents the smallest possible duration increment: exactly 1 microsecond (0:00:00.000001).

Further Reading & Related Tutorials




Subscribe to our YouTube Channel here



plus2net.com







Python Video Tutorials
Python SQLite Video Tutorials
Python MySQL Video Tutorials
Python Tkinter Video Tutorials
✖
We use cookies to improve your browsing experience. . Learn more
HTML MySQL PHP JavaScript ASP Photoshop Articles Contact us
© 2000-2026 plus2net.com All rights reserved worldwide Privacy Policy Disclaimer