158 строки
6.0 KiB
C
158 строки
6.0 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
#include <math.h>
|
|
|
|
int main() {
|
|
time_t xmas2002 = 1040786563ll;
|
|
time_t summer2002 = 1025528525ll;
|
|
struct tm* tm_ptr;
|
|
|
|
// Make sure stime() always fails.
|
|
printf("stime: %d\n", stime(&xmas2002));
|
|
|
|
// Verify that tzname sets *something*.
|
|
tzset();
|
|
printf("tzname[0] set: %d\n", strlen(tzname[0]) >= 3);
|
|
printf("tzname[1] set: %d\n", strlen(tzname[1]) >= 3);
|
|
|
|
// Verify gmtime() creates correct struct.
|
|
tm_ptr = gmtime(&xmas2002);
|
|
printf("sec: %d\n", tm_ptr->tm_sec);
|
|
printf("min: %d\n", tm_ptr->tm_min);
|
|
printf("hour: %d\n", tm_ptr->tm_hour);
|
|
printf("day: %d\n", tm_ptr->tm_mday);
|
|
printf("mon: %d\n", tm_ptr->tm_mon);
|
|
printf("year: %d\n", tm_ptr->tm_year);
|
|
printf("wday: %d\n", tm_ptr->tm_wday);
|
|
printf("yday: %d\n", tm_ptr->tm_yday);
|
|
printf("dst: %d\n", tm_ptr->tm_isdst);
|
|
printf("off: %ld\n", (long)tm_ptr->tm_gmtoff);
|
|
printf("zone: %s\n", tm_ptr->tm_zone);
|
|
|
|
// Verify timegm() reverses gmtime; run through an entire year in half hours.
|
|
int timegmOk = 1;
|
|
for (int i = 0; i < 2*24*266; ++i) {
|
|
struct tm tmp;
|
|
time_t test = xmas2002 + 30*60*i;
|
|
if (gmtime_r(&test, &tmp) != &tmp) printf("gmtime_r failed\n");
|
|
struct tm copy = tmp;
|
|
copy.tm_wday = -1;
|
|
copy.tm_yday = -1;
|
|
if (timegm(©) != test || copy.tm_wday != tmp.tm_wday ||
|
|
copy.tm_yday != tmp.tm_yday)
|
|
timegmOk = 0;
|
|
}
|
|
printf("timegm <-> gmtime: %d\n", timegmOk);
|
|
|
|
// Verify gmtime_r() doesn't clobber static data.
|
|
time_t t1 = 0;
|
|
struct tm tm1;
|
|
gmtime_r(&t1, &tm1);
|
|
printf("old year still: %d\n", tm_ptr->tm_year);
|
|
printf("new year: %d\n", tm1.tm_year);
|
|
|
|
// Verify localtime() picks up timezone data.
|
|
struct tm tm_winter, tm_summer;
|
|
if (localtime_r(&xmas2002, &tm_winter) != &tm_winter) printf("localtime_r failed\n");
|
|
if (localtime_r(&summer2002, &tm_summer) != &tm_summer) printf("localtime_r failed\n");
|
|
printf("localtime found DST data (summer): %s\n", tm_summer.tm_isdst < 0 ? "no" : "yes");
|
|
printf("localtime found DST data (winter): %s\n", tm_winter.tm_isdst < 0 ? "no" : "yes");
|
|
int localeHasDst = tm_winter.tm_isdst == 1 || tm_summer.tm_isdst == 1; // DST is in December in south
|
|
printf("localtime matches daylight: %s\n", localeHasDst == _daylight ? "yes" : "no");
|
|
int goodGmtOff = (tm_winter.tm_gmtoff != tm_summer.tm_gmtoff) == localeHasDst;
|
|
printf("localtime gmtoff matches DST: %s\n", goodGmtOff ? "yes" : "no");
|
|
printf("localtime tm_zone matches tzname (winter): %s\n",
|
|
strcmp(tzname[tm_winter.tm_isdst], tm_winter.tm_zone) ? "no" : "yes");
|
|
printf("localtime tm_zone matches tzname (summer): %s\n",
|
|
strcmp(tzname[tm_summer.tm_isdst], tm_summer.tm_zone) ? "no" : "yes");
|
|
|
|
// Verify localtime() and mktime() reverse each other; run through an entire year
|
|
// in half hours (the two hours where the time jumps forward and back are the
|
|
// ones to watch, but we don't where they are since the zoneinfo could be US or
|
|
// European)
|
|
int mktimeOk = 1;
|
|
for (int i = 0; i < 2*24*266; ++i) {
|
|
struct tm tmp;
|
|
time_t test = xmas2002 + 30*60*i;
|
|
if (localtime_r(&test, &tmp) != &tmp) printf("localtime_r failed\n");
|
|
struct tm copy = tmp;
|
|
copy.tm_wday = -1;
|
|
copy.tm_yday = -1;
|
|
if (mktime(©) != test || copy.tm_wday != tmp.tm_wday ||
|
|
copy.tm_yday != tmp.tm_yday || copy.tm_isdst != tmp.tm_isdst)
|
|
mktimeOk = 0;
|
|
}
|
|
printf("localtime <-> mktime: %d\n", mktimeOk);
|
|
|
|
// Verify that mktime is able to guess what the dst is. It might get it wrong
|
|
// during the one ambiguous hour when the clock goes back -- we assume that in
|
|
// no locale that happens on Jul 1 (summer2002) or Dec 25 (xmas2002).
|
|
int oldDstWinter = tm_winter.tm_isdst, oldDstSummer = tm_summer.tm_isdst;
|
|
tm_winter.tm_isdst = tm_summer.tm_isdst = -1;
|
|
mktime(&tm_winter); mktime(&tm_summer);
|
|
printf("mktime guesses DST (winter): %d\n", tm_winter.tm_isdst == oldDstWinter);
|
|
printf("mktime guesses DST (summer): %d\n", tm_summer.tm_isdst == oldDstSummer);
|
|
|
|
// Verify localtime_r() doesn't clobber static data.
|
|
time_t t3 = 60*60*24*5; // Jan 5 1970
|
|
struct tm tm3;
|
|
localtime_r(&t3, &tm3);
|
|
printf("old year still: %d\n", tm_ptr->tm_year);
|
|
printf("new year: %d\n", tm3.tm_year);
|
|
|
|
// Verify time() returns reasonable value (between 2011 and 2030).
|
|
time_t t4 = 0;
|
|
time(&t4);
|
|
timespec ts;
|
|
assert(clock_gettime(CLOCK_REALTIME, &ts) == 0);
|
|
assert(abs(ts.tv_sec - t4) <= 2);
|
|
printf("time: %d\n", t4 > 1309635200ll && t4 < 1893362400ll);
|
|
|
|
// Verify difftime() calculates accurate time difference.
|
|
time_t t5 = 1309635200ll;
|
|
printf("difftime+: %lf\n", difftime(t5, xmas2002));
|
|
printf("difftime-: %lf\n", difftime(xmas2002, t5));
|
|
|
|
// Verify dysize() knows its leap years.
|
|
printf("1854 days: %d\n", dysize(1854));
|
|
printf("2000 days: %d\n", dysize(2000));
|
|
printf("2001 days: %d\n", dysize(2001));
|
|
printf("2004 days: %d\n", dysize(2004));
|
|
|
|
// Verify asctime() formatting().
|
|
printf("asctime: %s", asctime(gmtime(&xmas2002)));
|
|
|
|
tm_ptr = gmtime(&xmas2002);
|
|
char* formatted = asctime(tm_ptr);
|
|
char buffer[32];
|
|
struct tm t6;
|
|
asctime_r(gmtime_r(&summer2002, &t6), buffer);
|
|
printf("winter asctime: %s", formatted);
|
|
printf("summer asctime_r: %s", buffer);
|
|
// Verify asctime_r() and ctime_r() don't clobber static data.
|
|
asctime_r(&t6, buffer);
|
|
ctime_r(&summer2002, buffer);
|
|
printf("winter asctime again: %s", formatted);
|
|
printf("winter month again: %d\n", tm_ptr->tm_mon);
|
|
|
|
// Verify that ctime_r(x, buf) is equivalent to asctime_r(localtime(x), buf).
|
|
time_t t7 = time(0);
|
|
char buffer2[30];
|
|
char buffer3[30];
|
|
printf("ctime matched: %d\n", !strcmp(ctime_r(&t7, buffer2),
|
|
asctime_r(localtime(&t7), buffer3)));
|
|
|
|
// Verify that clock() advances.
|
|
time_t start_t = time(NULL);
|
|
clock_t start = clock();
|
|
printf("clock(start): %d\n", start >= 0);
|
|
while (clock() - start < 2 * CLOCKS_PER_SEC); // Poor man's sleep().
|
|
clock_t diff = time(NULL) - start_t;
|
|
printf("clock(end): %d\n", diff >= 2 && diff < 30);
|
|
|
|
return 0;
|
|
}
|