📄 tzset.c
字号:
/* Determine the seconds west of GMT and the dst rules */ if (gettimeofday(&tv, &tz)) return -1; sw = tz.tz_minuteswest * 60; dr = dayrules; while (dr->dst_type >= 0 && dr->dst_type != tz.tz_dsttime) dr++; /* Create the transition time using the old rules */ tzset_compat(dr, sw, _tztab(tz.tz_minuteswest, 0), _tztab(tz.tz_minuteswest, 1));#if defined(SYSTEM_FIVE) || defined(_XOPEN_SOURCE) TIMEZONE = tz.tz_minuteswest * 60; DAYLIGHT = tz.tz_dsttime;#endif return 0;}/* * Non-System V specific routines */#ifndef SYSTEM_FIVE/* * utoi() converts an unsigned string of 1 or more digts, and performs * range checking according to supplied limits. A pointer to the first * non-digit is returned, unless there is an error, in which case a * null pointer is returned. */static char *utoi(p, ip, minv, maxv)register char *p;int *ip;int minv;int maxv;{ register int i; /* Make sure we've got at least one digit */ if (*p < '0' || *p > '9') return (char *)0; /* Convert until first non-digit */ i = 0; do i = (i * 10) + *p++ - '0'; while (*p >= '0' && *p <= '9'); /* Make sure the number is in range */ if (i < minv || i > maxv) return (char *)0; /* Return the number and updated pointer */ *ip = i; return p;} /* * tzsetenv() sets the time conversion information according to the TZ * environment variable. The format, as specified by POSIX 1003.1, is: * * stdoffset[dst[offset][,start[/time],end[/time]]] * * A status is returned to indicate if the string was correct. A zero * value indicates it was correct; non-zero indicates it was incorrect. */statictzsetenv(p)register char * p;{ register int tti; /* transistion time info index */ int val; int i; static int secs_per_hms[3] = {SECS_PER_HOUR, SECS_PER_MIN, 1}; _tzs.timecnt = tti = 0; tzname[1] = ""; /* Get std and dst zone names */ { register int ai = 0; /* abbreviation index */ int len; int gmtoff; char sign = '+'; int negate_gmt = 0; do { /* Copy time zone abbreviation string */ tzname[tti] = &_tzs.chars[ai]; _tzs.ttis[tti].tt_abbrind = ai; len = 0; while ((*p && *p < '+') || (*p > '-' && *p < '0') || *p > '9') { _tzs.chars[ai++] = *p++; if (ai == TZ_MAX_CHARS) return -1; len++; }; _tzs.chars[ai++] = '\0'; if (len < 3) return -1; /* Get the offset's sign, if there is one */ if (*p == '+' || *p == '-') sign = *p++; /* Get the offset if there is one, or should be */ if (sign || (*p >= '0' && *p <= '9')) { gmtoff = 0; if (sign != '-') negate_gmt = 1; for (i = 0;;) { if (!(p = utoi(p, &val, 0, 59))) return -1; gmtoff += val * secs_per_hms[i]; i++; if (*p != ':' || i == 3) break; p++; }; } else /* We only get here if the offset for dst is */ /* being defaulted. Since the offset for std */ /* must be specified, gmtoff is guaranteed to */ /* contain the std offset */ gmtoff += SECS_PER_HOUR; /* Compensate for backwards '-' flag */ if (negate_gmt) gmtoff = -gmtoff; negate_gmt = 0; sign = 0; _tzs.ttis[tti].tt_gmtoff = gmtoff; /* Indicate if this zone is in daylight savings time */ _tzs.ttis[tti].tt_isdst = tti; /* Set up table bookkeeping for mktime() without rule */ _tzs.types[tti] = tti; } while (++tti < 2 && *p != ',' && *p != '\0'); }; _tzs.timecnt = tti; /* Process the optional rule */ if (tti == 2 && *p == ',') { int hms[2]; int m[2], n[2], d[2]; int jday[2]; char day_spec[2]; int j; register time_t ytt; int y; int tc; int ly; register int tday; /* transition day */ register int wday; static int jday_of_month[2][MONS_PER_YEAR] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }; /* First thing we do is parse the rule */ for (i = 0; i < 2; i++) { /* Check for mandatory ',' */ if (*p++ != ',') return -1; /* Get the day specifier */ if ((day_spec[i] = *p) == 'M') { /* Mm.n.d (nth day (d) of month (m)) */ p++; if (!(p = utoi(p, &m[i], 1, 12)) || *p++ != '.') return -1; if (!(p = utoi(p, &n[i], 1, 5)) || *p++ != '.') return -1; if (!(p = utoi(p, &d[i], 0, 6))) return -1; } else { /* Jn or n (Julian day) */ if (*p == 'J') p++; if (!(p = utoi(p, &jday[i], day_spec[i] == 'J', 365))) return -1; }; /* Get the optional time specifier */ if (*p == '/') { p++; hms[i] = 0; for (j = 0;;) { if (!(p = utoi(p, &val, 0, 59))) return -1; hms[i] += val * secs_per_hms[j]; j++; if (*p != ':' || j == 3) break; p++; }; } else hms[i] = 2 * SECS_PER_HOUR; }; /* Now for every year that is representable by a time_t */ /* value, create a pair of transition times. One for the */ /* start and one for the end of summer time. The transition */ /* times are used by localtime() in determining whether */ /* standard or summer time is in effect */ /* The following *_year symbols, represent the minimum */ /* and maximum whole years representable by the time_t */ /* type. These definitions assume that time_t is a */ /* signed long */#define t_min_year (time_t)0x8017e880 /* Minimum year in time_t format */#define min_year 1902 /* Minimum year */#define max_year 2037 /* Maximum year */#define feb28_day (31 + 28) /* Julian day (1 based) of Feb 28th */ tc = 0; ytt = t_min_year; /* Create a pair of transition times for each year */ for (y = min_year; y <= max_year; y++) { ly = isleap(y); for (i = 0; i < 2; i++) { /* Determine the transition time according */ /* to its specification */ if (day_spec[i] == 'M') { /* day of month */ tday = jday_of_month[ly][m[i]-1]; wday = (d[i] - ((ytt / SECS_PER_DAY) + EPOCH_WDAY + tday)) % DAYS_PER_WEEK; if (wday < 0) wday += DAYS_PER_WEEK; tday += wday; tday += (n[i] - 1) * DAYS_PER_WEEK; if (tday >= jday_of_month[ly][m[i]]) tday -= DAYS_PER_WEEK; } else { /* day of year */ tday = jday[i]; if (day_spec[i] == 'J' && (!ly || tday < feb28_day)) tday--; }; /* Store the transition time and type index */ _tzs.ats[tc] = ytt + hms[i] + (tday * SECS_PER_DAY) - _tzs.ttis[i].tt_gmtoff; _tzs.types[tc] = i ^ 1; tc++; }; ytt += DAYS_PER_NYEAR * SECS_PER_DAY; if (ly) ytt += SECS_PER_DAY; }; _tzs.timecnt = tc; };#if defined(_XOPEN_SOURCE) TIMEZONE = -_tzs.ttis[0].tt_gmtoff; DAYLIGHT = (tti>1);#endif /* If not at end of string, then there was something unexpected */ return *p != '\0';}#endif/* * System V specific routines. */#ifdef SYSTEM_FIVE/* * tzsetenv() sets the time zone information according to the TZ * environment variable using the System V format of stdoffsetdst. * For compatiblity, the transition times are computed using the same * brain damaged rules as System V. This routine always succeeds, but * the results may be bogus if the format of the variable is incorrect. */statictzsetenv(p)register char * p;{ register int n; char sign; char *std = "123"; char *dst = "123"; struct dayrule *dr = dayrules; /* Copy the "std" designation */ n = 0; do std[n] = *p ? *p++ : ' '; while (++n < 3); /* Get the offset, which may be preceded by a minus sign */ if (sign = *p == '-') p++; n = 0; while (*p >= '0' && *p <= '9') n = (n * 10) + *p++ - '0'; /* Compute the time zone offset */ if (sign) n = -n; TIMEZONE = ((long)(n * 60)) * 60; /* If "dst" is specified, get it */ if ((DAYLIGHT = *p) != '\0') { /* Get the "dst" designation */ n = 0; do dst[n] = *p ? *p++ : ' '; while (++n < 3); } else dr++; /* Create the transition time using the old rules */ tzset_compat(dr, timezone, std, dst); return 0;}#endif/* * tzset() is used to initialize the time conversion information * used by localtime() and mktime(). */voidtzset(){ register char * name; register char * tzpath;#ifdef SYSTEM_FIVE#define tzpath_of(n) (n)#define wants_gmt(n) (n && !*n)#define envar(n) (n)#else#define tzpath_of(n) ((n && *n == ':') ? &n[1] : (char *)0)#define wants_gmt(n) (n && *n == ':' && !n[1])#define envar(n) (n && !tzpath)#endif /* SYSTEM_FIVE */ _tz_is_set = TRUE; if (name = getenv("TZ")) strncpy(_last_tz_set, name, sizeof(_last_tz_set)); else _last_tz_set[0] = '\0'; if (!wants_gmt(name)) { /* did not request GMT */ tzpath = tzpath_of(name); if (tzpath && !tzload(tzpath)) /* requested path worked */ return; if (envar(name) && !tzsetenv(name)) /* environment string worked */ return; if (!tzload((char *)0)) /* default name worked */ return; if (!tzsetkernel()) /* kernel guess worked */ return; } tzsetgmt(); /* GMT is default */}static struct zone { int offset; char *stdzone; char *dlzone;} zonetab[] = { -1*60, "MET", "MET DST", /* Middle European */ -2*60, "EET", "EET DST", /* Eastern European */ 4*60, "AST", "ADT", /* Atlantic */ 5*60, "EST", "EDT", /* Eastern */ 6*60, "CST", "CDT", /* Central */ 7*60, "MST", "MDT", /* Mountain */ 8*60, "PST", "PDT", /* Pacific */#ifdef notdef /* there's no way to distinguish this from WET */ 0, "GMT", 0, /* Greenwich */#endif 0*60, "WET", "WET DST", /* Western European */ -10*60, "EST", "EST", /* Aust: Eastern */ -10*60+30, "CST", "CST", /* Aust: Central */ -8*60, "WST", 0, /* Aust: Western */ -1};/* * _tztab -- * check static tables or create a new zone name; broken out from * timezone() so that we can make a guess as to what the zone is if * the standard tables aren't in place in /etc. * DO NOT USE THIS ROUTINE OUTSIDE OF THE STANDARD LIBRARY. */char *_tztab(zone,dst) register int zone; int dst;{ register struct zone *zp; register char *cp; static char czone[] = "GMT+nn:nn"; /* space for zone name */ /* search static tables */ for (zp = zonetab; zp->offset != -1;++zp) if (zp->offset == zone) { if (dst && zp->dlzone) return(zp->dlzone); if (!dst && zp->stdzone) return(zp->stdzone); } /* create one */ cp = &czone[3]; if (zone < 0) { zone = -zone; *cp++ = '+'; } else *cp++ = '-'; if ((*cp = zone / 600) != 0) { *cp++ += '0'; zone %= 600; }; *cp++ = (zone / 60) + '0'; zone %= 60; *cp++ = ':'; *cp++ = (zone / 10) + '0'; *cp++ = (zone % 10) + '0'; *cp = '\0'; return(czone);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -