#include static int leapyear(int year) { return ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0)); } /* * This is a simple implementation of timegm() which does what is needed * by parse-time-string.c -- just turns the "struct tm" into a GMT time_t. * It does not normalize any of the fields of the "struct tm", nor does * it set tm_wday or tm_yday. */ static time_t timegm(struct tm *tm) { int monthlen[2][12] = { { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, }; int year, month, days; days = 365 * (tm->tm_year - 70); for (year = 70; year < tm->tm_year; year++) { if (leapyear(1900 + year)) { days++; } } for (month = 0; month < tm->tm_mon; month++) { days += monthlen[leapyear(1900 + year)][month]; } days += tm->tm_mday - 1; return ((((days * 24) + tm->tm_hour) * 60 + tm->tm_min) * 60 + tm->tm_sec); } #include #include #include void tm_test(int niter) { const int monthlen[2][12] = { { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, }; int i; struct tm tm, *tmp; time_t t; for (i = 0; i < niter; i++) { tm.tm_year = (lrand48() % 67) + 70; tm.tm_mon = lrand48() % 12; do { t = (lrand48() % 31) + 1; } while (t > monthlen[leapyear(1900 + tm.tm_year)][tm.tm_mon]); tm.tm_mday = t; tm.tm_hour = lrand48() % 24; tm.tm_min = lrand48() % 60; tm.tm_sec = lrand48() % 60; t = timegm(&tm); tmp = gmtime(&t); if (tmp->tm_sec != tm.tm_sec || tmp->tm_min != tm.tm_min || tmp->tm_hour != tm.tm_hour || tmp->tm_mday != tm.tm_mday || tmp->tm_mon != tm.tm_mon || tmp->tm_year != tm.tm_year) { printf("%4d-%02d-%02d %02d:%02d:%02d -> " "%4d-%02d-%02d %02d:%02d:%02d\n", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour, tmp->tm_min, tmp->tm_sec); } } } void time_test(int niter) { int i; time_t st, et; struct tm *tmp; for (i = 0; i < niter; i++) { st = (time_t)lrand48(); tmp = gmtime(&st); et = timegm(tmp); if (st != et) { printf("%d -> %d (%4d-%02d-%02d %02d:%02d:%02d)\n", st, et, tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour, tmp->tm_min, tmp->tm_sec); } } } int main(void) { const int niter = 10000000; srand48(getpid()); tm_test(niter); time_test(niter); return (0); }