## 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 `int`s 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);