- /* time_t isn't large enough to rule out overflows, so check
- for major overflows. A gross check suffices, since if t0
- has overflowed, it is off by a multiple of TIME_T_MAX -
- TIME_T_MIN + 1. So ignore any component of the difference
- that is bounded by a small value. */
-
- /* Approximate log base 2 of the number of time units per
- biennium. A biennium is 2 years; use this unit instead of
- years to avoid integer overflow. For example, 2 average
- Gregorian years are 2 * 365.2425 * 24 * 60 * 60 seconds,
- which is 63113904 seconds, and rint (log2 (63113904)) is
- 26. */
- int ALOG2_SECONDS_PER_BIENNIUM = 26;
- int ALOG2_MINUTES_PER_BIENNIUM = 20;
- int ALOG2_HOURS_PER_BIENNIUM = 14;
- int ALOG2_DAYS_PER_BIENNIUM = 10;
- int LOG2_YEARS_PER_BIENNIUM = 1;
-
- int approx_requested_biennia =
- (SHR (year_requested, LOG2_YEARS_PER_BIENNIUM)
- - SHR (EPOCH_YEAR - TM_YEAR_BASE, LOG2_YEARS_PER_BIENNIUM)
- + SHR (mday, ALOG2_DAYS_PER_BIENNIUM)
- + SHR (hour, ALOG2_HOURS_PER_BIENNIUM)
- + SHR (min, ALOG2_MINUTES_PER_BIENNIUM)
- + (LEAP_SECONDS_POSSIBLE
- ? 0
- : SHR (sec, ALOG2_SECONDS_PER_BIENNIUM)));
-
- int approx_biennia = SHR (t0, ALOG2_SECONDS_PER_BIENNIUM);
- int diff = approx_biennia - approx_requested_biennia;
- int approx_abs_diff = diff < 0 ? -1 - diff : diff;
-
- /* IRIX 4.0.5 cc miscalculates TIME_T_MIN / 3: it erroneously
- gives a positive value of 715827882. Setting a variable
- first then doing math on it seems to work.
- (ghazi@caip.rutgers.edu) */
- time_t time_t_max = TIME_T_MAX;
- time_t time_t_min = TIME_T_MIN;
- time_t overflow_threshold =
- (time_t_max / 3 - time_t_min / 3) >> ALOG2_SECONDS_PER_BIENNIUM;
-
- if (overflow_threshold < approx_abs_diff)
+ if (! ranged_convert (convert, &t, &tm))
+ return -1;
+ long_int dt = tm_diff (year, yday, hour, min, sec, &tm);
+ if (dt == 0)
+ break;
+
+ if (t == t1 && t != t2
+ && (tm.tm_isdst < 0
+ || (isdst < 0
+ ? dst2 <= (tm.tm_isdst != 0)
+ : (isdst != 0) != (tm.tm_isdst != 0))))
+ /* We can't possibly find a match, as we are oscillating
+ between two values. The requested time probably falls
+ within a spring-forward gap of size DT. Follow the common
+ practice in this case, which is to return a time that is DT
+ away from the requested time, preferring a time whose
+ tm_isdst differs from the requested value. (If no tm_isdst
+ was requested and only one of the two values has a nonzero
+ tm_isdst, prefer that value.) In practice, this is more
+ useful than returning -1. */
+ goto offset_found;
+
+ remaining_probes--;
+ if (remaining_probes == 0)