Skip to content
Snippets Groups Projects
Commit f64271a8 authored by Moe Jette's avatar Moe Jette
Browse files

Optionally accept seconds field.

Range check month/date values (e.g. "13/45/06" is invalid)
Make year specification optional
Accept "-" separator between date and time.
Automatically set date to tommorow if time specified 
  that is earlier than now.
parent 822ca52e
No related branches found
No related tags found
No related merge requests found
...@@ -30,6 +30,9 @@ ...@@ -30,6 +30,9 @@
#define _RUN_STAND_ALONE 0 #define _RUN_STAND_ALONE 0
time_t time_now;
struct tm *time_now_tm;
/* convert time differential string into a number of seconds /* convert time differential string into a number of seconds
* time_str (in): string to parse * time_str (in): string to parse
* pos (in/out): position of parse start/end * pos (in/out): position of parse start/end
...@@ -79,15 +82,16 @@ static int _get_delta(char *time_str, int *pos, long *delta) ...@@ -79,15 +82,16 @@ static int _get_delta(char *time_str, int *pos, long *delta)
return -1; 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 * time_str (in): string to parse
* pos (in/out): position of parse start/end * 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 * 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; int offset = *pos;
/* get hour */ /* get hour */
...@@ -109,6 +113,18 @@ static int _get_time(char *time_str, int *pos, int *hour, int *minute) ...@@ -109,6 +113,18 @@ static int _get_time(char *time_str, int *pos, int *hour, int *minute)
goto prob; goto prob;
min = (min * 10) + time_str[offset++] - '0'; 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])) { while (isspace(time_str[offset])) {
offset++; offset++;
} }
...@@ -120,11 +136,12 @@ static int _get_time(char *time_str, int *pos, int *hour, int *minute) ...@@ -120,11 +136,12 @@ static int _get_time(char *time_str, int *pos, int *hour, int *minute)
} }
*pos = offset - 1; *pos = offset - 1;
*hour = hr; *hour = hr;
*minute = min; *minute = min;
*second = sec;
return 0; return 0;
prob: *pos = offset - 1; prob: *pos = offset;
return -1; return -1;
} }
...@@ -143,6 +160,10 @@ static int _get_date(char *time_str, int *pos, int *month, int *mday, int *year) ...@@ -143,6 +160,10 @@ static int _get_date(char *time_str, int *pos, int *month, int *mday, int *year)
mon = time_str[offset++] - '0'; mon = time_str[offset++] - '0';
if ((time_str[offset] >= '0') && (time_str[offset] <= '9')) if ((time_str[offset] >= '0') && (time_str[offset] <= '9'))
mon = (mon * 10) + time_str[offset++] - '0'; mon = (mon * 10) + time_str[offset++] - '0';
if ((mon < 1) || (mon > 12)) {
offset -= 2;
goto prob;
}
if ((time_str[offset] == '.') || (time_str[offset] == '/')) if ((time_str[offset] == '.') || (time_str[offset] == '/'))
offset++; offset++;
...@@ -152,21 +173,27 @@ static int _get_date(char *time_str, int *pos, int *month, int *mday, int *year) ...@@ -152,21 +173,27 @@ static int _get_date(char *time_str, int *pos, int *month, int *mday, int *year)
day = time_str[offset++] - '0'; day = time_str[offset++] - '0';
if ((time_str[offset] >= '0') && (time_str[offset] <= '9')) if ((time_str[offset] >= '0') && (time_str[offset] <= '9'))
day = (day * 10) + time_str[offset++] - '0'; day = (day * 10) + time_str[offset++] - '0';
if ((day < 1) || (day > 31)) {
offset -= 2;
goto prob;
}
if ((time_str[offset] == '.') || (time_str[offset] == '/')) if ((time_str[offset] == '.') || (time_str[offset] == '/'))
offset++; offset++;
/* get year */ /* get optional year */
if ((time_str[offset] < '0') || (time_str[offset] > '9')) if ((time_str[offset] >= '0') && (time_str[offset] <= '9')) {
goto prob; yr = time_str[offset++] - '0';
yr = time_str[offset++] - '0'; if ((time_str[offset] < '0') || (time_str[offset] > '9'))
if ((time_str[offset] < '0') || (time_str[offset] > '9')) goto prob;
goto prob; yr = (yr * 10) + time_str[offset++] - '0';
yr = (yr * 10) + time_str[offset++] - '0'; } else
yr = 0;
*pos = offset - 1; *pos = offset - 1;
*month = mon - 1; /* zero origin */ *month = mon - 1; /* zero origin */
*mday = day; *mday = day;
*year = yr + 100; /* 1900 == "00" */ if (yr)
*year = yr + 100; /* 1900 == "00" */
return 0; return 0;
prob: *pos = offset; prob: *pos = offset;
...@@ -178,8 +205,8 @@ static int _get_date(char *time_str, int *pos, int *month, int *mday, int *year) ...@@ -178,8 +205,8 @@ static int _get_date(char *time_str, int *pos, int *month, int *mday, int *year)
* input formats: * input formats:
* today or tomorrow * today or tomorrow
* midnight, noon, teatime (4PM) * midnight, noon, teatime (4PM)
* HH:MM [AM|PM] * HH:MM[:SS] [AM|PM]
* MMDDYY or MM/DD/YY or MM.DD.YY * MMDD[YY] or MM/DD[/YY] or MM.DD[.YY]
* now + count [minutes | hours | days | weeks] * now + count [minutes | hours | days | weeks]
* *
* Invalid input results in message to stderr and return value of zero * 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) ...@@ -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) extern time_t parse_time(char *time_str)
{ {
time_t delta = (time_t) 0; time_t delta = (time_t) 0;
time_t now = time(NULL);
struct tm now_tm;
int hour = -1, minute = -1, second = 0; int hour = -1, minute = -1, second = 0;
int month = -1, mday = -1, year = -1; int month = -1, mday = -1, year = -1;
int num = 0, pos = 0; 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++) { 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; continue;
if (strncasecmp(time_str+pos, "today", 5) == 0) { if (strncasecmp(time_str+pos, "today", 5) == 0) {
struct tm *now_tm = localtime(&now); month = time_now_tm->tm_mon;
month = now_tm->tm_mon; mday = time_now_tm->tm_mday;
mday = now_tm->tm_mday; year = time_now_tm->tm_year;
year = now_tm->tm_year;
pos += 4; pos += 4;
continue; continue;
} }
if (strncasecmp(time_str+pos, "tomorrow", 8) == 0) { if (strncasecmp(time_str+pos, "tomorrow", 8) == 0) {
time_t later = now + (24 * 60 * 60); time_t later = time_now + (24 * 60 * 60);
struct tm *now_tm = localtime(&later); struct tm *later_tm = localtime(&later);
month = now_tm->tm_mon; month = later_tm->tm_mon;
mday = now_tm->tm_mday; mday = later_tm->tm_mday;
year = now_tm->tm_year; year = later_tm->tm_year;
pos += 7; pos += 7;
continue; continue;
} }
if (strncasecmp(time_str+pos, "midnight", 8) == 0) { if (strncasecmp(time_str+pos, "midnight", 8) == 0) {
hour = 23; hour = 0;
minute = 59; minute = 0;
second = 60; second = 0;
pos += 7; pos += 7;
continue; continue;
} }
...@@ -236,8 +264,8 @@ extern time_t parse_time(char *time_str) ...@@ -236,8 +264,8 @@ extern time_t parse_time(char *time_str)
int i; int i;
long delta = 0; long delta = 0;
time_t later; time_t later;
struct tm *now_tm; struct tm *later_tm;
for (i=(pos+3);((time_str[i]!='\0')&&(time_str[i]!='\n')); i++) { for (i=(pos+3); ; i++) {
if (time_str[i] == '+') { if (time_str[i] == '+') {
pos += i; pos += i;
if (_get_delta(time_str, &pos, &delta)) if (_get_delta(time_str, &pos, &delta))
...@@ -253,21 +281,21 @@ extern time_t parse_time(char *time_str) ...@@ -253,21 +281,21 @@ extern time_t parse_time(char *time_str)
pos += i; pos += i;
goto prob; goto prob;
} }
later = now + delta; later = time_now + delta;
now_tm = localtime(&later); later_tm = localtime(&later);
month = now_tm->tm_mon; month = later_tm->tm_mon;
mday = now_tm->tm_mday; mday = later_tm->tm_mday;
year = now_tm->tm_year; year = later_tm->tm_year;
hour = now_tm->tm_hour; hour = later_tm->tm_hour;
minute = now_tm->tm_min; minute = later_tm->tm_min;
second = now_tm->tm_sec; second = later_tm->tm_sec;
continue; continue;
} }
if ((time_str[pos] < '0') || (time_str[pos] > '9')) /* invalid */ if ((time_str[pos] < '0') || (time_str[pos] > '9')) /* invalid */
goto prob; goto prob;
/* We have some numeric value to process */ /* We have some numeric value to process */
if (time_str[pos+2] == ':') { /* time */ 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; goto prob;
continue; continue;
} }
...@@ -277,28 +305,52 @@ extern time_t parse_time(char *time_str) ...@@ -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); */ /* 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) && (month == -1)) /* nothing specified, time=0 */
if ((hour == -1) && (year == -1)) /* nothing specified */
return (time_t) 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; hour = 0;
minute = 0; minute = 0;
} }
if (year == -1) { /* no date implies today */ else if ((hour != -1) && (month == -1)) { /* time, no date implies soonest day */
struct tm *now_tm = localtime(&now); if ((hour > time_now_tm->tm_hour)
month = now_tm->tm_mon; || ((hour == time_now_tm->tm_hour) && (minute > time_now_tm->tm_min))) {
mday = now_tm->tm_mday; /* today */
year = now_tm->tm_year; 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)); if (year == -1) {
now_tm.tm_sec = second; if ((month > time_now_tm->tm_mon)
now_tm.tm_min = minute; || ((month == time_now_tm->tm_mon) && (mday > time_now_tm->tm_mday))
now_tm.tm_hour = hour; || ((month == time_now_tm->tm_mon) && (mday == time_now_tm->tm_mday)
now_tm.tm_mday = mday; && (hour > time_now_tm->tm_hour))
now_tm.tm_mon = month; || ((month == time_now_tm->tm_mon) && (mday == time_now_tm->tm_mday)
now_tm.tm_year = year; && (hour == time_now_tm->tm_hour) && (minute > time_now_tm->tm_min))) {
now_tm.tm_isdst = 1; /* this year */
return mktime(&now_tm);; 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); prob: fprintf(stderr, "Invalid time specification (pos=%d): %s", pos, time_str);
return (time_t) 0; return (time_t) 0;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment