Add Book to My BookshelfPurchase This Book Online

Chapter 7 - Time of Day Operations

UNIX Systems Programming for SVR4
David A. Curry
 Copyright © 1996 O'Reilly & Associates, Inc.

Formatting Date Strings
Now that you can convert UNIX time to a struct tm structure and vice-versa, the next thing you need to do is convert the elements of this structure into something readable by human beings. There are five functions provided to do this:
    #include <time.h>
    char *ctime(const time_t *clock);
    char *asctime(const struct tm *tm);
    size_t *strftime(const char *s, size_t maxsize, const char *format,
        const struct tm *tm);
    int cftime(char *s, const char *format, const time_t *clock);
    int ascftime(char *s, const char *format, const struct tm *tm);
The asctime function converts the time contained in tm as returned by localtime or gmtime to a 26-character string and returns a pointer to that string. The string has the format:
    DDD MMM dd hh:mm:ss yyyy\n\0
For example:
    Thu Jan  1 00:00:00 1970\n\0
The ctime function is equivalent to calling:
    asctime(localtime(&clock));
The cftime, ascftime, and strftime functions all do essentially the same thing, with cftime being to ascftime as ctime is to asctime. The cftime and ascftime functions are obsolete, and strftime should be used instead. HP-UX 10.x does not provide cftime or ascftime.
The strftime function copies characters into the array pointed to by s, which is of maxsize bytes in length. The contents of the string are controlled by the string contained in format. The format string is similar to a printf format string; all ordinary characters in the string (including the terminating null character) are copied into s, and characters in format that are preceded by a percent sign (%) represent formatting directives. The strftime function is internationalized, and uses values in formatting directives that are appropriate for the current locale.
The valid formatting directives are as follows. If the format string is null, the locale's default format is used:
%%
A literal percent sign
%a
The locale's abbreviated weekday name
%A
The locale's full weekday name
%b
The locale's abbreviated month name
%B
The locale's full month name
%c
The locale's appropriate date and time representation
%C
The locale's date and time representation as produced by the date command
%d
The day of the month (01–31)
%D
The date as %m/%d/%y
%e
The day of the month (1–31, single digits are preceded by a space)
%h
The locale's abbreviated month name
%H
The hour (00–23)
%I
The hour (01–12)
%j
The day of the year (001–366)
%k
The hour (0–23, single digits are preceded by a space) (Solaris 2.x only)
%l
The hour (1–12, single digits are preceded by a space) (Solaris 2.x only)
%m
The month number (01–12)
%M
The minute (00–59)
%n
Same as \n
%p
The locale's equivalent of A.M. or P.M.
%r
The time as %I:%M:%S [AM|PM]
%R
The time as %H:%M
%S
The second (00–61); allows for leap seconds
%t
Same as \t
%T
The time as %H:%M:%S
%U
The week number of the year (00–53); Sunday is the first day of week 01, days prior to the first Sunday in January are in week 00
%w
The weekday number (0–6); Sunday is day 0
%W
The week number of the year (00–53); Monday is the first day of week 01, days prior to the first Monday in January are in week 00
%x
The locale's appropriate date representation
%X
The locale's appropriate time representation
%y
The year within the century (00–99)
%Y
The year with the century (for example, 1962)
%Z
The time zone name, or no characters if no time zone exists
Example 7-1 shows a small program that demonstrates the use of strftime and its output in several different locales (if your system does not have the internationalization options installed, all the output is in English). The setlocale function is used to set the locale; it is described in more detail in Chapter 16, Miscellaneous Routines.
Example 7-1:  date
#include <locale.h>
#include <stdio.h>
#include <time.h>
/*
* Sample formats.
*/
char *formats[] = {
    "%A, %B %e, %Y, %H:%M:%S",
    "%I:%M %p, %d-%b-%y",
    "%x %X",
    "%C",
    "%c",
    NULL
};
char *locales[] = {
    "C", "de", "fr", "it", "sv", NULL
};
char *localeNames[] = {
    "UNIX", "German", "French", "Italian", "Swedish", NULL
};
int
main(int argc, char **argv)
{
    int i, j;
    time_t clock;
    struct tm *tm;
    char buf[BUFSIZ];
/*
     * Get current time.
     */
    time(&clock);
    tm = gmtime(&clock);
/*
     * For each locale...
     */
    for (i=0; locales[i] != NULL; i++) {
        /*
         * Print the locale name and set it.
         */
        printf("%s:\n", localeNames[i]);
        setlocale(LC_TIME, locales[i]);
/*
         * For each format string...
         */
        for (j=0; formats[j] != NULL; j++) {
            strftime(buf, sizeof(buf), formats[j], tm);
            printf("\t%-25s %s\n", formats[j], buf);
        }
printf("\n");
    }
exit(0);
}
    % date
    UNIX:
        %A, %B %e, %Y, %H:%M:%S   Sunday, March 20, 1994, 22:38:19
        %I:%M %p, %d-%b-%y        10:38 PM, 20-Mar-94
        %x %X                     03/20/94 22:38:19
        %C                        Sun Mar 20 22:38:19 GMT 1994
        %c                        Sun Mar 20 22:38:19 1994
    German:
        %A, %B %e, %Y, %H:%M:%S   Sonntag, März 20, 1994, 22:38:19
        %I:%M %p, %d-%b-%y        10:38 PM, 20-Mär-94
        %x %X                     20.03.94 22:38:19
        %C                        Sonntag, 20. März 1994, 22:38:19 Uhr GMT
        %c                        So 20 Mär 94, 22:38:19 GMT
    French:
        %A, %B %e, %Y, %H:%M:%S   dimanche, mars 20, 1994, 22:38:19
        %I:%M %p, %d-%b-%y        10:38 PM, 20-mar-94
        %x %X                     20.03.94 22:38:19
        %C                        dimanche, 20 mars 1994, 22:38:19 GMT
        %c                        dim 20 mar 94, 22:38:19 GMT
    Italian:
        %A, %B %e, %Y, %H:%M:%S   domenica, marzo 20, 1994, 22:38:19
        %I:%M %p, %d-%b-%y        10:38 PM, 20-mar-94
        %x %X                     20/03/94 22:38:19
        %C                        domenica, 20 marzo 1994, 22:38:19 GMT
        %c                        Dom 20 mar 94, 22:38:19 GMT
    Swedish:
        %A, %B %e, %Y, %H:%M:%S   söndag, mars 20, 1994, 22:38:19
        %I:%M %p, %d-%b-%y        10:38 EM, 20-mar-94
        %x %X                     94-03-20 22:38:19
        %C                        söndag, 20 mars 1994 kl 22:38:19 GMT
        %c                        sön 20 mar 94 kl 22:38:19 GMT
To perform conversions in the other direction, from a string to an internal time representation, use the getdate function:
    #include <time.h>
    struct tm *getdate(const char *string);
The getdate function converts user-defined date and time specifications pointed to by string into a struct tm structure. User-defined templates are used to parse and interpret the input string. The templates are text files created by the user and identified using the environment variable DATEMSK. Each line in the template file represents an acceptable date and/or time specification, using the same descriptors as described previously for strftime. The first template that matches the input specification is used. If successful, getdate returns a pointer to a struct tm structure; if it fails, it returns NULL and sets the external variable getdate_err to indicate the error.
The month and weekday names can contain any combination of upper- and lowercase letters. If only the weekday is given, today is assumed if the given day is equal to the current day, otherwise next week is assumed. If only the month is given, the current month is assumed if the given month is equal to the current month; otherwise, next year is assumed (unless a year is given). If no hour, minute, and second are given, the current hour, minute, and second are assumed. If no date is given, today is assumed if the given hour is later than the current hour, and tomorrow is assumed otherwise.
Example 7-2 shows an example use of the getdate function.
Example 7-2:  getdate
#include <stdio.h>
#include <time.h>
extern int getdate_err;
int
main(int argc, char **argv)
{
    struct tm *tm;
    char buf[BUFSIZ];
    for (;;) {
        /*
         * Prompt for a string.
         */
        printf("? ");
    /*
         * Read the string.
         */
        if (fgets(buf, sizeof(buf), stdin) == NULL) {
            putchar('\n');
            exit(0);
        }
    /*
         * Convert it.
         */
        if ((tm = getdate(buf)) != NULL)
            printf("%s\n", asctime(tm));
        else
            printf("Error (%d).\n", getdate_err);
    }
}
    % cat getdate.template
    %m
    %A %B %d %Y, %H:%M:%S
    %A
    %B
    %m/%d/%y %I %p
    %d,%m,%Y %H:%M
    at %A the %dst of %B in %Y
    run job at %I %p,%B %dnd
    %A den %d. %B %Y %H.%M Uhr
    % setenv DATEMSK getdate.template
    % getdate
    ? 10/1/87 4 PM
    Thu Oct  1 16:00:00 1987
    ? Friday
    Fri Mar 25 18:13:17 1994
    ? Friday September 18 1987, 10:30:30
    Fri Sep 18 10:30:30 1987
    ? 24,9,1986 10:30
    Wed Sep 24 10:30:00 1986
    ? at monday the 1st of december in 1986
    Mon Dec  1 18:13:23 1986
    ? run job at 3 PM, december 2nd
    Fri Dec  2 15:00:00 1994
    ? ^D
Porting Notes
The ctime and asctime functions are common to all versions of UNIX; the other functions are less widespread.
The getdate function conflicts with a public domain function of the same name that is used in many programs. The public domain function attempts to produce a time_t given an arbitrary date string; it performs all the magic necessary to determine what format the string is in. The purpose of this function is to allow users to input dates and times in whatever format they're used to, without having to predetermine what format that is. Generally speaking, the public domain function is significantly more useful than the function provided by SVR4.

Previous SectionNext Section
Books24x7.com, Inc © 2000 –  Feedback