Reputation: 299
I need to use the function gettimeofday for a home assignment, and after reading the man page and looking some online examples, I can't see why people sometimes use both the tv_sec member of the struct and tv_usec member of the struct. The man page states:
The tv argument is a struct timeval (as specified in <sys/time.h>):
struct timeval {
time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* microseconds */
};
So, assuming I need to return time in nanoseconds and I have created two timeval structs, start & end and I logged their time with gettimeofday(). Naturally my first thought was to calculate the difference in microseconds, i.e. start.tv_usec-end.tv_usec and then multiply it by 1000 to convert it into nanoseconds.
However, many online examples and tutorials calculate both the differences of the seconds and microseconds, convert them and then add them. (e.g.)
I read through the entire man page and couldn't find out why, would appreciate an explanation, if there is any.
Upvotes: 3
Views: 3221
Reputation: 753535
The tv_sec
holds the whole number of seconds since the Unix Epoch — 1970-01-01 00:00:00 +00:00 — and the tv_usec
(or tv_nsec
when working with the more modern struct timespec
) holds the fractional part — values [0..999,999] microseconds for struct timeval
and [0..999,999,999] nanoseconds for struct timespec
.
In the days before 64-bit integers were widespread, time_t
was a 32-bit signed type, and that 'runs out' in January 2038 — there will have been more 2 billion seconds since the epoch. There was no room to store sub-second units in a single integer.
-2147483647 = 1901-12-13 20:45:53 +00:00
+2147483647 = 2038-01-19 03:14:07 +00:00
Even now, if dealing with nanoseconds, you need 30 bits to represent up to 999,999,999 nanoseconds (and 20 bits to represent up to 999,999 microseconds). The requirements for nanoseconds means that it is not sensible to try scaling a 64-bit number to represent seconds and nanoseconds — the Y2K38 problem would be deferred by something like 280 years, whereas the two-part solution puts it off until after the universe ends, which should be long enough for everyone. (I plan to start working on the Y10K problem on 5000-01-02, if I'm still around. 😀)
So, although not ideal, the two part structure makes it easy to use the regular formatting functions that take a time_t
value — there are lots of them, and the ones that take a struct tm
derived from a time_t
value. And the arithmetic on them isn't hard.
I note that, in some respects, both struct timeval
and struct timespec
are under-specified by POSIX. What is the sign of the tv_usec
or tv_nsec
portion of a struct timeval
or struct timespec
if the tv_sec
component is negative (see Seconds Since the Epoch — If the year is <1970 or the value is negative, the relationship is undefined). POSIX leaves the behaviour of negative values of tv_sec
undefined, which is probably sensible, but does make life a bit difficult. Of course, there are also the issues of "when did which part of which country switch between the Julian and Gregorian calendars?" and "was there a year zero?" that would also have to be dealt with. When time_t
was a 32-bit number, it reached back as far as December 1901, which largely avoids the problems (but Russia didn't switch from Julian to Gregorian until after the October Revolution, which occurred in November in the Gregorian calendar). Now that time_t
is usually a 64-bit number, years BC (or BCE) also become representable.
Be careful when printing the tv_usec
or tv_nsec
part. Remember to add enough leading zeros by using %.6d
for microseconds, %.9ld
for nanoseconds, where the necessary conversion specifier (d
vs ld
vs …) for tv_usec
is not clearly defined in POSIX — but d
is usually correct. (The tv_nsec
member is a long
; that's easy and reliable.)
Upvotes: 2
Reputation: 13189
The time is represented by the whole number of seconds, PLUS the microseconds in the range 0 - 999999.
Upvotes: 0
Reputation: 777
The "microseconds" field doesn't have enough space to store all the time that passed. The "seconds" field is not precise enough. Together, they provide the most information.
Upvotes: 1