Depending on the amount of input data, I have a program that runs in seconds or in days. At the end of my program, I want to print the elapsed “clock wall” time: in seconds if it is less then one minute, in min and sec if it is less than one hour, in hour-min-sec if it is less than one day, and in day-hour-min-sec otherwise. Here is the code I am using:
#include <cstdio>
#include <ctime>
#include <unistd.h> // for sleep
int main (int argc, char ** argv)
{
time_t startRawTime, endRawTime;
time (&startRawTime);
printf ("%s", ctime (&startRawTime));
sleep (3); // any preprocessing of input data
time (&endRawTime);
printf ("%s", ctime (&endRawTime));
printf ("%.0fs\n", difftime (endRawTime, startRawTime));
time_t elapsed = static_cast<time_t>(difftime (endRawTime, startRawTime));
struct tm * ptm = gmtime (&elapsed);
printf ("%id %ih %im %is\n", ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
return 0;
}
Here is what it prints:
Mon Apr 9 14:43:16 2012
Mon Apr 9 14:43:19 2012
3s
1d 0h 0m 3s
Of course the last line is wrong (it should be “0d”). It seems it can be solved easily by printing ptm->tm_mday - 1. However, ptm->tm_mday will also be “1” when there really was one day elapsed between the two dates. And so in that case, I don’t want to make it appear as “0d”.
So is there a way to handle this properly? Or should I get the result of difftime as a double (that is, as a number of seconds) and then calculate myself the number of sec/min/hours/days?
Remark: my code is used only on Linux, compiled with gcc -lstdc++.
A
time_tvalue represents a particular moment in time. The result ofdifftimeis the interval, in seconds, between two moments. That’s a very different thing.In your code,
difftime()returns3.0, since there are 3 seconds between the two specified times. Converting that totime_tgives you a moment 3 seconds after the epoch; on most systems, that’s going to be 3 seconds past midnight GMT on January 1, 1970. Thetm_mdayvalue is 1 because that was the first day of the month.You might be able to make this work by subtracting 1 from the
tm_mdayvalue, sincetm_mdayis 1-based rather than 0-based. But you’ll still get meaningless results for longer intervals. For example, an interval of 31.5 days will give you noon on February 1, because January has 31 days; that’s not relevant to the information you’re trying to get.Just treat the result of
difftime()as adouble(because that’s what it is) and compute the number of days, hours, minutes, and seconds by simple arithmetic.(With some loss of portability, you can just subract the
time_tvalues directly rather than usingdifftime(). That will make some of the arithmetic a little easier, but it will break on systems where atime_tvalue is something other than an integer count of seconds since some epoch.difftime()exists for a reason.)That’s not correct; if the time interval is just over 1 day,
ptm->tm_mdaywill be2. You can verify this with a small modification to your code:When I make this change, I get this output:
which could be corrected by subtracting 1 from
ptm->tm_mday. But again, that’s not the right approach.