time64_t timestamp64(time_t (*func)(struct tm*), struct tm64* tm64) { time64_t time; struct tm tm; memset(&tm, 0, sizeof(tm)); /* If this succeeds it fits in a standard struct tm */ if(tm64_to_tm(tm64, &tm) == 0) { time = timestamp64_mktime(func, &tm); /* * This still would fail for 1969-12-31 23:59:59 GMT, but * the fallback code will properly handle that case anyway. */ if(time != -1) { /* Copy back updated information */ tm_to_tm64(&tm, tm64); return time; } } /* * Convert the struct to a year that is day compatible with * the current day. */ int64_t year = tm64->tm_year; if(year < 1902) { /* For years below the 32 bit size time_t value we need to use * the lower comparable years */ int day = day_of_week(year, tm64->tm_mon + 1, tm64->tm_mday); if(tm64->tm_mon == 2 && leap_year(year)) { tm.tm_year = lower_leap_month_table[day] - 1900; } else { tm.tm_year = lower_common_month_table[tm.tm_mon][day] - 1900; } } else if(year > 2037) { /* For years above the 32 bit size time_t value we need to use * the lower comparable years */ int day = day_of_week(year, tm64->tm_mon + 1, tm64->tm_mday); if(tm64->tm_mon == 2 && leap_year(year)) { tm.tm_year = higher_leap_month_table[day] - 1900; } else { tm.tm_year = higher_common_month_table[tm.tm_mon][day] - 1900; } } time = timestamp64_mktime(func, &tm); tm_to_tm64(&tm, tm64); if(year != tm64->tm_year) { /* Correct for the changed year to do the mktime computation */ time += year_diff_to_seconds(tm64->tm_year, year, day_before_leap(tm64)); } tm64->tm_year = year; return time; }
time64_t timestamp64(time_t (*func)(struct tm*), struct tm64* tm64) { struct tm tm; memset(&tm, 0, sizeof(tm)); /* If this succeeds it fits in a standard struct tm */ if(tm64_to_tm(tm64, &tm) == 0) { time64_t time = (time64_t)func(&tm); /* * This still would fail for 1969-12-31 23:59:59 GMT, but * the fallback code will properly handle that case anyway. */ if(time != -1) { /* Copy back updated information */ tm_to_tm64(&tm, tm64); return time; } } /* * Convert the struct to a year that is day compatible with * the current day. */ int64_t year = tm64->tm_year; if(year < 1902) { /* For years below the 32 bit size time_t value we need to use * the lower comparable years */ int day = day_of_week(year, tm64->tm_mon + 1, tm64->tm_mday); if(tm64->tm_mon == 2 && leap_year(year)) { tm.tm_year = lower_leap_month_table[day] - 1900; } else { tm.tm_year = lower_common_month_table[tm.tm_mon][day] - 1900; } } else if(year > 2037) { /* For years above the 32 bit size time_t value we need to use * the lower comparable years */ int day = day_of_week(year, tm64->tm_mon + 1, tm64->tm_mday); if(tm64->tm_mon == 2 && leap_year(year)) { tm.tm_year = higher_leap_month_table[day] - 1900; } else { tm.tm_year = higher_common_month_table[tm.tm_mon][day] - 1900; } } time64_t time = (time64_t) func(&tm); if(time == -1 && errno == EINVAL) { // retry one time because of perhaps DST change. This invalid // time due to DST change only happens if time moves forward, // so we know we start off with DST not active. // This happens at least on NetBSD. tm.tm_isdst = 0; time = (time64_t) func(&tm); } tm_to_tm64(&tm, tm64); if(year != tm64->tm_year) { /* Correct for the changed year to do the mktime computation */ time += year_diff_to_seconds(tm64->tm_year, year, day_before_leap(tm64)); } tm64->tm_year = year; return time; }