home *** CD-ROM | disk | FTP | other *** search
- /*
- * util.c : Some miscellaneous routines for handling dates.
- *
- * George Ferguson (ferguson@cs.rochester.edu), 27 Oct 1990.
- *
- * $Id: util.c,v 1.1 90/10/28 13:05:14 ferguson Exp $
- *
- */
-
- #include <sys/time.h>
- #include <ctype.h>
- extern char *shortMonStr[];
-
- /*
- * Functions defined here:
- */
- int computeDOW(), firstDOW(), lastDay();
- void getCurrentDate();
- int parseDate();
-
- /*
- * Global data
- */
- static int mon_max[] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
-
- /* - - - - - - - - */
- /*
- * computeDOW(day,mon,year) : Returns the day of the week for the
- * requested date (0=Sunday, 1=Monday, etc).
- * This newer, faster, method is courtesy findeis@alberta.
- */
- int
- computeDOW(d,m,y)
- int d,m,y;
- {
- static int dp [12] = {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5};
- register int y4, s;
-
- y = y - 1; /* actually y - 1901 */
- s = (y/4) * 5;
- y4 = y % 4;
- if ((y4 == 3) && (m>1)) s++;
- s = s + y4 + dp[m] + d + 1;
- return (s % 7);
- }
-
- /*
- * firstDOW(mon,year) : Returns the doy of the week for the first
- * day of the given month and year.
- */
- int
- firstDOW(mon,year)
- int mon,year;
- {
- return(computeDOW(1,mon,year));
- }
-
- /*
- * lastDay(mon,year) : Returns the last day of the requested
- * month (and handles leap years, etc).
- */
- int
- lastDay(mon,year)
- int mon,year;
- {
- if ((mon == 1)&&(dysize(year+1900) == 366))
- return(29);
- else return(mon_max[mon]);
- }
-
- /*
- * nextDay(d,m,y) : Increment d,m,y to the next day
- */
- void
- nextDay(dp,mp,yp)
- int *dp,*mp,*yp;
- {
- if (*dp != lastDay(*mp,*yp))
- *dp += 1;
- else {
- *dp = 1;
- if (*mp != 11)
- *mp += 1;
- else {
- *mp = 0;
- *yp += 1;
- }
- }
- }
-
- /*
- * prevDay(d,m,y) : Decrement d,m,y to the previous day
- */
- void
- prevDay(dp,mp,yp)
- int *dp,*mp,*yp;
- {
- if (*dp != 1)
- *dp -= 1;
- else {
- if (*mp != 0)
- *mp -= 1;
- else {
- *yp -= 1;
- *mp = 0;
- }
- *dp = lastDay(*mp,*yp);
- }
- }
-
- /* - - - - - - - - */
- /*
- * getCurrentDate() : What else?
- */
- void
- getCurrentDate(dp,mp,yp)
- int *dp,*mp,*yp;
- {
- struct timeval t;
- struct timezone tz;
- struct tm *r;
-
- gettimeofday(&t,&tz);
- r = localtime(&(t.tv_sec));
- *dp = r->tm_mday;
- *mp = r->tm_mon;
- *yp = r->tm_year;
- }
-
- /* - - - - - - - - */
- /*
- * parseDate(text,dp,mp,yp) : Parse the string text into a date which is
- * either an absolute or a relative date as follows:
- *
- * rel date = [+-]{<num>[dmy]}*
- * abs date = [<day><mon><year>]* where <day> = <num> less than 32
- * <mon> = <string>
- * <year>= <num> greater than 32
- * The variables pointed to by dp,mp,yp are filled in with the new date.
- * Whitespace is skipped.
- * Returns -1 if the date was garbled, else 0.
- */
- int
- parseDate(text,dp,mp,yp)
- char *text;
- int *dp,*mp,*yp;
- {
- int day,mon,year,last,num,sign,i;
-
- day = mon = year = 0;
- last = lastDay(*mp,*yp);
- if (*text == '+' || *text == '-') { /* relative date */
- sign = *text++; /* save sign */
- while (*text) { /* parse string... */
- while (isspace(*text)) /* skip white space */
- text += 1;
- num = 0;
- while (*text >= '0' && *text <= '9') { /* get a number */
- num = num * 10 + *text - '0';
- text += 1;
- }
- switch(*text) { /* and a specifier */
- case '\0': /* no specifier => days */
- case 'D' :
- case 'd' : day = num;
- break;
- case 'M' :
- case 'm' : mon = num;
- break;
- case 'Y' :
- case 'y' : year = num;
- break;
- default: return(-1);
- }
- if (*text != '\0') /* continue unless at end */
- text += 1;
- }
- if (sign == '+') { /* now set the `current' date */
- *dp += day;
- if (*dp > last) {
- *dp -= last;
- *mp += 1;
- }
- *mp += mon;
- if (*mp > 11) {
- *mp -= 12;
- *yp += 1;
- }
- *yp += year;
- } else {
- *yp -= year;
- *mp -= mon;
- if (*mp < 0) {
- *mp += 12;
- *yp -= 1;
- }
- *dp -= day;
- if (*dp < 1) {
- *mp -= 1;
- if (*mp < 0) {
- *mp = 11;
- *yp -= 1;
- }
- *dp += last;
- }
- }
- } else { /* absolute date */
- while (*text) {
- while (isspace(*text)) /* skip white space */
- text += 1;
- num = 0;
- while (*text >= '0' && *text <= '9') { /* try a number */
- num = num * 10 + *text - '0';
- text += 1;
- }
- if (num == 0) { /* no number try a month */
- if (islower(*text))
- *text = toupper(*text);
- for (i=0; i < 12 && strcmp(text,shortMonStr[i]) != 0; i++) ;
- if (i == 12) {
- return(-1);
- } else {
- *mp = i;
- text += 3;
- }
- } else if (num < 32) /* number was either day or year */
- *dp = num;
- else if (num >= 1900)
- *yp = num - 1900;
- else *yp = num;
- }
- }
- return(0);
- }
-