user16164417
user16164417

Reputation:

How to Calculate Difference Between 2 Timevals?

In my code I have:

struct timeval arrival_time, struct timeval pickup_time;

sprintf(buf, "Stat-Req-Dispatch:: %lu.%06d\r\n", (pickup_time.tv_sec - arrival_time.tv_sec),
        (pickup_time.tv_usec - arrival_time.tv_usec));

But I have noticed that this code isn't correct since sometimes the part which comes after . in printing might be negative.

I tried: struct timeval dispatch_time = pickup_time-arrival_time; but doesn't compile.

How can I properly print the difference between both times?


if (pickup_time.tv_usec < arrival_time.tv_usec)
{
    dispatch_time.tv_sec = pickup_time.tv_sec - arrival_time.tv_sec - 1;
    dispatch_time.tv_usec = pickup_time.tv_usec - arrival_time.tv_usec + 1000000;
} else
{
    dispatch_time.tv_sec = pickup_time.tv_sec - arrival_time.tv_sec;
    dispatch_time.tv_usec = pickup_time.tv_usec - arrival_time.tv_usec;
}

sprintf(buf, "%sStat-Req-Dispatch:: %lu.%06d\r\n", buf, dispatch_time.tv_sec, dispatch_time.tv_usec);

Upvotes: 2

Views: 4326

Answers (2)

Remy Lebeau
Remy Lebeau

Reputation: 595711

timeval::tv_sec is represented as seconds, and timeval::tv_usec is represented as microseconds. Since you are just looking at the fields indivudally, pickup_time may have a higher tv_sec than arrival_time, but have a lesser tv_usec (ie, arrival_time could be 1 second 30 microseconds while pickup_time is 5 seconds 10 microseconds);

The GNU C documentation describes a timeval_subtract() function that accounts for this:

21.3 Calculating Elapsed Time

The GNU C Library does not provide any functions for computing the difference between two values of type struct timeval or struct timespec. Here is the recommended way to do this calculation by hand. It works even on some peculiar operating systems where the tv_sec member has an unsigned type.

/* Subtract the ‘struct timeval’ values X and Y,
   storing the result in RESULT.
   Return 1 if the difference is negative, otherwise 0. */

int
timeval_subtract (struct timeval *result, struct timeval *x, struct timeval *y)
{
  /* Perform the carry for the later subtraction by updating y. */
  if (x->tv_usec < y->tv_usec) {
    int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
    y->tv_usec -= 1000000 * nsec;
    y->tv_sec += nsec;
  }
  if (x->tv_usec - y->tv_usec > 1000000) {
    int nsec = (x->tv_usec - y->tv_usec) / 1000000;
    y->tv_usec += 1000000 * nsec;
    y->tv_sec -= nsec;
  }

  /* Compute the time remaining to wait.
     tv_usec is certainly positive. */
  result->tv_sec = x->tv_sec - y->tv_sec;
  result->tv_usec = x->tv_usec - y->tv_usec;

  /* Return 1 if result is negative. */
  return x->tv_sec < y->tv_sec;
}

For example:

struct timeval arrival_time, pickup_time, elapsed_time;
...
timeval_subtract(&elapsed_time, &pickup_time, &arrival_time);
sprintf(buf, "Stat-Req-Dispatch:: %lu.%06d\r\n", elapsed_time.tv_sec, elapsed_time.tv_usec);

Upvotes: 0

Shawn
Shawn

Reputation: 52334

If you're using Linux+glibc, or a BSD OS, they give you some macros to manipulate timevals, including one to calculate the difference between two times:

#include <stdio.h>
#include <sys/time.h>

int main(void)
{
  struct timeval arrival_time = { .tv_sec = 100, .tv_usec = 50 },
    pickup_time = { .tv_sec = 150, .tv_usec = 0 },
    time_difference;
  timersub(&pickup_time, &arrival_time, &time_difference);
  printf("%ld seconds %ld useconds\n", (long)time_difference.tv_sec,
         (long)time_difference.tv_usec);
  return 0;
}

Upvotes: 5

Related Questions