jac@yoko.rutgers.edu (Jonathan A. Chandross) (05/31/91)
Submitted-by: Andy Werner (st6934@siucvmb.bitnet) Posting-number: Volume 1, Source:50 Archive-name: util/hyperc/time/time_util Architecture: ANY_2 Version-number: 1.00 Some more complex time functions, including Gregorian <--> Julian conversion and date --> day of the week. Enjoy. =Read.Me -time_util -Version 1.00 - -More HyperC Time Functions: - -The following files were ported to HyperC from the book: - -Common C Functions by Kim Jon Brand published by Que Corporation 1985. - -zeller.c : Given a date, returns the day of week -jul.c : Given a date, returns the Julian date (the day of year) -revjul.c : Given a Julian date and base year, returns the date - -scanf.c : By Eric Mcgillicuddy, used in the demo portion of the source. -setmem.c : Used in revjul.c - -To compile, place all of the files in the same directory, and type: -cc (or ccn) <filename without the .c at the end> - -Feedback welcome. - - Andy Werner - st6934@siucvmb.bitnet - =Manifest - -Read.Me -jul.c -revjul.c -scanf.c -setmem.c -zeller.c - =jul.c - -/* module name : jul.c - * function name : unsigned int jul() - * author : Kim J. Brand - * revision history : - * |-version-|--date--|-by reason-| - * 1.0 10/01/84 kb COMMON_C_FUNCTIONS initial release - * compiled with : HyperC for the Apple II; std.h, scanf.c - * linked with : s.o, libc - * linked by : Andy Werner - st6934@siucvmb.bitnet - 3/26/91 - * problems : Julian dates 0-3 reserved for error indicators - NOT! - * description : returns the julian date from the date string based on a - * base year given ( the year may be 2 or 4 digits, as the - * function assumes that 2 = digit years < base year are in - * the next century). - */ - -#include <std.h> -#include "scanf.c" - -/* #include "macros.h" (this was included according to book cited above. */ - -#define MO 0 -#define DAY 1 -#define YR 2 - -#define BAD_DIGIT (-1) -#define BAD_MONTH 367 -#define BAD_DAY 368 -#define BAD_YEAR 369 - -#define DEMO - -UINT jul(date, base) /* Returns unsigned int Julian date from string at - * date in MM/DD/YY format; Julian base year given by - * base; day of year returned if base year is the - * same as date year. - */ - -CHAR *date; /* pointer to d-o-w string is returned from this initialized - * array of pointers to characters - */ - -INT base; - -{ - LOCAL INT days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - -/* Make a lookup table for the days in each month indexed by the month in the - * year. - */ - - CHAR ch ; /* all purpose character variable */ - INT n = 0 ; /* starting index in input string */ - - INT mdy[3]; /* array holding the three values created from input string - * month, day, year. - */ - - UINT retjul; /* becomes return value */ - - /* start at zero in each 'register' */ - - days[2] = 28; /* static array created at compile time and assumed to be - * permanent; corrects any changes that may have occurred - * to February - */ - -mdy[MO] = mdy[DAY] = mdy[YR] = 0; /* initialize array values */ - -while (ch = *date++) /* parse string, through to end */ -{ - if (ch == '-' || ch == '/') /* legal separators are '-', '/' */ - { - ++n; - continue; - } - if (isdigit(ch)) /* was (!isdigit(ch)) but didn't work */ - - mdy[n] = 10 * mdy[n] + (ch - '0'); /* adds new digit to total for this */ - /* place, a very simplified atoi() */ - /* that relies on ascii sequences */ - -/* This print statement was used for debugging */ - -/* -printf("\nmdy[MO]=%d, mdy[DAY]=%d, mdy[YR]=%d\r", mdy[MO], mdy[DAY], mdy[YR]); - */ - -} - if (mdy[MO] < 1 || mdy[MO] > 12) /* purge bad months */ - return(BAD_MONTH); - -/* If there are only two digits, two-digit years before 1980 are assumed to - be in the next century; two digit years after the base year are assumed - to be in this century. The translation becomes (if base == 1980); - 0-79 = 2000-2079 80-99 = 1980-1999 - */ - - - if (mdy[YR] < 100) /* only two digits? */ - { - if (mdy[YR] < base - 1900) /* prior to base year digits are */ - mdy[YR] += 2000; /* assumed to be in the next century */ - else - - mdy[YR] += 1900; /* 01 -> 2001 will make 84 1984 */ - } - if (mdy[YR] < base) /* return bad years */ - return (BAD_YEAR); - - if (mdy[YR] % 4 == 0 && mdy[YR] % 100 != 0 || mdy[YR] % 400 == 0) - - days[2] = 29; /* set Februrary days to 29 if leap yr */ - - if (mdy[DAY] < 1 || mdy[DAY] > days[mdy[MO]]) - return (BAD_DAY); /* return bad days */ - - retjul = mdy[DAY]; /* set jul equal to days */ - /* in current month */ - - for (n = 1; n < mdy[MO]; n++) - - { - retjul += days[n]; -/* printf("n=%d, days[n]=%d, retjul=%d \r", n, days[n], retjul); */ - } - - for (n = base; n < mdy[YR]; n++) - - { - - if (n % 4 == 0 && n % 100 != 0 || n % 400 == 0) - - retjul += 366; - - else - - retjul += 365; -/* printf("days[n]=%d, retjul=%d \r", days[n], retjul);*/ - } /* these printf statements used to debug */ -/* printf("n=%d, days[n]=%d, retjul=%d \r", n, days[n], retjul);*/ - return (retjul); -} - -#ifdef DEMO - -main() -{ - CHAR buff [10]; /* place to build input */ - INT base; - UINT jul(); /* watch for systems that don't flush non-newline - * terminated strings. You may need to fflush() - * after each printf() - */ - { - printf("Example: base year = 1984, date = 12/31/84\r"); - printf("\rReturns : 366\r"); - printf("\rAnother example: base year = 1953, date = 5/7/1984\r"); - printf("\rReturns : 11450\r"); - printf("\nEnter base year (19yy): "); - scanf("%d",&base); - printf("\nEnter a date (MM/DD/YY or MM/DD/YYYY): "); - scanf("%s",buff); - printf("\nThe Julian date is: %u\r\r", jul(buff, base)); - } - /* print day of week for date entered */ -} - -#endif =revjul.c -/* module title: revjul.c - * function name: char *revjul() - * main() for demo - * - * author: Kim J. Brand - * - * revision history: - * version/--date--/by reason-------------------------------------------- - * 1.0 10/01/84 kb COMMON_C_FUNCTIONS initial release - * - * compiled with: HyperC - std.h, scanf.c - * compiled by: Andy Werner - st6934@siucvmb.bitnet - 3/27/91 - * linked with: s.o, libc (int twodates()) - * linked by: Andy Werner - st6934@siucvmb.bitnet - * - * problems: - * - * description: converts a Julian number into a date string - * - */ - -#include <std.h> -#include "scanf.c" -#include "setmem.c" - -#define DEMO - -CHAR *revjul(jul,year) /* returns pointer to string that */ -INT jul; /* is calendar date for this */ -INT year; /* Julian date in form mm/dd/yy */ - -{ - /* number of days in each month */ - /* indexed by the month in the year*/ - - LOCAL INT days[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - - LOCAL CHAR date[11];/* a place for returned date string*/ - /* including the null, must be */ - /* static or will evaporate */ - - INT days_year; /* the days/year for a given year */ - INT n = 1; /* an index into the days/month */ - - setmem(date, sizeof(date), 0); /* must fill with nulls so */ - /* strlen knows where date ends */ - - days[2] = 28; /* fix February if changed */ - - do - { - if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) - days_year = 366; - else - days_year = 365; - - year++, jul -= days_year; /* increment the year and */ - } /* test that does not */ - /* go over top */ - while (jul > 0); - year--, jul += days_year; /* reverse the effect of going */ - /* too far */ - - if (days_year == 366) /* if current year is leap */ - days[2] = 29; /* fix February */ - - do - jul -= days[n++]; /* subtract days from each */ - while (jul > 0); /* month until jul < 0 */ - - /* n holds month number */ - --n, jul += days[n]; /* jul has day of month */ - - year = (year > 1999 ? year : year - 1900); - - sprintf(date, "%d/%d/%d", n, jul, year); /* at date build string*/ - - return (date); /* that returns a pointer */ - /* to the string */ -} - -#ifdef DEMO - -main() /* a simple demonstration main() */ - -{ - INT jul; - INT base; - - CHAR *revjul(); - - { - printf("\nExample: Julian date = 11450, base year = 1953\r"); - printf("\nReturns: 5/7/84\r"); - printf("\n\rAnother example: Julian date = 366, base year = 1984\r"); - printf("\nReturns: 12/31/84\r\r"); - printf("\nEnter Julian date: "); - scanf("%d", &jul); - printf("\nEnter base year: "); - scanf("%d", &base); - printf("\nDate = %s\n", revjul(jul, base)); - } -} =scanf.c -/* scanf.c utility function Formatted input for HyperC */ - -/* #include <std.h> */ - -#define BUFSIZ 100 -#define TRUE 1 -#define FALSE 0 - -INT scanf(fmt,args) -TEXT *fmt; -INT *args; - -{ -TEXT buf[BUFSIZ], temp[BUFSIZ]; -TEXT *str, *ptr; -INT maxchars, nargs, i, **arv; -BOOL ignore, space; -CHAR fctl; - -LOCAL INT convert() -{ -INT val; -CHAR fctl; - -val=0; -while (isdigit(*fmt)) - val = 10*val + *fmt++ -'0'; -if (!val) - switch (fctl =*fmt) { - case 'd': - case 'D': - val = 6; - break; - - case 'i': - case 'I': - val = 8; - break; - - case 'u': - case 'U': - val = 5; - break; - - case 'o': - case 'O': - val = 6; - break; - - case 'x': - case 'X': - val = 4; - break; - - case 'h': - case 'H': - val = 3; - break; - - case 'c': - case 'C': - val = 1; - break; - - default: - val = BUFSIZ - 2; - break; - } - return ((val > BUFSIZ-2) ? BUFSIZ-2 : val); -} - -LOCAL VOID strcopy (dest, src) -CHAR *src, *dest; -{ - while (*dest++ = *src++) - ; -} - -arv=&args; -nargs=0; -ignore = FALSE; -space = FALSE; -conRead (buf, BUFSIZ); -str = buf; -while (*fmt) { - if (*fmt == ' ') - space = TRUE; - if (*fmt++ == '%') { - if (*fmt == '*') { /* suppression character, useless but k&r use it*/ - ignore = TRUE; - ++fmt; - } - maxchars = convert(); - ptr = temp; - for (i =0; i < maxchars; i++) { - if (isspace(*str) && space) { - str++; - break; - } - *ptr++ = *str++; - } - *ptr = '\0'; - ptr = temp; - if (!ignore) - switch (fctl = *fmt++) { - case 'd': - case 'D': - case 'i': - case 'I': - **arv = atoi (&ptr); - break; - - case 'u': - case 'U': - if (*ptr =='-') - *ptr=' '; - **arv = atoi (&ptr); - break; - - case 'o': - case 'O': - movel (ptr,ptr+1,8); - ptr[0] = '0'; - **arv = atoi (&ptr); - break; - - case 'x': - case 'X': - movel (ptr,&ptr[2],6); - *ptr = '0'; /* add '0x' prefix to string to make atoi work*/ - ptr[1] = 'x'; - **arv = atoi (&ptr); - break; - - case 'h': - case 'H': - **arv = atoi (&ptr); - break; - - case 'c': - case 'C': - **arv = *ptr; - break; - - case 'n': - case 'N': - arv++; - break; - - case 's': - case 'S': - strcopy (*arv, ptr); - break; - - default: - **arv = '\0'; - break; - } /*end switch */ - arv++; - ++nargs; - fmt--; /* clean up control string pointer */ - } /* end if '%' */ - } /* end while */ -return (nargs); -} /*end scanf */ - =setmem.c - -/* module title: setmem.c - * function name: void setmem() - * - * author: Kim J. Brand - * revision history: - * version/--date--/by reason------------------------------------------------- - * 1.0 10/01/84 kb COMMON_C_FUNCTIONS initial release - * - * compiled with: std.h - * compiled by: Andy Werner - st6934@siucvmb.bitnet - 3/26/91 - * compiled with: revjul.c - * linked by: Andy Werner - st6934@siucvmb.bitnet - 3/26/91 - * - * problems: - * - * description: initializes a block of memory pointed to by addr for length - * given by size with val - * - */ - -VOID setmem(addr, size, val) /* fill, starting at addr, for size, w/ val */ -CHAR *addr; -UINT size; -CHAR val; - { - while(size--) /* fill up sequential bytes of memory */ - *addr++ = val; /* until size counted down to zero */ - } =zeller.c - -/* module name : zeller.c - * function name : char * zeller() - * author : Kim J. Brand - * revision history : - * |-version-|--date--|-by reason-| - * 1.0 10/01/84 kb COMMON_C_FUNCTIONS initial release - * compiled with : HyperC for the Apple II; std.h, scanf.c - * linked with : s.o, libc - * linked by : Andy Werner - st6934@siucvmb.bitnet 4/25/91 - * problems : scanf.c reads the /r and messes up calculation - fixed. - * description : produces Zeller congruence, given a pointer to the date string - * passed, in format mm/dd/yy or mm/dd/yyyy and returns a pointer - * to a string indicating the day of week that the date falls on - * (separator may also be a hyphen). - * parameter : pointer to string passed to zeller() - * returns : day of week - */ - -#include <std.h> -#include "scanf.c" - -/* #include "macros.h" (this was included according to book cited above. */ - -#define Int(x) ((INT) (x)) /* macro defined for zeller to work - needed? */ - /* macro also defined in 'macros.h' above */ -#define MO 0 -#define DAY 1 -#define YR 2 - -#define BAD_DIGIT (-1) - -#define DEMO - -CHAR *zeller(date) /* receive pointer to date string; - * return pointer to day-of-week string - */ -CHAR *date; /* pointer to d-o-w string is returned from this initialized - * array of pointers to characters - */ - -{ - CHAR ch ; /* all purpose character variable */ - INT n = 0 ; /* starting index in input string */ - INT month; /* temporary variables */ - INT year; /* with obvious uses */ - INT century; - INT offset; /* offset of year in century */ - INT mdy[3]; /* array holding the three values created from input string - * month, day, year. - */ - - -LOCAL CHAR *day[] = {"Sunday","Monday","Tuesday","Wednesday", - "Thursday","Friday","Saturday"}; - -mdy[MO] = mdy[DAY] = mdy[YR] = 0; /* initialize array values */ - -while (ch = *date++) /* parse string, through to end */ -{ - if (ch == '-' || ch == '/') /* legal separators are '-', '/' */ - { - ++n; - continue; - } - if (isdigit(ch)) /* was (!isdigit(ch)) to return error */ - - mdy[n] = 10 * mdy[n] + (ch - '0');/* adds new digit to total for this */ - /* place, a very simplified atoi() */ - /* that relies on ascii sequences */ - -/* This print statement was used for debugging */ - -/* -printf("\nmdy[MO]=%d, mdy[DAY]=%d, mdy[YR]=%d\r", mdy[MO], mdy[DAY], mdy[YR]); - */ - -} - if (mdy[YR] < 100) - - mdy[YR] += 1900; /* accept 2-digit dates for this century*/ - - if (mdy[MO] > 2) - { - month = mdy[MO] - 2; /* adjust year & month based on February*/ - year = mdy[YR]; - } - else - { - month = mdy[MO] + 10; - year = mdy[YR] - 1; - } - -century = year / 100; /* century as 2-digit number */ - -offset = year % 100; /* years into century */ - -/* These print statements were used for debugging */ - -/* printf("\ncentury=%d, year=%d, offset=%d\r",century, year, offset); - * - * printf("\nmonth=%d, mdy[MO]=%d, mdy[DAY]=%d\r",month, mdy[MO], mdy[DAY]); - */ - -/* a magic formula for which we must give credit to Zeller */ - -n = Int((13 * month - 1) / 5) + mdy[DAY] + offset + Int(offset / 4) - + Int(century / 4) - 2 * century + 77; - -n = n - 7 * (n / 7); - -return (day[n]); -} - -#ifdef DEMO - -main() -{ - CHAR buff [40]; /* place to build input */ - CHAR *zeller(); - printf("\nThe zeller function calculates the day for a given date.\r"); - printf("\nEnter a date (MM/DD/YY or MM/DD/YYYY): "); - scanf("%s",buff); - printf("\nThe day is: %s\r\r",zeller(buff)); - /* print day of week for date entered */ -} - -#endif + END OF ARCHIVE