time_t
The most basic representation of a date and time is the type time_t. The value of a time_t variable is the number of seconds since January 1, 1970, sometimes call the Unix epoch. This is the best way to internally represent the start and end times for an event because it is easy to compare these values. Two time_t values a and b can be compared using <:
if(a < b) { printf("Time a is before time b\n"); }
struct tm
While time_t represents a date and time as a single number, struct tm represents it as a struct with a lot of numbers:
struct tm { int tm_sec; /* Seconds. [0-60] (1 leap second) */ int tm_min; /* Minutes. [0-59] */ int tm_hour; /* Hours. [0-23] */ int tm_mday; /* Day. [1-31] */ int tm_mon; /* Month. [0-11] */ int tm_year; /* Year - 1900. */ int tm_wday; /* Day of week. [0-6] */ int tm_yday; /* Days in year.[0-365] */ int tm_isdst; /* DST. [-1/0/1]*/ };
Conversion
You can convert a time_t value to a struct tm value using the localtime function:
struct tm startTM; time_t start; /* ... */ startTM = *localtime(&start);
You can convert a struct tm value to a time_t value using the mktime function:
struct tm startTM; time_t start; /* ... */ start = mktime(&startTM);
How to input a date
Your program will need to input a date. Here is an example of a safe and robust way to input a date:
time_t InputDate(char *prompt) { char buffer[100]; char *result; struct tm date; do { printf("%s", prompt); /* Get a line of up to 100 characters */ fgets(buffer, sizeof(buffer), stdin); /* Remove any \n we may have input */ if(strlen(buffer) > 0) buffer[strlen(buffer)-1] = '\0'; result = strptime(buffer, "%m/%d/%Y", &date); } while(result == NULL); /* Convert to time_t format */ date.tm_min = 0; date.tm_hour = 0; date.tm_sec = 0; date.tm_isdst = 1; return mktime(&date); }
This function asks the user for a time with the given prompt. If the time is correctly entered, it converts it to type time_t, expressing a time and date of 12:00am on the entered date.
In order to use the strptime function, you will need to #include <time.h>. However, you must preceed the #include with this code:
#define __USE_XOPEN #include <time.h>
Any time you #include <time.h> in your program, use the line #define __USE_XOPEN before it. Note that it begins with two underlines.
How to input a time
After entering the date, you can enter a time using this safe and robust function:
time_t InputTime(char *prompt, time_t date) { char buffer[100]; char *result; struct tm time; time = *localtime(&date); do { printf("%s", prompt); /* Get a line of up to 100 characters */ fgets(buffer, sizeof(buffer), stdin); /* Remove any \n we may have input */ if(strlen(buffer) > 0) buffer[strlen(buffer)-1] = '\0'; result = strptime(buffer, "%I:%M%p", &time); } while(result == NULL); return mktime(&time); }
This function is passed a date expressed as a time_t value, the output of the InputDate function. The time is entered and added to the date to produce a date and time value that is returned. Here is an example of how these functions can be used to input a date, start time, and end time.
time_t date; time_t start; time_t end; /*...*/ date = InputDate("Event date: "); start = InputTime("Start time: ", date); end = InputTime("End time: ", date);
How to output a time_t value.
To output a time or date, you convert it to a struct tm:
struct tm startTM; time_t start; /* ... */ startTM = *localtime(&start);
Once converted, the value in struct tm are:
struct tm { int tm_sec; /* Seconds. [0-60] (1 leap second) */ int tm_min; /* Minutes. [0-59] */ int tm_hour; /* Hours. [0-23] */ int tm_mday; /* Day. [1-31] */ int tm_mon; /* Month. [0-11] */ int tm_year; /* Year - 1900. */ int tm_wday; /* Day of week. [0-6] */ int tm_yday; /* Days in year.[0-365] */ int tm_isdst; /* DST. [-1/0/1]*/ };
Now I can get the hour in the example as startTM.tm_hour. There are a couple strange things about this struct. To get the actual year, use startTM.tm_year + 1900. To get the actual month number, use startTM.tm_mon + 1.
The function ctime
The function ctime converts a time_t value into a string of the following form:
Thu Apr 14 14:00:00 2011
This is a handy way to test to see if a time is what you expect. For example, if I have a variable: time_t timeDate and want to know what its value is, I can add this code while debugging:
printf("The date/time is %s\n", ctime(&timeDate));
This is also the easiest way to save the start date/time and end date/time to a file.
Reading the output of ctime
To read the output of ctime from a file and convert it back to a time_t value, use this code:
struct tm tim; time_t startTime; fgets(buffer, sizeof(buffer), file); strptime(buffer, "%a %b %d %H:%M:%S %Y", &tim); startTime = mktime(&tim);
This inputs the date/time string from a file into the character string buffer. It then used strptime to convert it to a struct tm structure. Then the funciton mktime converts the struct tm value to a time_t value.