/* mdate.c mods: lrl 930719: cleaned up the code a little lrl 910815: Added "h" option to displacement. Corrected problem where, with a format specified with no displacement, mdate would think the format was a date string. */ #include #include #include #define SYSOK 0 #define SYSERR 1 int isleap(int year) { int leap; leap = 0; if ( (year % 4 ) == 0) leap = 1; if ( (year % 100 ) == 0) leap = 0; if ( (year % 400 ) == 0) leap = 1; if ( (year % 4000 ) == 0) leap = 0; return leap; } time_t timeparse(char *sdate) { int i; char savch; char *spnt, *allmons, *oztime; char *getenv(char *vv); time_t thyme; char tzone[4]; static int monlen[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; int month, day, year, hour, minute, second; spnt = sdate; /* first, find the beginning of the string by finding the first non-blank character */ while ( (*spnt == ' ') && (*spnt != NULL) ) spnt++; /* if this is a digit, then we are using the mmddhhnn[[cc]yy] format */ if (isdigit( (int)*spnt)) { tzone[0] = '?' ; tzone[1] = '?' ; tzone[2] = '?' ; tzone[3] = NULL; /* get the month */ month = 0; for ( i = 0; i < 2; i++ ) { if (isdigit( (int)*spnt)) { month = month * 10 + (*spnt - '0'); } else { fprintf(stderr," Bad date string: %s \n",sdate); fprintf(stderr," The month is bad. \n"); exit(SYSERR); } spnt++; } /* get the day of the month */ day = 0; for ( i = 0; i < 2; i++ ) { if (isdigit( (int)*spnt)) { day = day * 10 + (*spnt - '0'); } else { fprintf(stderr," Bad date string: %s \n",sdate); fprintf(stderr," The day of the month is bad. \n"); exit(SYSERR); } spnt++; } /* get the hour of the day */ hour = 0; for ( i = 0; i < 2; i++ ) { if (isdigit( (int)*spnt)) { hour = hour * 10 + (*spnt - '0'); } else { fprintf(stderr," Bad date string: %s \n",sdate); fprintf(stderr," The hour of the day is bad. \n"); exit(SYSERR); } spnt++; } /* get the minute of the hour */ minute = 0; for ( i = 0; i < 2; i++ ) { if (isdigit( (int)*spnt)) { minute = minute * 10 + (*spnt - '0'); } else { fprintf(stderr," Bad date string: %s \n",sdate); fprintf(stderr," The minute of the hour is bad. \n"); exit(SYSERR); } spnt++; } /* get the second of the minute to 0 */ second = 0; if (*spnt != NULL) { /* get the year */ year = 0; for ( i = 0; i < 2; i++ ) { if (isdigit( (int)*spnt)) { year = year * 10 + (*spnt - '0'); } else { fprintf(stderr," Bad date string: %s \n",sdate); fprintf(stderr," The year is bad. \n"); exit(SYSERR); } spnt++; } /* but wait--is there more? */ if (*spnt != NULL) /* full 4 digits in the year? */ { /* get the rest of the year */ for ( i = 0; i < 2; i++ ) { if (isdigit( (int)*spnt)) { year = year * 10 + (*spnt - '0'); } else { fprintf(stderr," Bad date string: %s \n",sdate); fprintf(stderr," The year is bad. \n"); exit(SYSERR); } spnt++; } } else { year = year + 1900; /* only two digits in the year */ if ( year < 1920 ) year = year + 100; /* remain valid past the year 2000 */ } } else { /* no year--complain */ fprintf(stderr," Bad date string: %s \n",sdate); fprintf(stderr," The year must be specified. \n"); exit(SYSERR); } } else { /* the full string format must have been used */ /* This should be one of the days of the week. Save the 4rth char and replace it with NULL, terminating a (tentative) day-of-the-week string, which can then be checked against all the days of the week. */ allmons = strdup("SunMonTueWedThuFriSat"); i = 0; while ( (strncmp(&allmons[3*i],spnt,3) != 0) && (i < 7)) i++; if ( i < 7 ) { /* Advance to the next field, which should be the month */ while ( (*spnt != ' ') && (*spnt != NULL)) spnt++; while ( (*spnt == ' ') && (*spnt != NULL)) spnt++; } /* if no match was made, this is probably an error, but we will just assume that the user got lazy and simply did not include a day of the week. */ /* Now find out which day of the month we are using */ allmons = strdup("JanFebMarAprMayJunJulAugSepOctNovDec"); i = 0; while ( (strncmp(&allmons[3*i],spnt,3) != 0) && (i < 12)) i++; if ( i < 12 ) { month = i + 1; } else { fprintf(stderr," Bad date string: %s \n",sdate); fprintf(stderr," The month must be in the form Jan, Feb, etc.\n"); exit(SYSERR); } /* scan forward to the day of the month */ while ( (*spnt != ' ') && (*spnt != NULL)) spnt++; while ( (*spnt == ' ') && (*spnt != NULL)) spnt++; /* get the day of the month */ day = 0; while ( isdigit( (int)*spnt) ) { day = day * 10 + ( *spnt - '0' ); spnt++; } if (*spnt != ' ') { fprintf(stderr," Bad date string: %s \n",sdate); fprintf(stderr," The day of the month is bad. \n"); exit(SYSERR); } /* scan forward to the time of day */ while ( (*spnt != ' ') && (*spnt != NULL)) spnt++; while ( (*spnt == ' ') && (*spnt != NULL)) spnt++; /* get the time of day */ hour = 0; for ( i = 0; i < 2; i++ ) { if (isdigit( (int)*spnt)) { hour = hour * 10 + (*spnt - '0'); } else { fprintf(stderr," Bad date string: %s \n",sdate); fprintf(stderr," The hour of the day is bad. \n"); exit(SYSERR); } spnt++; } if (*spnt != ':') { fprintf(stderr," Bad date string: %s \n",sdate); fprintf(stderr," The first time separator is bad. \n"); exit(SYSERR); } spnt++; /* get the minute of the hour */ minute = 0; for ( i = 0; i < 2; i++ ) { if (isdigit( (int)*spnt)) { minute = minute * 10 + (*spnt - '0'); } else { fprintf(stderr," Bad date string: %s \n",sdate); fprintf(stderr," The minute of the hour is bad. \n"); exit(SYSERR); } spnt++; } if (*spnt != ':') { fprintf(stderr," Bad date string: %s \n",sdate); fprintf(stderr," The second time separator is bad. \n"); exit(SYSERR); } spnt++; /* get the second of the minute */ second = 0; for ( i = 0; i < 2; i++ ) { if (isdigit( (int)*spnt)) { second = second * 10 + (*spnt - '0'); } else { fprintf(stderr," Bad date string: %s \n",sdate); fprintf(stderr," The second of the minute is bad. \n"); exit(SYSERR); } spnt++; } if (*spnt != ' ') { fprintf(stderr," Bad date string: %s \n",sdate); fprintf(stderr," There should be a space after the time. \n"); exit(SYSERR); } /* scan forward to the time zone */ while ( (*spnt != ' ') && (*spnt != NULL)) spnt++; while ( (*spnt == ' ') && (*spnt != NULL)) spnt++; /* get the time zone */ strncpy(tzone,spnt,3); tzone[3] = NULL; /* skip ahead to the year */ while ( (*spnt != NULL && ! isdigit( (int)*spnt) ) ) spnt++; /* get the year */ year = 0; for ( i = 0; i < 4; i++ ) { if (isdigit( (int)*spnt)) { year = year * 10 + (*spnt - '0'); } else { fprintf(stderr," Bad date string: %s \n",sdate); fprintf(stderr," The year is bad.\n"); exit(SYSERR); } spnt++; } } /* ok, at this point, we have the year, month, day, hour, minute, and second. now we need to combine these into the number of seconds since 00:00:00 GMT, January 1, 1970 */ thyme = 0; /* First, add in all the seconds which have passed until the beginning of the desired year */ for ( i = 1970; i < year; i++ ) thyme += ( 365 + ( isleap(i) ? 1 : 0) ) * 24 * 3600; /* Next, add in all the seconds which have passed until the beginning of the desired month */ for ( i = 1; i < month; i++ ) { thyme += monlen[i] * 24 * 3600; /* take care of Feb 29 */ if (isleap(year) && (i == 2)) thyme += 24 * 3600; } /* next, add in the time of the day */ thyme += ( ((day-1) * 24 + hour) * 60 + minute ) * 60 + second; /* Now we have to shift our time to GMT */ /* we cannot recognize all the timezones in the world, but we can at least try to deal with the one being used here */ if ( (oztime = getenv("TZ")) != NULL) { spnt = oztime; /* scan until we hit a digit */ while ( (! isdigit( (int)*spnt)) && (*spnt != NULL)) spnt++; if (*spnt != NULL) { hour = 0; minute = 0; second = 0; /* get the hour correction time */ while (isdigit( (int)*spnt)) { hour = hour * 10 + (*spnt - '0'); spnt++; } /* are minutes specified as well? */ if (*spnt == ':') { spnt++; /* get the minute correction time */ while (isdigit( (int)*spnt)) { minute = minute * 10 + (*spnt - '0'); spnt++; } /* are seconds specified as well? */ if (*spnt == ':') { spnt++; /* get the second correction time */ while (isdigit( (int)*spnt)) { second = second * 10 + (*spnt - '0'); spnt++; } } } } else { fprintf(stderr ," timeparse: cannot make sense of the TZ environment variable.\n"); exit(SYSERR); } /* check to make sure the time zone matches what we were given */ if ( strncmp(tzone,"???",3) == 0 ) { for (i=0; i<3; i++) tzone[i] = oztime[i]; } if ( strncmp(oztime,tzone,3) == 0 ) { thyme += (hour * 60 + minute) * 60 + second; } else if ( strncmp(spnt,tzone,3) == 0 ) { thyme += ( (hour-1) * 60 + minute) * 60 + second; } else { fprintf(stderr,"timeparse: The time zone specified did not match the TZ enviroment variable\n"); exit(SYSERR); } } else { fprintf(stderr," timeparse: Unable to obtain present time zone.\n"); fprintf(stderr," Assuming GMT.\n"); } return thyme; } main(int argc, char **argv) { int i; char prtim[30]; time_t time(), svtime, *ptime; char *inarg, *fmt; int numdays, numhours, numminutes, digit, togo; /* first, set up defaults */ numdays = 0; /* no days ahead or behind */ numhours = 0; numminutes = 0; svtime = time(0); /* use current time */ /* get each cmd line argument */ i = 1; togo = argc - 1; if ( togo > 0 ) { /* displacement field? */ if ( (argv[i][0] == '+' ) || (argv[i][0] == '-' ) ) { inarg = argv[i] + 1; while (*inarg != NULL) { digit = *inarg - '0'; if ((digit >= 0) && (digit <= 9)) { numdays = numdays*10 + digit; } else if ( digit == ('h'-'0') ) { /* numdays is hhmm instead of the number of days */ numminutes = numdays % 100 ; numhours = numdays / 100 + numminutes / 60 ; numminutes = numminutes % 60 ; numdays = numhours / 24 ; numhours = numhours % 24 ; } else { fprintf(stderr,"Improper day-delta specification: %s \n" ,argv[i]); fprintf(stderr," Usage:\n"); fprintf(stderr," mdate [ +n | -n [ date [ format ] ] ] \n"); exit(SYSERR); } inarg++; } if (argv[i][0] == '-') { numdays = 0 - numdays; numhours = 0 - numhours; numminutes = 0 - numminutes; } i++; togo--; } } if ( togo > 0 ) { /* the date specifier string */ svtime = timeparse(argv[i]); i++; togo--; } if (togo > 0 ) { fmt = argv[i]; i++; togo--; } else { fmt = "%a %b %e %H:%M:%S %Z %Y%n"; } /* now add in a correction for day-delta */ svtime += ( (numdays * 24 + numhours) * 60 + numminutes ) * 60; ptime = &svtime; (void) cftime(prtim,fmt,ptime); printf("%s",prtim); return SYSOK; }