diff --git a/src/common/parse_time.c b/src/common/parse_time.c index af98266b5fdfd4efef82f8d71843710f11b2cff7..abc7cb21eb42936511bf776147324d7000420692 100644 --- a/src/common/parse_time.c +++ b/src/common/parse_time.c @@ -30,6 +30,9 @@ #define _RUN_STAND_ALONE 0 +time_t time_now; +struct tm *time_now_tm; + /* convert time differential string into a number of seconds * time_str (in): string to parse * pos (in/out): position of parse start/end @@ -79,15 +82,16 @@ static int _get_delta(char *time_str, int *pos, long *delta) return -1; } -/* convert "HH:MM [AM|PM]" string to numeric values +/* convert "HH:MM[:SS] [AM|PM]" string to numeric values * time_str (in): string to parse * pos (in/out): position of parse start/end - * hour, minute (out): numberic values + * hour, minute, second (out): numberic values * RET: -1 on error, 0 otherwise */ -static int _get_time(char *time_str, int *pos, int *hour, int *minute) +static int +_get_time(char *time_str, int *pos, int *hour, int *minute, int * second) { - int hr, min; + int hr, min, sec; int offset = *pos; /* get hour */ @@ -109,6 +113,18 @@ static int _get_time(char *time_str, int *pos, int *hour, int *minute) goto prob; min = (min * 10) + time_str[offset++] - '0'; + /* get optional second */ + if (time_str[offset] == ':') { + offset++; + if ((time_str[offset] < '0') || (time_str[offset] > '9')) + goto prob; + sec = time_str[offset++] - '0'; + if ((time_str[offset] < '0') || (time_str[offset] > '9')) + goto prob; + sec = (sec * 10) + time_str[offset++] - '0'; + } else + sec = 0; + while (isspace(time_str[offset])) { offset++; } @@ -120,11 +136,12 @@ static int _get_time(char *time_str, int *pos, int *hour, int *minute) } *pos = offset - 1; - *hour = hr; + *hour = hr; *minute = min; + *second = sec; return 0; - prob: *pos = offset - 1; + prob: *pos = offset; return -1; } @@ -143,6 +160,10 @@ static int _get_date(char *time_str, int *pos, int *month, int *mday, int *year) mon = time_str[offset++] - '0'; if ((time_str[offset] >= '0') && (time_str[offset] <= '9')) mon = (mon * 10) + time_str[offset++] - '0'; + if ((mon < 1) || (mon > 12)) { + offset -= 2; + goto prob; + } if ((time_str[offset] == '.') || (time_str[offset] == '/')) offset++; @@ -152,21 +173,27 @@ static int _get_date(char *time_str, int *pos, int *month, int *mday, int *year) day = time_str[offset++] - '0'; if ((time_str[offset] >= '0') && (time_str[offset] <= '9')) day = (day * 10) + time_str[offset++] - '0'; + if ((day < 1) || (day > 31)) { + offset -= 2; + goto prob; + } if ((time_str[offset] == '.') || (time_str[offset] == '/')) offset++; - /* get year */ - if ((time_str[offset] < '0') || (time_str[offset] > '9')) - goto prob; - yr = time_str[offset++] - '0'; - if ((time_str[offset] < '0') || (time_str[offset] > '9')) - goto prob; - yr = (yr * 10) + time_str[offset++] - '0'; + /* get optional year */ + if ((time_str[offset] >= '0') && (time_str[offset] <= '9')) { + yr = time_str[offset++] - '0'; + if ((time_str[offset] < '0') || (time_str[offset] > '9')) + goto prob; + yr = (yr * 10) + time_str[offset++] - '0'; + } else + yr = 0; *pos = offset - 1; *month = mon - 1; /* zero origin */ *mday = day; - *year = yr + 100; /* 1900 == "00" */ + if (yr) + *year = yr + 100; /* 1900 == "00" */ return 0; prob: *pos = offset; @@ -178,8 +205,8 @@ static int _get_date(char *time_str, int *pos, int *month, int *mday, int *year) * input formats: * today or tomorrow * midnight, noon, teatime (4PM) - * HH:MM [AM|PM] - * MMDDYY or MM/DD/YY or MM.DD.YY + * HH:MM[:SS] [AM|PM] + * MMDD[YY] or MM/DD[/YY] or MM.DD[.YY] * now + count [minutes | hours | days | weeks] * * Invalid input results in message to stderr and return value of zero @@ -187,36 +214,37 @@ static int _get_date(char *time_str, int *pos, int *month, int *mday, int *year) extern time_t parse_time(char *time_str) { time_t delta = (time_t) 0; - time_t now = time(NULL); - struct tm now_tm; int hour = -1, minute = -1, second = 0; int month = -1, mday = -1, year = -1; int num = 0, pos = 0; + struct tm res_tm; + + time_now = time(NULL); + time_now_tm = localtime(&time_now); for (pos=0; ((time_str[pos] != '\0')&&(time_str[pos] != '\n')); pos++) { - if (isblank(time_str[pos])) + if (isblank(time_str[pos]) || (time_str[pos] == '-')) continue; if (strncasecmp(time_str+pos, "today", 5) == 0) { - struct tm *now_tm = localtime(&now); - month = now_tm->tm_mon; - mday = now_tm->tm_mday; - year = now_tm->tm_year; + month = time_now_tm->tm_mon; + mday = time_now_tm->tm_mday; + year = time_now_tm->tm_year; pos += 4; continue; } if (strncasecmp(time_str+pos, "tomorrow", 8) == 0) { - time_t later = now + (24 * 60 * 60); - struct tm *now_tm = localtime(&later); - month = now_tm->tm_mon; - mday = now_tm->tm_mday; - year = now_tm->tm_year; + time_t later = time_now + (24 * 60 * 60); + struct tm *later_tm = localtime(&later); + month = later_tm->tm_mon; + mday = later_tm->tm_mday; + year = later_tm->tm_year; pos += 7; continue; } if (strncasecmp(time_str+pos, "midnight", 8) == 0) { - hour = 23; - minute = 59; - second = 60; + hour = 0; + minute = 0; + second = 0; pos += 7; continue; } @@ -236,8 +264,8 @@ extern time_t parse_time(char *time_str) int i; long delta = 0; time_t later; - struct tm *now_tm; - for (i=(pos+3);((time_str[i]!='\0')&&(time_str[i]!='\n')); i++) { + struct tm *later_tm; + for (i=(pos+3); ; i++) { if (time_str[i] == '+') { pos += i; if (_get_delta(time_str, &pos, &delta)) @@ -253,21 +281,21 @@ extern time_t parse_time(char *time_str) pos += i; goto prob; } - later = now + delta; - now_tm = localtime(&later); - month = now_tm->tm_mon; - mday = now_tm->tm_mday; - year = now_tm->tm_year; - hour = now_tm->tm_hour; - minute = now_tm->tm_min; - second = now_tm->tm_sec; + later = time_now + delta; + later_tm = localtime(&later); + month = later_tm->tm_mon; + mday = later_tm->tm_mday; + year = later_tm->tm_year; + hour = later_tm->tm_hour; + minute = later_tm->tm_min; + second = later_tm->tm_sec; continue; } if ((time_str[pos] < '0') || (time_str[pos] > '9')) /* invalid */ goto prob; /* We have some numeric value to process */ if (time_str[pos+2] == ':') { /* time */ - if (_get_time(time_str, &pos, &hour, &minute)) + if (_get_time(time_str, &pos, &hour, &minute, &second)) goto prob; continue; } @@ -277,28 +305,52 @@ extern time_t parse_time(char *time_str) /* printf("%d/%d/%d %d:%d\n",month+1,mday,year+1900,hour+1,minute); */ - /* now convert the time into time_t format */ - if ((hour == -1) && (year == -1)) /* nothing specified */ + if ((hour == -1) && (month == -1)) /* nothing specified, time=0 */ return (time_t) 0; - if (hour == -1) { /* no time implies 00:00 */ + else if ((hour == -1) && (month != -1)) { /* date, no time implies 00:00 */ hour = 0; minute = 0; } - if (year == -1) { /* no date implies today */ - struct tm *now_tm = localtime(&now); - month = now_tm->tm_mon; - mday = now_tm->tm_mday; - year = now_tm->tm_year; + else if ((hour != -1) && (month == -1)) { /* time, no date implies soonest day */ + if ((hour > time_now_tm->tm_hour) + || ((hour == time_now_tm->tm_hour) && (minute > time_now_tm->tm_min))) { + /* today */ + month = time_now_tm->tm_mon; + mday = time_now_tm->tm_mday; + year = time_now_tm->tm_year; + } else {/* tomorrow */ + time_t later = time_now + (24 * 60 * 60); + struct tm *later_tm = localtime(&later); + month = later_tm->tm_mon; + mday = later_tm->tm_mday; + year = later_tm->tm_year; + + } } - bzero(&now_tm, sizeof(now_tm)); - now_tm.tm_sec = second; - now_tm.tm_min = minute; - now_tm.tm_hour = hour; - now_tm.tm_mday = mday; - now_tm.tm_mon = month; - now_tm.tm_year = year; - now_tm.tm_isdst = 1; - return mktime(&now_tm);; + if (year == -1) { + if ((month > time_now_tm->tm_mon) + || ((month == time_now_tm->tm_mon) && (mday > time_now_tm->tm_mday)) + || ((month == time_now_tm->tm_mon) && (mday == time_now_tm->tm_mday) + && (hour > time_now_tm->tm_hour)) + || ((month == time_now_tm->tm_mon) && (mday == time_now_tm->tm_mday) + && (hour == time_now_tm->tm_hour) && (minute > time_now_tm->tm_min))) { + /* this year */ + year = time_now_tm->tm_year; + } else { + year = time_now_tm->tm_year + 1; + } + } + + /* convert the time into time_t format */ + bzero(&res_tm, sizeof(res_tm)); + res_tm.tm_sec = second; + res_tm.tm_min = minute; + res_tm.tm_hour = hour; + res_tm.tm_mday = mday; + res_tm.tm_mon = month; + res_tm.tm_year = year; + res_tm.tm_isdst = 1; + return mktime(&res_tm); prob: fprintf(stderr, "Invalid time specification (pos=%d): %s", pos, time_str); return (time_t) 0;