Today at work, I investigated some problems with our firewall management software called Heimdal. After adding more instrumentation and finding another bug, I noticed that the number of active rules decreased much faster than they should.
remaining_seconds = ((address.block_timestamp+datetime.timedelta(seconds=address.block_duration))-datetime.datetime.now()).seconds
What I expected was to get the total of seconds left to re-add the rule with the correct timeout to the firewall. But you guessed it; that was not what I got. Instead, during debugging, I got this:
At first glance, everything looks good, but at the second, the last line seems odd. That’s because 83089 seconds are not nearly 19 days. Instead, 83089 seconds are exactly 23:04:49 hours. Sounds familiar? These are, indeed, the hours, minutes, and seconds in the second last line. So I looked up what timedelta.seconds actually does in the Python docs and was surprised by a big yellow warning box informing me that I’ve made a very common mistake.
So timedelta.seconds returns exactly what I got. The hours, minutes, and seconds of the timedelta I calculated. But this is still not what I want. To get what I was expecting my code would calculate in the first place, I need to use timedelta.total_seconds(). Totally counterintuitive, but this is only raising another question: “Why?”
After talking to a colleague, they explained to me that the timedelta object internally only holds days, seconds, and microseconds. Everything else is transformed into these three types, so this behavior is at least somewhat consistent, but still confusing. They also added some guesses as to why everything is broken down to these three types, but it is late and I have no motivation to dive into Python this deep this afternoon. Sorry.