#include #include #include #include time_t start_time(void) { // return the start of our time range // we want 12:00 local time on January 1st of the first year >= 1880 // we can represent (1880, because time zones based on GMT were // enacted in 1885, so we start a little bit earlier if we can) for (int y = 1880; y < 2000; y++) { struct tm tm; tm.tm_year = y - 1900; tm.tm_mon = 0; tm.tm_mday = 1; tm.tm_hour = 12; tm.tm_min = 0; tm.tm_sec = 0; tm.tm_isdst = -1; time_t t = mktime(&tm); if (t != (time_t)-1) { return t; } } assert(0); // no date before 2000 representable? mktime is broken } time_t end_time(void) { // return the end of our time range // 12:00 local time on dec. 31 of the current year seems ok. // we might want to extend that a few years into the future, but // it's hard to say how much: Sometimes DST changes are only // published weeks before they happen, so even the end of the year // is a bit optimistic. time_t t = time(NULL); struct tm *tmp = localtime(&t); struct tm tm; tm.tm_year = tmp->tm_year; tm.tm_mon = 11; tm.tm_mday = 31; tm.tm_hour = 12; tm.tm_min = 0; tm.tm_sec = 0; tm.tm_isdst = -1; t = mktime(&tm); if (t != (time_t)-1) { return t; } assert(0); // end of current year not representable? mktime is broken } int_least32_t diff(struct tm utm, struct tm ltm) { int_least32_t d; // local time should be close to noon, timezones are somwhere in // the +/- 14 hours range, so the UTC date can differ by at most one // date. Therefore we just check whether the UTC date is earlier or // later than the local date. if (ltm.tm_year > utm.tm_year) { d = 86400; } else if (ltm.tm_year < utm.tm_year) { d = -86400; } else { if (ltm.tm_mon > utm.tm_mon) { d = 86400; } else if (ltm.tm_mon < utm.tm_mon) { d = -86400; } else { if (ltm.tm_mday > utm.tm_mday) { d = 86400; } else if (ltm.tm_mday < utm.tm_mday) { d = -86400; } else { d = 0; } } } d += (ltm.tm_hour - utm.tm_hour) * 3600 + (ltm.tm_min - utm.tm_min) * 60 + (ltm.tm_sec - utm.tm_sec); return d; } int main(void) { time_t start = start_time(); time_t end = end_time(); for (time_t t = start; t <= end; t += 24*3600) { struct tm utm = *(gmtime(&t)); struct tm ltm = *(localtime(&t)); int_least32_t d = diff(utm, ltm); printf("%.0f %.0f\n", (double)t, (double)d); } }