struct tm * posixtm (const char *s, unsigned int syntax_bits) { if (posixtime (s, syntax_bits) == -1) return NULL; return &t; }
int main (void) { char buff[MAX_BUFF_LEN + 1]; buff[MAX_BUFF_LEN] = 0; while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0]) { char time_str[MAX_BUFF_LEN]; unsigned int syntax_bits; time_t t; if (sscanf (buff, "%s %u", time_str, &syntax_bits) != 2) printf ("*\n"); else { printf ("%-15s %2u ", time_str, syntax_bits); if (posixtime (&t, time_str, syntax_bits)) printf ("%12ld %s", (long int) t, ctime (&t)); else printf ("%12s %s", "*", "*\n"); } } exit (0); }
bool posixtime (time_t *p, const char *s, unsigned int syntax_bits) { struct tm tm0; struct tm tm1; struct tm const *tm; time_t t; if (posix_time_parse (&tm0, s, syntax_bits)) return false; tm1 = tm0; tm1.tm_isdst = -1; t = mktime (&tm1); if (t != (time_t) -1) tm = &tm1; else { /* mktime returns -1 for errors, but -1 is also a valid time_t value. Check whether an error really occurred. */ tm = localtime (&t); if (! tm) return false; } /* Reject dates like "September 31" and times like "25:61". Do not reject times that specify "60" as the number of seconds. */ if ((tm0.tm_year ^ tm->tm_year) | (tm0.tm_mon ^ tm->tm_mon) | (tm0.tm_mday ^ tm->tm_mday) | (tm0.tm_hour ^ tm->tm_hour) | (tm0.tm_min ^ tm->tm_min) | (tm0.tm_sec ^ tm->tm_sec)) { /* Any mismatch without 60 in the tm_sec field is invalid. */ if (tm0.tm_sec != 60) return false; { /* Allow times like 01:35:60 or 23:59:60. */ time_t dummy; char buf[16]; char *b = stpcpy (buf, s); strcpy (b - 2, "59"); if (!posixtime (&dummy, buf, syntax_bits)) return false; } } *p = t; return true; }
int main () { char buff[MAX_BUFF_LEN + 1]; buff[MAX_BUFF_LEN] = 0; while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0]) { char time_str[MAX_BUFF_LEN]; unsigned int syntax_bits; time_t t; char *result; sscanf (buff, "%s %u", time_str, &syntax_bits); t = posixtime (time_str, syntax_bits); result = (t == (time_t) -1 ? "***" : ctime (&t)); printf ("%d %s\n", (int) t, result); } exit (0); }
int main (void) { unsigned int i; int fail = 0; char curr_year_str[30]; struct tm *tm; time_t t_now; int err; size_t n_bytes; /* The above test data requires Universal Time, e.g., TZ="UTC0". */ err = setenv ("TZ", "UTC0", 1); ASSERT (err == 0); t_now = time (NULL); ASSERT (t_now != (time_t) -1); tm = localtime (&t_now); ASSERT (tm); n_bytes = strftime (curr_year_str, sizeof curr_year_str, "%Y", tm); ASSERT (0 < n_bytes); for (i = 0; T[i].in; i++) { time_t t_out; time_t t_exp = T[i].t_expected; bool ok; /* Some tests assume that time_t is signed. If it is unsigned and the result is negative, skip the test. */ if (T[i].t_expected < 0 && ! TYPE_SIGNED (time_t)) { printf ("skipping %s: result is negative, " "but your time_t is unsigned\n", T[i].in); continue; } if (T[i].valid && t_exp != T[i].t_expected) { printf ("skipping %s: result is out of range of your time_t\n", T[i].in); continue; } /* If an input string does not specify the year number, determine the expected output by calling posixtime with an otherwise equivalent string that starts with the current year. */ if (8 <= strlen (T[i].in) && (T[i].in[8] == '.' || T[i].in[8] == '\0')) { char tmp_buf[20]; stpcpy (stpcpy (tmp_buf, curr_year_str), T[i].in); ASSERT (posixtime (&t_exp, tmp_buf, T[i].syntax_bits)); } ok = posixtime (&t_out, T[i].in, T[i].syntax_bits); if (ok != !!T[i].valid) { printf ("%s return value mismatch: got %d, expected %d\n", T[i].in, !!ok, T[i].valid); fail = 1; continue; } if (!ok) continue; if (t_out != t_exp) { printf ("%s mismatch (-: actual; +:expected)\n-%12ld\n+%12ld\n", T[i].in, t_out, t_exp); fail = 1; } } return fail; }