Saturday, May 26, 2012

Converting two date(1) outputs into a time delta

So I wrote a little shell script that went something like:
date
somestuff
morestuff
otherstuff
date
and I wanted to calculate the time between the first date and the second. It's not rocket science; by inspection you can tell whether the start and end are on the same day, same hour, etc., and do the necessary "borrow"s -- if something started at 1:59:59 and finished at 2:00:17 then it obviously took about 18 seconds.

But suppose you want to do it programmatically -- which I almost always want to, because I may want to know in a couple months whether the time has gone up or down. The second thing that came to mind was to change all those date commands to something more like date +%s, because if what you have is

$ date
Sat May 26 22:20:39 PDT 2012
$ somestuff
…
$ date
Sat May 26 22:22:29 PDT 2012
it would be a lot easier to calculate the time difference if instead you had this:
$ date +%s
1338096039
$ somestuff
…
$ date +%s
1338096149
but that would make the output more computer-friendly than human-friendly. To paraphrase the old IBM motto, "Machines should do date conversions; people should think."

So here's what I did instead. I wrote some Python to do the conversions -- or rather to call the conversion routines. Here's an extract; it's inside a loop that reads all the lines in a screen-scrape (or script(1) output) file.

    if aline.endswith(' date'):
        expecting_date = True   # Next line will resemble 'Sat May 26 hh:mm:ss' etc
    elif expecting_date:
        secs = time.mktime(time.strptime(aline, '%a %b %d %H:%M:%S %Z %Y'))
        dates.append(secs)      # Will this code work beyond 2038 AD ??
        expecting_date = False
It turns out that in this particular file, whenever you see a line ending with " date", the next line will have output from date(1).

After the loop runs, what we have is a list of times based upon the date(1) outputs: if the file has 'Sat May 26 22:20:39 PDT 2012' (a string) then the list dates will have 1338096039 (a number), which can be compared, subtracted from something, etc.

The routine you want to remember is time.strptime; that magic "format" string is the format that my dates come in. Somehow I had the idea that you ought to be able to just put '%S' or something like this into strptime, and it would know you meant the "standard" (POSIX maybe?) date format. But it didn't work for me, thus the '%a %b %d %H:%M:%S %Z %Y'

That's all there is to it! Next time I'll look for this posting, rather than grinning (or not) and bearing it.

No comments: