RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Minimize Date and Time Display Drudgery-2 : Page 2

Time for a Change
It's hard to imagine a large-scale application that doesn't rely on date and time calculations. In most cases, a crude representation of the system's time (e.g., time_t) is used. However, when the date and time are presented in a human readable format, customization and formatting are necessary. In the United States, the accepted date format is MMDDYYYY. However, in many other countries the day precedes the month, as in 31/12/2007. Similarly, the common time format in the UK is based on a 12 hour clock, e.g., 6:30 PM, whereas in other countries a 24-hour clock is used instead i.e., 18:30. These locale-specific differences, along with text formatting, are all handled by the strftime() function declared in <ctime>. strftime() takes a format string to compose a date and time string:

size_t strftime(char *s, 
                size_t maxsz, 
                const char *fmt, 
                const struct tm *ptm);
The first parameter is the address of a memory buffer into which the resulting date and time string is written. The maxsz parameter specifies the maximum number of characters that can be written to s, excluding the terminating '\0'. The final argument is a pointer to a valid tm struct, which is obtained by calling localtime() and gmtime(). On success, strftime() returns the number of characters (excluding the terminating '\0') written to s. If the number of characters required is greater than maxsz, strftime() returns 0.

The interesting bit for you is the third parameter fmt, the format string. It contains a sequence of escape characters and optional text. An escape sequence represents a certain date and time category (day, month, seconds). It consists of a % sign followed by a case-sensitive letter. For example, %a represents the abbreviated name of the day (Sun), %A stands for the full name of the day (Sunday). A complete list of all the POSIX escape sequences is available here. The ISO C89 and C99 lists of escape sequences are slightly different, so you should check your compiler's documentation before using non-portable escapes.

It's About Time
Let's see strftime() in action. Suppose you want to display the current date and time in the following format:

Monday, February 05, 2007. The local time is: 16:01:26
Break this string down to its date and time components and pair them with their matching escapes (I'll discuss the last three components later):
  • Full name of the weekday (%A)
  • Full name of the month (%B)
  • The numeric day of the month (%d)
  • A four digit year (%Y)
  • The hour of the day in a 24-hour clock
  • The minute of the hour (0-59)
  • The second of the minute (0-60, 60 used in a leap minute)
Here's a complete program that uses the format string fmt to compose a date and time string according to the template above:

#include <iostream>
#include <ctime>
using namespace std;
const int BUFSIZE=200;
int main()
 time_t t = time(0); //obtain the current time_t value
 tm now=*localtime(&t); //convert it to tm
 char tmdescr[BUFSIZE]={0};
 const char fmt[]="%A, %B %d %Y. The time is %X"; 
 if (strftime(tmdescr, sizeof(tmdescr)-1, fmt, &now)>0);
  cerr<<"strftime failed. Errno code: "<<errno<<endl;
The output is:

Monday, February 05 2007. The time is 07:09:55
At the heart of this program lies the following string format:

"%A, %B %d %Y. The time is %X";
The last escape sequence, %X, is tricky. I could have broken the timestamp into hours, minutes, and seconds—plus the intervening ':' characters between them. However, the %X escape sequence is convenient shorthand for hh:mm:ss so I used that instead. If you want to display only some of these components, for instance, only the hour and the minutes, use the individual escape sequences of each of these components.

Notice that the translation of escape sequences is locale-specific. The default locale "C" (or "POSIX") will use American English weekday and month names. However, after loading a French locale (either by calling setlocale() or setting the appropriate environment variables), the output of the same strftime() call changes to:

lundi, février 05 2007. The time is 07:09:55
That is, the value of each escape sequence depends on the current locale's representation of that category. Any hard-coded text embedded in the format string remains unmodified. This is why you should use dynamically loaded string tables (or message catalogs in POSIX parlance) instead of hard-coded text.

Now, suppose you want to display the abbreviated month name (%b), the numeric day of the month (%d), the day of the year (%j), and a two-digit year (%y). The new format string will change accordingly to:

"%b %d, day %j in %y"
The output is:

Feb 05, day 036 in 07

Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date