The Boston Diaries

The ongoing saga of a programmer who doesn't live in Boston, nor does he even like Boston, but yet named his weblog/journal “The Boston Diaries.”

Go figure.

Monday, May 15, 2000

Elapsed time is …

Okay, in monnet I'm keeping track of how long the program runs so when the report is printed, you can see how much time has elapsed since the program started. I want the display to look something like: 10d 14h 13m 33s. Make it easier to read than something like 915213s.

Under ANSI C, you have the various functions under time.h and the “official” way to calculate elapsed time is to call difftime() (as you portably can't assume that time_t is in sections, or even a integral type). That returns, as a double, the number of seconds between the two time values.

The problem is, you can't really take that result, stick it into a struct tm and call mktime() to renormalize it, as the value could overflow an int (which is what each field is defined as in struct tm). An int is defined as a minimum of 16 bits, which isn't even enough to record the number of seconds in a day. Sure, on modern systems ints are probably 32 bits in size, but that only leaves you some 68 years before the seconds overflow (it should be fun in 2038).

So it's more portable to do the math directly.

So, I thought I'd be cute and try to do the minimal amount of math possible, and in looking over math.h I saw modf(), which splits a double into its integral portion and fractional portion. So, I tried:

  diff = difftime(end,start);

  diff /= 60.0;
  tmp   = modf(diff,&diff);
  sec   = tmp * 60.0;

  diff /= 60.0;
  tmp   = modf(diff,&diff);
  min   = tmp * 60.0;

  diff /= 24.0;
  tmp   = modf(diff,&diff);
  hour  = tmp * 24.0;

  diff /= 365.0;
  tmp   = modf(diff,&diff);
  day   = tmp * 365.0;

  year  = diff;

only to have it fail miserably. Even several variations on that didn't work. So I bit the bullet and did it the old fasion way:

#define SECSMIN         (60.0)
#define SECSHOUR        (60.0 * 60.0)
#define SECSDAY         (60.0 * 60.0 * 24.0)
#define SECSYEAR        (60.0 * 60.0 * 24.0 * 365.2422)

  diff = difftime(end,start);

  year = (int)(diff / SECSYEAR);
  diff -= ((double)year) * SECSYEAR;

  day = (int)(diff / SECSDAY);
  diff -= ((double)day) * SECSDAY;

  hour = (int)(diff / SECSHOUR);
  diff -= ((double)hour) * SECSHOUR;

  min = (int)(diff / SECSMIN);
  diff -= ((double)min) * SECSMIN;

  sec = (int)(diff);

Obligatory Picture

[The future's so bright, I gotta wear shades]

Obligatory Contact Info

Obligatory Feeds

Obligatory Links

Obligatory Miscellaneous

You have my permission to link freely to any entry here. Go ahead, I won't bite. I promise.

The dates are the permanent links to that day's entries (or entry, if there is only one entry). The titles are the permanent links to that entry only. The format for the links are simple: Start with the base link for this site:, then add the date you are interested in, say 2000/08/01, so that would make the final URL:

You can also specify the entire month by leaving off the day portion. You can even select an arbitrary portion of time.

You may also note subtle shading of the links and that's intentional: the “closer” the link is (relative to the page) the “brighter” it appears. It's an experiment in using color shading to denote the distance a link is from here. If you don't notice it, don't worry; it's not all that important.

It is assumed that every brand name, slogan, corporate name, symbol, design element, et cetera mentioned in these pages is a protected and/or trademarked entity, the sole property of its owner(s), and acknowledgement of this status is implied.

Copyright © 1999-2024 by Sean Conner. All Rights Reserved.