Skip to Content
Course content

220: Working with Timedeltas

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I once worked with a junior developer who was tasked with implementing a 30-day trial expiration for a SaaS product. He decided to handle it by simply adding 30 to the day attribute of the user's signup date. It worked perfectly during his testing in May. Then February rolled around, and the system started throwing ValueError: day is out of range for month. He had forgotten that dates aren't just simple integers; they're complex objects with varying month lengths and leap years. That's exactly why we have timedelta.

In Python, a timedelta represents a duration—the difference between two dates or times. Instead of trying to do the mental gymnastics of calculating how many days are left in a month, you describe the duration you want, and Python handles the calendar logic for you.

Shifting Dates Forward and Backward

When you want to find a date in the future or the past, you don't modify the datetime object directly (since they are immutable). Instead, you create a timedelta object and add or subtract it from your starting point. I usually find it cleanest to import timedelta directly from the datetime module.

from datetime import datetime, timedelta

# Let's say a user signed up right now
signup_date = datetime.now()

# Define a 30-day trial period
trial_duration = timedelta(days=30)

# Calculate the expiration date
expiration_date = signup_date + trial_duration

print(f"Signed up on: {signup_date}")
print(f"Trial expires on: {expiration_date}")

You can pass several arguments to timedelta, including weeks, days, hours, minutes, seconds, milliseconds, and microseconds. If you need to move backward in time—say, to check a user's activity over the last 24 hours—you just subtract the delta.

Measuring the Gap Between Two Events

The inverse is also true: if you subtract one datetime object from another, Python doesn't return a number; it returns a timedelta object. This is incredibly useful for calculating "time elapsed" without having to worry about the underlying Unix timestamps.

# Imagine we have a log of when a process started and ended
start_time = datetime(2023, 10, 1, 12, 0, 0)
end_time = datetime(2023, 10, 2, 14, 30, 0)

duration = end_time - start_time
print(f"The process took {duration} to complete.") 
# Output: The process took 1 day, 2:30:00

The Trap of the Seconds Attribute

Here is where most developers—including myself, early in my career—trip up. A timedelta object has an attribute called .seconds. It sounds like it should give you the total length of the duration in seconds, but it doesn't. The .seconds attribute only returns the remaining seconds that didn't make it into a full day.

If your duration is 1 day and 5 seconds, .seconds will return 5, not 86405. If you need the actual total duration expressed in seconds, you must use the .total_seconds() method.

diff = timedelta(days=1, seconds=5)

print(diff.seconds)       # Output: 5 (This is almost always NOT what you want)
print(diff.total_seconds()) # Output: 86405.0 (This is the actual duration)

I always tell people: unless you specifically need to isolate the "time of day" portion of a duration, avoid .seconds entirely and stick with .total_seconds(). It saves a lot of debugging headaches.




📋 Practical Task

Build a Session Timeout Validator

You are building a security feature for a web application that requires users to re-authenticate if their session has been inactive for more than 30 minutes.

Write a function called is_session_expired(last_activity_time) that does the following:

  • Takes a datetime object representing the last time the user performed an action.
  • Calculates the difference between the current time (datetime.now()) and that activity time.
  • Returns True if the difference is greater than 30 minutes, and False otherwise.

Test your function with these two cases:

# Case 1: Activity was 10 minutes ago (Should return False)
# Case 2: Activity was 45 minutes ago (Should return True)
Rating
0 0

There are no comments for now.

to be the first to leave a comment.