X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=tests%2Ftest-parse-datetime.c;h=22fe9bc1194ac55edcab23eb4cdd8ec2df2d7efd;hb=5bf73fbe89c75118e5e9a53e4b88a57729d26964;hp=45dbae6760b7bedf4bda8b16b6c00268a3c3b359;hpb=4b6dad7e35019625bd5eb30796beebac099a7422;p=gnulib.git diff --git a/tests/test-parse-datetime.c b/tests/test-parse-datetime.c index 45dbae676..22fe9bc11 100644 --- a/tests/test-parse-datetime.c +++ b/tests/test-parse-datetime.c @@ -36,7 +36,7 @@ #define LOG(str, now, res) (void) 0 #endif -static const char* const day_table[] = +static const char *const day_table[] = { "SUNDAY", "MONDAY", @@ -48,17 +48,169 @@ static const char* const day_table[] = NULL }; + +#if ! HAVE_TM_GMTOFF +/* Shift A right by B bits portably, by dividing A by 2**B and + truncating towards minus infinity. A and B should be free of side + effects, and B should be in the range 0 <= B <= INT_BITS - 2, where + INT_BITS is the number of useful bits in an int. GNU code can + assume that INT_BITS is at least 32. + + ISO C99 says that A >> B is implementation-defined if A < 0. Some + implementations (e.g., UNICOS 9.0 on a Cray Y-MP EL) don't shift + right in the usual way when A < 0, so SHR falls back on division if + ordinary A >> B doesn't seem to be the usual signed shift. */ +#define SHR(a, b) \ + (-1 >> 1 == -1 \ + ? (a) >> (b) \ + : (a) / (1 << (b)) - ((a) % (1 << (b)) < 0)) + +#define TM_YEAR_BASE 1900 + +/* Yield the difference between *A and *B, + measured in seconds, ignoring leap seconds. + The body of this function is taken directly from the GNU C Library; + see src/strftime.c. */ +static long int +tm_diff (struct tm const *a, struct tm const *b) +{ + /* Compute intervening leap days correctly even if year is negative. + Take care to avoid int overflow in leap day calculations. */ + int a4 = SHR (a->tm_year, 2) + SHR (TM_YEAR_BASE, 2) - ! (a->tm_year & 3); + int b4 = SHR (b->tm_year, 2) + SHR (TM_YEAR_BASE, 2) - ! (b->tm_year & 3); + int a100 = a4 / 25 - (a4 % 25 < 0); + int b100 = b4 / 25 - (b4 % 25 < 0); + int a400 = SHR (a100, 2); + int b400 = SHR (b100, 2); + int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400); + long int ayear = a->tm_year; + long int years = ayear - b->tm_year; + long int days = (365 * years + intervening_leap_days + + (a->tm_yday - b->tm_yday)); + return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour)) + + (a->tm_min - b->tm_min)) + + (a->tm_sec - b->tm_sec)); +} +#endif /* ! HAVE_TM_GMTOFF */ + +static long +gmt_offset (time_t s) +{ + long gmtoff; + +#if !HAVE_TM_GMTOFF + struct tm tm_local = *localtime (&s); + struct tm tm_gmt = *gmtime (&s); + + gmtoff = tm_diff (&tm_local, &tm_gmt); +#else + gmtoff = localtime (&s)->tm_gmtoff; +#endif + + return gmtoff; +} + int main (int argc _GL_UNUSED, char **argv) { struct timespec result; struct timespec result2; + struct timespec expected; struct timespec now; const char *p; int i; + long gmtoff; + time_t ref_time = 1304250918; set_program_name (argv[0]); + gmtoff = gmt_offset (ref_time); + + + /* ISO 8601 extended date and time of day representation, + 'T' separator, local time zone */ + p = "2011-05-01T11:55:18"; + expected.tv_sec = ref_time - gmtoff; + expected.tv_nsec = 0; + ASSERT (parse_datetime (&result, p, 0)); + LOG (p, expected, result); + ASSERT (expected.tv_sec == result.tv_sec + && expected.tv_nsec == result.tv_nsec); + + /* ISO 8601 extended date and time of day representation, + ' ' separator, local time zone */ + p = "2011-05-01 11:55:18"; + expected.tv_sec = ref_time - gmtoff; + expected.tv_nsec = 0; + ASSERT (parse_datetime (&result, p, 0)); + LOG (p, expected, result); + ASSERT (expected.tv_sec == result.tv_sec + && expected.tv_nsec == result.tv_nsec); + + + /* ISO 8601, extended date and time of day representation, + 'T' separator, UTC */ + p = "2011-05-01T11:55:18Z"; + expected.tv_sec = ref_time; + expected.tv_nsec = 0; + ASSERT (parse_datetime (&result, p, 0)); + LOG (p, expected, result); + ASSERT (expected.tv_sec == result.tv_sec + && expected.tv_nsec == result.tv_nsec); + + /* ISO 8601, extended date and time of day representation, + ' ' separator, UTC */ + p = "2011-05-01 11:55:18Z"; + expected.tv_sec = ref_time; + expected.tv_nsec = 0; + ASSERT (parse_datetime (&result, p, 0)); + LOG (p, expected, result); + ASSERT (expected.tv_sec == result.tv_sec + && expected.tv_nsec == result.tv_nsec); + + + /* ISO 8601 extended date and time of day representation, + 'T' separator, w/UTC offset */ + p = "2011-05-01T11:55:18-07:00"; + expected.tv_sec = 1304276118; + expected.tv_nsec = 0; + ASSERT (parse_datetime (&result, p, 0)); + LOG (p, expected, result); + ASSERT (expected.tv_sec == result.tv_sec + && expected.tv_nsec == result.tv_nsec); + + /* ISO 8601 extended date and time of day representation, + ' ' separator, w/UTC offset */ + p = "2011-05-01 11:55:18-07:00"; + expected.tv_sec = 1304276118; + expected.tv_nsec = 0; + ASSERT (parse_datetime (&result, p, 0)); + LOG (p, expected, result); + ASSERT (expected.tv_sec == result.tv_sec + && expected.tv_nsec == result.tv_nsec); + + + /* ISO 8601 extended date and time of day representation, + 'T' separator, w/hour only UTC offset */ + p = "2011-05-01T11:55:18-07"; + expected.tv_sec = 1304276118; + expected.tv_nsec = 0; + ASSERT (parse_datetime (&result, p, 0)); + LOG (p, expected, result); + ASSERT (expected.tv_sec == result.tv_sec + && expected.tv_nsec == result.tv_nsec); + + /* ISO 8601 extended date and time of day representation, + ' ' separator, w/hour only UTC offset */ + p = "2011-05-01 11:55:18-07"; + expected.tv_sec = 1304276118; + expected.tv_nsec = 0; + ASSERT (parse_datetime (&result, p, 0)); + LOG (p, expected, result); + ASSERT (expected.tv_sec == result.tv_sec + && expected.tv_nsec == result.tv_nsec); + + now.tv_sec = 4711; now.tv_nsec = 1267; p = "now"; @@ -173,6 +325,8 @@ main (int argc _GL_UNUSED, char **argv) ASSERT (!parse_datetime (&result, p, &now)); p = "UTC+4:00 tomorrow ago"; ASSERT (!parse_datetime (&result, p, &now)); + p = "UTC+4:00 tomorrow hence"; + ASSERT (!parse_datetime (&result, p, &now)); p = "UTC+4:00 40 now ago"; ASSERT (!parse_datetime (&result, p, &now)); p = "UTC+4:00 last tomorrow"; @@ -191,6 +345,11 @@ main (int argc _GL_UNUSED, char **argv) LOG (p, now, result2); ASSERT (result.tv_sec == result2.tv_sec && result.tv_nsec == result2.tv_nsec); + p = "UTC+400 1 day hence"; + ASSERT (parse_datetime (&result2, p, &now)); + LOG (p, now, result2); + ASSERT (result.tv_sec == result2.tv_sec + && result.tv_nsec == result2.tv_nsec); now.tv_sec = 4711; now.tv_nsec = 1267; p = "UTC+400 yesterday";