Time and Date Processing In C (by Chuck Allison)

zhaozj2021-02-16  63

Time and Date Processing In C

Chuck Allison

-------------------------------------------------- ------------------------------

Chuck Allison is a software architect for the Family History Department of the Church of Jesus Christ of Latter Day Saints Church Headquarters in Salt Lake City. He has a BS and MS in mathematics, has been programming since 1975, and has been teaching and developing in C since 1984. His current interest is object-oriented technology and education. He is a member of X3J16, the ANSI C Standards Committee. Chuck can be reached on the Internet at allison@decus.org, or at (801)240-4510 .

Most operating systems have some way of keeping track of the current date and time. ANSI C makes this information available in various formats through the library functions defined in time.h. The time function returns a value of type time_t (usually a long), Which is an importation-dependent encoding of the current date and time. You in Turn Pass this value to other functions Which Decode and format it.

THE PROGRAM in Listing 1 Uses The Functions Time, Localtime and Strftime To Print The Current Date And Time In Various Formats. The localtime function breaks the Encode Time Down Into

StructTM {INTTM_SEC; / * (0 - 61) * / INTTM_MIN; / * (0 - 59) * / INTTM_HOUR; / * (0 - 23) * / INTTM_MDAY; / * (1 - 31) * / INTTM_MON; / * (0 - 11) * / INTTM_YEAR; / * PAST 1900 * / INTTM_WDAY; / * (0 - 6) * / INTTM_YDAY; / * (0 - 365) * / INTTM_ISDST; / * daylight savings flag * /};. local time overwrites a static structure each time you call it, and returns its address (therefore only one such structure is available at a time in a program without making an explicit copy) The ctime function returns a pointer to a static string which contains the full time and date in a standard format (including a terminating newline). strftime formats a string according to user specifications (eg,% A represents the name of the day of the week). See Table 1 For The Complete List of Format Descriptors.

Time / Date ArithmeticYou can do time / date arithmetic by changing the values ​​in a tm structure. The program in Listing 2 shows how to compute a date a given number of days in the future, as well as the elapsed execution time in seconds. Note the optional alternate syntax for the time function (the time_t parameter is passed by reference instead of returned as a value). The mktime function alters a tm structure so that the date and time values ​​are within the proper ranges, after which the day-of -week (tm_wday) and day-of-year (tm_yday) fields are updated accordingly. mktime brings the date and time values ​​in the tm structure into their proper ranges, and updates the day of week (tm-wday) and day of year (tm-yday) values ​​accordingly. This occurs when a date falls outside the range that your implementation supports. My MS-DOS-based compiler, for example, can not encode dates before January 1, 1970, but VAXC can process dates as early as The MID-1800S. The Asctime Function Returns The Standar d string for the time represented in tm parameter (so ctime (& tval) is equivalent to asctime (localtime (& tval)). The function difftime returns the difference in seconds between two time_t encodings as a double.

If you need to process dates outside your system's range or calculate the interval between two dates in units other than seconds, you need to roll your own date encoding. The application in Listing 3 through Listing 5 shows a technique for determining the number of years, months and days between two dates, using a simple month-day-year structure. It subtracts one date from another, much as you might have done in elementary school (ie, it subtracts the days first, borrowing from the month's place if necessary, and so on). Note that leap years are taken into account. For brevity, the date_interval function assumes that the dates are valid and that the first date entered precedes the second. Following the lead of the functions in time.h, It returns a pointer to a static Date structure which holds the answer.File Time / Date StampsMost operating systems maintain a time / date stamp for files. At the very least, you can find out when a file was last modified. (The common make facility uses th is information to determine if a file needs to be recompiled, or if an application needs to be relinked). Since file systems vary across platforms, there can be no universal function to retrieve a file's time / date stamp, so the ANSI standard doesn ' t define one. However, most popular operating systems (including MS-DOS and VAX / VMS) provide the UNIX function stat, which returns pertinent file information, including the time last modified expressed as a time_t. The program in Listing 6 uses stat and Difftime to See eti the file time1.c is newer Than (IE, WAS Modified More Recently Than) Time2.c.

If you need to update the time / date stamp of a file to the current time, simply overwrite the first byte of a file with itself. Although the contents have not changed, your file system will think it has, and will update the time / date stamp accordingly. (Know your file system! Under VAX / VMS, you get a newer version of the file, while the older version is retained). This is sometimes called "touching" a file. The implementation of touch in Listing 7 creates the file if it does not already exist Note that the file is opened in "binary" mode. (indicated by the character b in the open mode string - I'll discuss file processing in detail in a future capsule) .Table 1 Format Descriptors for strftime

Code Sample Output -------------------------------------------% a WED% A WedneSDay% B OCT% B October% C WED OCT 07 13:24:27 1992% D 07 (DAY of MONTH [01-31])% H 13 (HOUR IN [00-23])% i 01 ( Hourin [01-12])% j 281 (DAY of year [001-366])% m 10 (MONTH [01-12])% M 24 (Minute [00-59])% P P P PM% S 27 ( Second [00-59])% u 40 (Sunday Week Of Year [00-52])% W 3 (DAY OF WEEK [0-6])% W 40 (Monday Week Of Year [00-52])% X WED OCT 7, 1992% x 13: 24: 27% Y 92% Y 1992% Z EDT (Daylight Savings Indicator)

Listing 1 Time1.c - Prints The Current Date And Time in Various Formats

#include #include

#define buffsize 128

Main () {time_t tval; struct tm * now; char buf [buffs]; char * fancy_format = "or getting really fancy: / n" "% a,% b% d, day% j of% Y. / N" "Time IS% I:% M% P.";

/ * Get current date and time * / TVAL = time (null); now = localtime (& TVAL); Printf ("The current date and time: / n" "% D /% 02D /% 02D% D:% 02D: % 02D / N / N ", NOW-> TM_MON 1, NOW-> TM_MDAY, NOW-> TM_YEAR, NOW-> TM_HOUR, NOW-> TM_MIN, NOW-> TM_SEC); Printf (" OR in Default System Format: / N% S / N ", CTIME (& TVAL)); strftime (buf, sizeof buf, fancy_format, now); PUTS (BUF); Return 0;}

/ * OutputThe Current Date and Time: 10/06/92 12:58:00

OR in default system format: Tue Oct 06 12:58:00 1992

OR Getting Really Fancy: Tuesday, October 06, Day 280 of 1992.The Time IS 12:58 PM. * /

/ * End of file * /

Listing 2 Time2.c - Shows How To Compute A Date A Given Number of Days in The Future, As Well As The Elapsed Execution Time In Seconds

#include #include #include

Main () {Time_t Start, Stop; StructTM * now; int NDAYS;

/ * Get Current Date and Time * / Time (& Start); Now = LocalTime (& Start);

/ * ENTER An Interval in Days * / FPUTS ("How Many Days from now?", Stderr); if (Scanf ("% D", & nDAYS)! = 1) Return EXIT_FAILURE; now-> TM_MDAY = NDAYS; IF (Mktime (now)! "New Date:% S", Asctime (now); Else Puts ("Sorry. can't Encode Your Date.");

/ * Calculate Elapsed Time * / Time (& STOP); Printf ("Elapsed Program Time In Seconds:% F / N", DiffTime (STOP, START);

Return EXIT_SUCCESS;

/ * OUTPUTHOW MANY DAYS from now? 45New Date: Fri Nov 20 12:40:32 1992Elapsed Program Time In Seconds: 1.000000 * /

/ * End of file * /

Listing 3 Date.h - a Simple Date Structure

Struct Date {int day; int month; int year;}; typedef struct date; date * Date *, const date *); / * end of file * /

Listing 4 Date_int.c - Computes Time Interval Between Two Dates

/ * date_int.c: compute duration between two dates * /

#include "date.h"

#define isleap (y) / ((y)% 4 == 0 && (Y)% 100! = 0 || (Y)% 400 == 0)

Static int DTAB [2] [13] = {0, 31, 28, 31, 30, 31, 30, 31}, {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};

Date * Date_Interval (const date * d1, const date * d2) {static date result; int MONTHS, DAYS, YEARS, PREV_MONTH;

/ * Compute the interval - Assume D1 precedes d2 * / years = d2-> year - d1-> year; months = d2-> month - d1-> month; days = d2-> day - d1-> day;

/ * Do Obvious Corrections (Days Before Months!) * * This is a loop in case the previous month is * february, and days <-28. * / Prev_month = d2-> month - 1; while (days <0) { / * Borrow from the previous month * / if (prev_month == 0) prev_month = 12; --Months; days = DTAB [Isleap (D2-> Year)] [prev_month--];}

IF (Months <0) {/ * borrow from the prepious year * / --year; months = 12;

/ * Preted output * / result.month = months; result.day = days; result.year = years; return & result;} / * end of file * /

Listing 5 TDATE.C - Illustrates The Date_Interval Function

/ * TDATE.C: Test Date_Interval () * /

#include #include #include "date.h"

Main () {DATE D1, D2, * RESULT; int NARGS;

/ * Read in Two Dates - Assume 1st Precedes 2nd * / fputs ("Enter a Date, MM / DD / YY>", stderr); Nargs = Scanf ("% D /% D /% D% * C", & D1 .month, & d1.day, & d1.year); if (Nargs! = 3) Return EXIT_FAILURE; FPUTS ("Enter a Later Date, MM / DD / YY>", stderr); NARGS = Scanf ("% D /% D /% D% * C ", & D2.MONTH, & D2.DAY, & D2.YEAR); if (NARGS! = 3) Return EXIT_FAILURUR

/ * Compute Interval in Years, Months, And Days * / Result = DATE_INTERVAL (& D1, & D2); Printf ("Years:% D, MONTHS: D, DAYS:% D / N", Result-> Year, Result- > MONTH, RESULT-> Day); RETURN EXIT_SUCCESS;

} / * Sample EXECUTION: ENTER A DATE, MM / DD / YY> 10/1 / 51ENTER A LATER DATE, MM / DD / YY> 10/6 / 92Years: 41, Months: 0, Days: 5 * // * END OF FILE * /

Listing 6 ftime.c - determines if Time1.c is newer Time2.c

/ * ftime.c: compare file time stamps * /

#include #include #include #include

Main () {struct stat fs1, fs2;

IF (Stat ("Time1.c", & FS1) == 0 && Stat ("Time2.c", & FS2) == 0) {Double Interval = DiffTime (fs2.st_mtime, fs1.st_mtime);

Printf ("TIME1.C% S NEWER THAN TIME2.C / N", (Interval <0.0)? "IS": "is not"); return exit_success;} else return exit_failure;} / * OutputTime1.c is not newer Than Time2.c * // * End of file * /

Listing 7 Touch.c - Updates Time Stamp by overwriting old file or create the file if it doesn't exist

/ * Touch.c: Update a file's time stamp * /

#include

Void touch (char * fname) {file * f = fopen (FNAME, "R B"); if (f! = null) {char c = getc (f); Rewind (f); PUTC (C, F) Else Fopen (FNAME, "WB"); fclose (f);}

/ * End of file * /

转载请注明原文地址:https://www.9cbs.com/read-17161.html

New Post(0)