8.7 gettimeofday: Wall-Clock Time

The gettimeofday system call gets the system's wall-clock time. It takes a pointer to a struct timeval variable. This structure represents a time, in seconds, split into two fields. The tv_sec field contains the integral number of seconds, and the tv_usec field contains an additional number of microseconds. This struct timeval value represents the number of seconds elapsed since the start of the UNIX epoch, on midnight UTC on January 1, 1970. The gettimeofday call also takes a second argument, which should be NULL. Include <sys/time.h> if you use this system call.

The number of seconds in the UNIX epoch isn't usually a very handy way of representing dates. The localtime and strftime library functions help manipulate the return value of gettimeofday. The localtime function takes a pointer to the number of seconds (the tv_sec field of struct timeval) and returns a pointer to a struct tm object. This structure contains more useful fields, which are filled according to the local time zone:

·         tm_hour, tm_min , tm_sec— The time of day, in hours, minutes, and seconds.

·         tm_year, tm_mon , tm_day— The year, month, and date.

·         tm_wday— The day of the week. Zero represents Sunday.

·         tm_yday— The day of the year.

·         tm_isdst— A flag indicating whether daylight savings time is in effect.

The strftime function additionally can produce from the struct tm pointer a customized, formatted string displaying the date and time. The format is specified in a manner similar to printf, as a string with embedded codes indicating which time fields to include. For example, this format string

 
"%Y-%m-%d %H:%M:%S" 

specifies the date and time in this form:

 
2001-01-14 13:09:42 

Pass strftime a character buffer to receive the string, the length of that buffer, the format string, and a pointer to a struct tm variable. See the strftime man page for a complete list of codes that can be used in the format string. Notice that neither localtime nor strftime handles the fractional part of the current time more precise than 1 second (the tv_usec field of struct timeval). If you want this in your formatted time strings, you'll have to include it yourself.

Include <time.h> if you call localtime or strftime.

The function in Listing 8.6 prints the current date and time of day, down to the millisecond.

Listing 8.6 (print-time.c) Print Date and Time
#include <stdio.h> 
#include <sys/time.h> 
#include <time.h> 
#include <unistd.h> 
 
void print_time () 
{
  struct timeval tv; 
  struct tm* ptm; 
  char time_string[40]; 
  long milliseconds; 
 
  /* Obtain the time of day, and convert it to a tm struct. */ 
  gettimeofday (&tv, NULL); 
  ptm = localtime (&tv.tv_sec); 
  /* Format the date and time, down to a single second. */ 
  strftime (time_string, sizeof (time_string), "%Y-%m-%d %H:%M:%S", ptm); 
  /* Compute milliseconds from microseconds. */ 
  milliseconds = tv.tv_usec / 1000; 
  /* Print the formatted time, in seconds, followed by a decimal point 
     and the milliseconds. */ 
  printf ("%s.%03ld\n", time_string, milliseconds); 
}