Skip to content

Instantly share code, notes, and snippets.

@diabloneo
Created March 18, 2014 13:22
Show Gist options
  • Star 19 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save diabloneo/9619917 to your computer and use it in GitHub Desktop.
Save diabloneo/9619917 to your computer and use it in GitHub Desktop.
Calculate diff of two struct timespec
#include <time.h>
void timespec_diff(struct timespec *start, struct timespec *stop,
struct timespec *result)
{
if ((stop->tv_nsec - start->tv_nsec) < 0) {
result->tv_sec = stop->tv_sec - start->tv_sec - 1;
result->tv_nsec = stop->tv_nsec - start->tv_nsec + 1000000000;
} else {
result->tv_sec = stop->tv_sec - start->tv_sec;
result->tv_nsec = stop->tv_nsec - start->tv_nsec;
}
return;
}
@vi
Copy link

vi commented Feb 20, 2018

Maybe const struct timespec *start, const struct timespec *stop?

@akshay-dandekar
Copy link

Should it be "1000000000UL" instead of "1000000000"?

Copy link

ghost commented May 18, 2018

This code is correct only if stop > start. If start is 0 and stop is 1ns, then the code above will produce result->tv_sec = -1 and result->tv_nsec = 999999999. If denormalized results are alright, then if ((stop->tv_nsec - start->tv_nsec) < 0) is not necessary at all.

@alejandro-colomar
Copy link

Should it be "1000000000UL" instead of "1000000000"?

It should be L, not UL, given that struct timespec::tv_nsec is of type long.

From man clock_gettime:

       The  res  and  tp  arguments  are  timespec structures, as specified in
       <time.h>:

           struct timespec {
               time_t   tv_sec;        /* seconds */
               long     tv_nsec;       /* nanoseconds */
           };

@ehetherington
Copy link

ehetherington commented Jul 4, 2020

<sys/time.h> has a macro for calculating the difference of two timevals called timersub.
Modifying it for timespecs is straightforward.

// from <sys/time.h>
// used timersub macro, changed timeval to timespec
// kept the order of operands the same, that is a - b = result
# define timespec_diff_macro(a, b, result)                  \
  do {                                                \
    (result)->tv_sec = (a)->tv_sec - (b)->tv_sec;     \
    (result)->tv_nsec = (a)->tv_nsec - (b)->tv_nsec;  \
    if ((result)->tv_nsec < 0) {                      \
      --(result)->tv_sec;                             \
      (result)->tv_nsec += 1000000000;                \
    }                                                 \
  } while (0)

Or, as a function:

/**
 * @fn timespec_diff(struct timespec *, struct timespec *, struct timespec *)
 * @brief Compute the diff of two timespecs, that is a - b = result.
 * @param a the minuend
 * @param b the subtrahend
 * @param result a - b
 */
static inline void timespec_diff(struct timespec *a, struct timespec *b,
    struct timespec *result) {
    result->tv_sec  = a->tv_sec  - b->tv_sec;
    result->tv_nsec = a->tv_nsec - b->tv_nsec;
    if (result->tv_nsec < 0) {
        --result->tv_sec;
        result->tv_nsec += 1000000000L;
    }
}

@alejandro-colomar
Copy link

alejandro-colomar commented Jul 26, 2020

<sys/time.h> has a macro for calculating the difference of two timevals called timersub.
Modifying it for timespecs is straightforward.

Thanks for that info. I just discovered that <sys/time.h> also has timespecsub() so you don't even need to modify it. It is a BSD function (actually a macro) and not a POSIX one. However, in linux we have libbsd to provide it.

The man pages includes many functions (or macros) which may also be interesting to you: man timespecsub

@markand
Copy link

markand commented Aug 8, 2022

timerspecsub nor timersub are part of any standard.

@alejandro-colomar
Copy link

alejandro-colomar commented Aug 8, 2022

timerspecsub nor timersub are part of any standard.

Yet they are useful, and relatively portable (Linux and BSDs).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment