A few weeks ago, Iron Blogger broke again. At the time I noticed that there were negative debts on the ledger, but didn’t have time to look into it. Being between contract gigs, I finally found some time today to dig into it. Big surprise; it was another daylight savings time bug. Basically, in order to work out how late a post is, there’s was something like this:
rounds_late = divide_timedelta(duedate(post) - post.counts_for), ROUND_LEN)
The above is somewhat simplified, but the essentials are intact.
Basically, find the difference between the two times and divide by the
length of a round (which happens to be one week). divide_timedelta
exists because there’s no built-in division method for timedelta
objects. It’s implementation was:
def divide_timedelta(numerator, denominator):
"""Divide two timedelta objects.
The timedelta type doesn't have it's own divide operator, which
is something we need in a few places.
Both numerator and denominator *must* be whole-second quantities.
The return value is of type int, not timedelta.
"""
# total_seconds returns a floating point value, but for our purposes it's
# always going to be an integer, and we don't want to deal with precision
# errors, so we convert before dividing.
return int(numerator.total_seconds())/int(denominator.total_seconds())
A couple things to note:
- The docstring has a mistake; it should actually be whole week (or round) quantities.
- We rely on property (1) to allow us to just do integer division, keeping things simple.
Okay, here’s the bug: a week isn’t actually a constant unit of time.
Most of the time it’s 24 hours * 7 days
, but if it spans a DST
boundary, it can be off by an hour in either direction. If it’s an hour
shorter, integer division will round down, and we’ll get an off-by-one
error. The upshot of this is that after the last party everybody was tagged
as owing one-post’s worth of money less than they really did – even if they
owed nothing to begin with.
The bug has been fixed now, and I caught a couple of other mistakes in the code while I was digging; they didn’t seem to be causing any immediate symptoms, but were clearly incorrect.
Date and time handling has been a constant source of problems for Iron Blogger, and I’m thinking about ways of making it less error-prone; see Issue #59. In addition to causing hiccups in operation and taking up some of my time, this has necessitated more caution when making improvements than I’d like. Making the date-and-time handling routines more robust will be well worth the effort, I think.
I’m also re-committing myself to the promise I made (and broke) about dedicating time to Iron Blogger. I’ve actually blocked off the time for this on my calendar, so I hope I’ll be more successful in sticking to it.