I've seen a number of questions / answers for subtracting two datetimes here but not one for adding or subtracting an interval to / from a timevalue.
Add milliseconds to timeval C++ This asnwer does not result in a valid timeval structure.
void addms2timeval(int microseconds, timeval tv); //prototype (doesn't exist yet)
...
struct timeval later;
gettimeofday(&later, NULL);
addms2timeval(1000, later);
//later is now 1000 us in the future.
Also doesn't seem to be part of the standard C libraries unless I missed it. https://pubs.opengroup.org/onlinepubs/007908775/xsh/systime.h.html https://www.gnu.org/software/libc/manual/html_node/Date-and-Time.html
Perhaps it's trivial, but it seems like one of those things that you can think you coded correctly but which then fails randomly every so often due to over / under flows.
Has anyone written and tested this?
I have a pair of files, timeval_math.c
and timeval_math.h
that probably show you how to do what you want.
timeval_math.h
#ifndef JLSS_ID_TIMEVAL_MATH_H
#define JLSS_ID_TIMEVAL_MATH_H
#include <sys/time.h>
extern void sub_timeval(struct timeval t1, struct timeval t2, struct timeval *td);
extern void add_timeval(struct timeval t1, struct timeval t2, struct timeval *td);
extern int cmp_timeval(struct timeval t1, struct timeval t2);
#endif /* JLSS_ID_TIMEVAL_MATH_H */
timeval_math.c
#include "timeval_math.h"
enum { US_PER_SECOND = 1000000 };
void sub_timeval(struct timeval t1, struct timeval t2, struct timeval *td)
{
td->tv_usec = t2.tv_usec - t1.tv_usec;
td->tv_sec = t2.tv_sec - t1.tv_sec;
if (td->tv_sec > 0 && td->tv_usec < 0)
{
td->tv_usec += US_PER_SECOND;
td->tv_sec--;
}
else if (td->tv_sec < 0 && td->tv_usec > 0)
{
td->tv_usec -= US_PER_SECOND;
td->tv_sec++;
}
}
void add_timeval(struct timeval t1, struct timeval t2, struct timeval *td)
{
td->tv_usec = t2.tv_usec + t1.tv_usec;
td->tv_sec = t2.tv_sec + t1.tv_sec;
if (td->tv_usec >= US_PER_SECOND)
{
td->tv_usec -= US_PER_SECOND;
td->tv_sec++;
}
else if (td->tv_usec <= -US_PER_SECOND)
{
td->tv_usec += US_PER_SECOND;
td->tv_sec--;
}
}
int cmp_timeval(struct timeval t1, struct timeval t2)
{
if (t1.tv_sec < t2.tv_sec)
return -1;
else if (t1.tv_sec > t2.tv_sec)
return +1;
else if (t1.tv_usec < t2.tv_usec)
return -1;
else if (t1.tv_usec > t2.tv_usec)
return +1;
else
return 0;
}
addms2timeval()
Clearly, you can write an addms2timeval()
function, but it isn't clear to me how your interface (void addms2timeval(int microseconds, timeval tv);
returns the value. You should probably use one of these two interfaces:
struct timeval addms2timeval(int microseconds, struct timeval tv);
void addms2timeval(int microseconds, struct timeval *tv);
Assuming the latter, you can write:
void addms2timeval(int microseconds, struct timeval *tv)
{
add_timeval(*tv, (struct timeval){.tv_sec = 0, .tv_usec = microseconds}, tv);
}
The second argument to add_timeval()
is a compound literal, a feature added to C99.
This code may be used for any purpose. There is no warranty.