📄 tzfile.c
字号:
+ num_isgmt2); off_t off; if (fseek (f, to_skip, SEEK_CUR) != 0 || (off = ftello (f)) < 0 || st.st_size < off + 2) goto lose; tzspec_len = st.st_size - off - 1; char *tzstr = alloca (tzspec_len); if (getc_unlocked (f) != '\n' || (fread_unlocked (tzstr, 1, tzspec_len - 1, f) != tzspec_len - 1)) goto lose; tzstr[tzspec_len - 1] = '\0'; tzspec = __tzstring (tzstr); } fclose (f); /* First "register" all timezone names. */ for (i = 0; i < num_types; ++i) (void) __tzstring (&zone_names[types[i].idx]); /* Find the standard and daylight time offsets used by the rule file. We choose the offsets in the types of each flavor that are transitioned to earliest in time. */ __tzname[0] = NULL; __tzname[1] = NULL; for (i = num_transitions; i > 0; ) { int type = type_idxs[--i]; int dst = types[type].isdst; if (__tzname[dst] == NULL) { int idx = types[type].idx; __tzname[dst] = __tzstring (&zone_names[idx]); if (__tzname[1 - dst] != NULL) break; } } if (__tzname[0] == NULL) { /* This should only happen if there are no transition rules. In this case there should be only one single type. */ assert (num_types == 1); __tzname[0] = __tzstring (zone_names); } if (__tzname[1] == NULL) __tzname[1] = __tzname[0]; compute_tzname_max (chars); if (num_transitions == 0) /* Use the first rule (which should also be the only one). */ rule_stdoff = rule_dstoff = types[0].offset; else { int stdoff_set = 0, dstoff_set = 0; rule_stdoff = rule_dstoff = 0; i = num_transitions - 1; do { if (!stdoff_set && !types[type_idxs[i]].isdst) { stdoff_set = 1; rule_stdoff = types[type_idxs[i]].offset; } else if (!dstoff_set && types[type_idxs[i]].isdst) { dstoff_set = 1; rule_dstoff = types[type_idxs[i]].offset; } if (stdoff_set && dstoff_set) break; } while (i-- > 0); if (!dstoff_set) rule_dstoff = rule_stdoff; } __daylight = rule_stdoff != rule_dstoff; __timezone = -rule_stdoff; __use_tzfile = 1; return; lose: fclose (f); ret_free_transitions: free ((void *) transitions); transitions = NULL;}/* The user specified a hand-made timezone, but not its DST rules. We will use the names and offsets from the user, and the rules from the TZDEFRULES file. */void__tzfile_default (const char *std, const char *dst, long int stdoff, long int dstoff){ size_t stdlen = strlen (std) + 1; size_t dstlen = strlen (dst) + 1; size_t i; int isdst; char *cp; __tzfile_read (TZDEFRULES, stdlen + dstlen, &cp); if (!__use_tzfile) return; if (num_types < 2) { __use_tzfile = 0; return; } /* Ignore the zone names read from the file and use the given ones instead. */ __mempcpy (__mempcpy (cp, std, stdlen), dst, dstlen); zone_names = cp; /* Now there are only two zones, regardless of what the file contained. */ num_types = 2; /* Now correct the transition times for the user-specified standard and daylight offsets from GMT. */ isdst = 0; for (i = 0; i < num_transitions; ++i) { struct ttinfo *trans_type = &types[type_idxs[i]]; /* We will use only types 0 (standard) and 1 (daylight). Fix up this transition to point to whichever matches the flavor of its original type. */ type_idxs[i] = trans_type->isdst; if (trans_type->isgmt) /* The transition time is in GMT. No correction to apply. */ ; else if (isdst && !trans_type->isstd) /* The type says this transition is in "local wall clock time", and wall clock time as of the previous transition was DST. Correct for the difference between the rule's DST offset and the user's DST offset. */ transitions[i] += dstoff - rule_dstoff; else /* This transition is in "local wall clock time", and wall clock time as of this iteration is non-DST. Correct for the difference between the rule's standard offset and the user's standard offset. */ transitions[i] += stdoff - rule_stdoff; /* The DST state of "local wall clock time" for the next iteration is as specified by this transition. */ isdst = trans_type->isdst; } /* Now that we adjusted the transitions to the requested offsets, reset the rule_stdoff and rule_dstoff values appropriately. They are used elsewhere. */ rule_stdoff = stdoff; rule_dstoff = dstoff; /* Reset types 0 and 1 to describe the user's settings. */ types[0].idx = 0; types[0].offset = stdoff; types[0].isdst = 0; types[1].idx = stdlen; types[1].offset = dstoff; types[1].isdst = 1; /* Reset the zone names to point to the user's names. */ __tzname[0] = (char *) std; __tzname[1] = (char *) dst; /* Set the timezone. */ __timezone = -types[0].offset; compute_tzname_max (stdlen + dstlen);}void__tzfile_compute (time_t timer, int use_localtime, long int *leap_correct, int *leap_hit, struct tm *tp){ register size_t i; if (use_localtime) { __tzname[0] = NULL; __tzname[1] = NULL; if (__builtin_expect (num_transitions == 0 || timer < transitions[0], 0)) { /* TIMER is before any transition (or there are no transitions). Choose the first non-DST type (or the first if they're all DST types). */ i = 0; while (i < num_types && types[i].isdst) { if (__tzname[1] == NULL) __tzname[1] = __tzstring (&zone_names[types[i].idx]); ++i; } if (i == num_types) i = 0; __tzname[0] = __tzstring (&zone_names[types[i].idx]); if (__tzname[1] == NULL) { size_t j = i; while (j < num_types) if (types[j].isdst) { __tzname[1] = __tzstring (&zone_names[types[j].idx]); break; } else ++j; } } else if (__builtin_expect (timer >= transitions[num_transitions - 1], 0)) { if (__builtin_expect (tzspec == NULL, 0)) { use_last: i = num_transitions; goto found; } /* Parse the POSIX TZ-style string. */ __tzset_parse_tz (tzspec); /* Convert to broken down structure. If this fails do not use the string. */ if (__builtin_expect (! __offtime (&timer, 0, tp), 0)) goto use_last; /* Use the rules from the TZ string to compute the change. */ __tz_compute (timer, tp, 1); /* If tzspec comes from posixrules loaded by __tzfile_default, override the STD and DST zone names with the ones user requested in TZ envvar. */ if (__builtin_expect (zone_names == (char *) &leaps[num_leaps], 0)) { assert (num_types == 2); __tzname[0] = __tzstring (zone_names); __tzname[1] = __tzstring (&zone_names[strlen (zone_names) + 1]); } *leap_correct = 0L; *leap_hit = 0; return; } else { /* Find the first transition after TIMER, and then pick the type of the transition before it. */ size_t lo = 0; size_t hi = num_transitions - 1; /* Assume that DST is changing twice a year and guess initial search spot from it. Half of a gregorian year has on average 365.2425 * 86400 / 2 = 15778476 seconds. */ i = (transitions[num_transitions - 1] - timer) / 15778476; if (i < num_transitions) { i = num_transitions - 1 - i; if (timer < transitions[i]) { if (i < 10 || timer >= transitions[i - 10]) { /* Linear search. */ while (timer < transitions[i - 1]) --i; goto found; } hi = i - 10; } else { if (i + 10 >= num_transitions || timer < transitions[i + 10]) { /* Linear search. */ while (timer >= transitions[i]) ++i; goto found; } lo = i + 10; } } /* Binary search. */ /* assert (timer >= transitions[lo] && timer < transitions[hi]); */ while (lo + 1 < hi) { i = (lo + hi) / 2; if (timer < transitions[i]) hi = i; else lo = i; } i = hi; found: /* assert (timer >= transitions[i - 1] && (i == num_transitions || timer < transitions[i])); */ __tzname[types[type_idxs[i - 1]].isdst] = __tzstring (&zone_names[types[type_idxs[i - 1]].idx]); size_t j = i; while (j < num_transitions) { int type = type_idxs[j]; int dst = types[type].isdst; int idx = types[type].idx; if (__tzname[dst] == NULL) { __tzname[dst] = __tzstring (&zone_names[idx]); if (__tzname[1 - dst] != NULL) break; } ++j; } if (__builtin_expect (__tzname[0] == NULL, 0)) __tzname[0] = __tzname[1]; i = type_idxs[i - 1]; } struct ttinfo *info = &types[i]; __daylight = rule_stdoff != rule_dstoff; __timezone = -rule_stdoff; if (__tzname[0] == NULL) { /* This should only happen if there are no transition rules. In this case there should be only one single type. */ assert (num_types == 1); __tzname[0] = __tzstring (zone_names); } if (__tzname[1] == NULL) /* There is no daylight saving time. */ __tzname[1] = __tzname[0]; tp->tm_isdst = info->isdst; assert (strcmp (&zone_names[info->idx], __tzname[tp->tm_isdst]) == 0); tp->tm_zone = __tzname[tp->tm_isdst]; tp->tm_gmtoff = info->offset; } *leap_correct = 0L; *leap_hit = 0; /* Find the last leap second correction transition time before TIMER. */ i = num_leaps; do if (i-- == 0) return; while (timer < leaps[i].transition); /* Apply its correction. */ *leap_correct = leaps[i].change; if (timer == leaps[i].transition && /* Exactly at the transition time. */ ((i == 0 && leaps[i].change > 0) || leaps[i].change > leaps[i - 1].change)) { *leap_hit = 1; while (i > 0 && leaps[i].transition == leaps[i - 1].transition + 1 && leaps[i].change == leaps[i - 1].change + 1) { ++*leap_hit; --i; } }}static voidinternal_functioncompute_tzname_max (size_t chars){ const char *p; p = zone_names; do { const char *start = p; while (*p != '\0') ++p; if ((size_t) (p - start) > __tzname_cur_max) __tzname_cur_max = p - start; } while (++p < &zone_names[chars]);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -