📄 timezone.c
字号:
stdlen = name - stdname; if (stdlen < 3) return -1; if (*name == '\0') return -1; name = getoffset(name, &stdoffset); if (name == NULL) return -1; if (*name != '\0') { dstname = name; name = getzname(name); dstlen = name - dstname; /* length of DST zone name */ if (dstlen < 3) return -1; if (*name != '\0' && *name != ',' && *name != ';') { name = getoffset(name, &dstoffset); if (name == NULL) return -1; } else dstoffset = stdoffset - SECSPERHOUR; if (*name == '\0') name = TZDEFRULESTRING; if (*name == ',' || *name == ';') { struct rule start; struct rule end; ++name; if ((name = getrule(name, &start)) == NULL) return -1; if (*name++ != ',') return -1; if ((name = getrule(name, &end)) == NULL) return -1; if (*name != '\0') return -1; sp->typecnt = 2; /* standard time and DST */ sp->ttis[0].tt_gmtoff = -stdoffset; sp->ttis[0].tt_isdst = 0; sp->ttis[0].tt_abbrind = 0; sp->ttis[1].tt_gmtoff = -dstoffset; sp->ttis[1].tt_isdst = 1; sp->ttis[1].tt_abbrind = stdlen + 1; generate_transitions(sp, &start, &end); } } else { dstlen = 0; sp->typecnt = 1; /* only standard time */ sp->timecnt = 0; sp->ttis[0].tt_gmtoff = -stdoffset; sp->ttis[0].tt_isdst = 0; sp->ttis[0].tt_abbrind = 0; } sp->charcnt = stdlen + 1; if (dstlen != 0) sp->charcnt += dstlen + 1; if ((size_t) sp->charcnt > sizeof(sp->chars)) return -1; cp = sp->chars; (void) strncpy(cp, stdname, stdlen); cp += stdlen; *cp++ = '\0'; if (dstlen != 0) { (void) strncpy(cp, dstname, dstlen); *(cp + dstlen) = '\0'; } return 0;}void tzset(){ char *TZstring; int dstfirst; static char *old_TZstring = NULL; TZstring = getenv("TZ"); /* read TZ envvar */ if (old_TZstring && TZstring && !strcmp(old_TZstring, TZstring)) /* do not repeatedly parse an unchanged TZ specification */ return; if ((TZstring && TZstring[0] && Parse_TZ(TZstring, &statism) == 0) || IZTZ_GETLOCALETZINFO(&statism, generate_transitions) || Parse_TZ(gmt, &statism) == 0) { daylight = statism.typecnt > 1; dstfirst = daylight && statism.ttis[0].tt_isdst && !statism.ttis[1].tt_isdst; timezone = -statism.ttis[dstfirst].tt_gmtoff; tzname[0] = statism.chars + statism.ttis[dstfirst].tt_abbrind; tzname[1] = statism.chars + statism.ttis[!dstfirst].tt_abbrind; real_timezone_is_set = TRUE; if (TZstring) { if (old_TZstring) old_TZstring = realloc(old_TZstring, strlen(TZstring) + 1); else old_TZstring = malloc(strlen(TZstring) + 1); if (old_TZstring) strcpy(old_TZstring, TZstring); } } else { timezone = 0; /* default is GMT0 which means no offsets */ daylight = 0; /* from local system time */ real_timezone_is_set = FALSE; if (old_TZstring) { free(old_TZstring); old_TZstring = NULL; } }#ifdef IZTZ_SETLOCALTZINFO /* Some SAS/C library functions, e.g. stat(), call library */ /* __tzset() themselves. So envvar TZ *must* exist in order to */ /* to get the right offset from GMT. XXX TRY HARD to fix this! */ set_TZ(timezone, daylight);#endif /* IZTZ_SETLOCALTZINFO */}/* XXX Does this also help SAS/C library work? */void __tzset(){ if (!real_timezone_is_set) tzset();}static struct tm _tmbuf;struct tm *gmtime(when) ZCONST time_t *when;{ long days = *when / SECSPERDAY; long secs = *when % SECSPERDAY; int isleap; memset(&_tmbuf, 0, sizeof(_tmbuf)); /* get any nonstandard fields */ _tmbuf.tm_wday = (days + EPOCH_WDAY) % 7; _tmbuf.tm_year = EPOCH_YEAR - TM_YEAR_BASE; isleap = leap(_tmbuf.tm_year + TM_YEAR_BASE); while (days >= year_lengths[isleap]) { days -= year_lengths[isleap]; _tmbuf.tm_year++; isleap = leap(_tmbuf.tm_year + TM_YEAR_BASE); } _tmbuf.tm_mon = 0; _tmbuf.tm_yday = days; while (days >= mon_lengths[isleap][_tmbuf.tm_mon]) days -= mon_lengths[isleap][_tmbuf.tm_mon++]; _tmbuf.tm_mday = days + 1; _tmbuf.tm_isdst = 0; _tmbuf.tm_sec = secs % SECSPERMIN; _tmbuf.tm_min = (secs / SECSPERMIN) % SECSPERMIN; _tmbuf.tm_hour = secs / SECSPERHOUR; return &_tmbuf;}struct tm *localtime(when) ZCONST time_t *when;{ time_t localwhen = *when; int timetype; struct tm *ret; __tzset(); if (statism.timecnt == 0 || localwhen < statism.ats[0]) timetype = statism.ttis[0].tt_isdst && statism.typecnt > 1 && !statism.ttis[1].tt_isdst; else { for (timetype = 1; timetype < statism.timecnt; ++timetype) if (localwhen < statism.ats[timetype]) break; timetype = statism.types[timetype - 1]; } localwhen += statism.ttis[timetype].tt_gmtoff; ret = gmtime(&localwhen); ret->tm_isdst = statism.ttis[timetype].tt_isdst; return ret;}#ifdef NEED__ISINDSTint _isindst(tb) struct tm *tb;{ time_t localt; /* time_t equivalent of given tm struct */ time_t univt; /* assumed UTC value of given time */ long tzoffset_adj; /* timezone-adjustment `remainder' */ int bailout_cnt; /* counter of tries for tz correction */ int timetype; __tzset(); /* when DST is unsupported in current timezone, DST is always off */ if (statism.typecnt <= 1) return FALSE; localt = mkgmtime(tb); if (localt == (time_t)-1) /* specified time is out-of-range, default to FALSE */ return FALSE; univt = localt - statism.ttis[0].tt_gmtoff; bailout_cnt = 3; do { if (statism.timecnt == 0 || univt < statism.ats[0]) timetype = statism.ttis[0].tt_isdst && statism.typecnt > 1 && !statism.ttis[1].tt_isdst; else { for (timetype = 1; timetype < statism.timecnt; ++timetype) if (univt < statism.ats[timetype]) break; timetype = statism.types[timetype - 1]; } if ((tzoffset_adj = localt - univt - statism.ttis[timetype].tt_gmtoff) == 0L) break; univt += tzoffset_adj; } while (--bailout_cnt > 0); /* return TRUE when DST is active at given time */ return (statism.ttis[timetype].tt_isdst);}#endif /* NEED__ISINDST */#endif /* !IZ_MKTIME_ONLY *//* Return the equivalent in seconds past 12:00:00 a.m. Jan 1, 1970 GMT of the local time and date in the exploded time structure `tm', adjust out of range fields in `tm' and set `tm->tm_yday', `tm->tm_wday'. If `tm->tm_isdst < 0' was passed to mktime(), the correct setting of tm_isdst is determined and returned. Otherwise, mktime() assumes this field as valid; its information is used when converting local time to UTC. Return -1 if time in `tm' cannot be represented as time_t value. */time_t mktime(tm) struct tm *tm;{ struct tm *ltm; /* Local time. */ time_t loctime; /* The time_t value of local time. */ time_t then; /* The time to return. */ long tzoffset_adj; /* timezone-adjustment `remainder' */ int bailout_cnt; /* counter of tries for tz correction */ int save_isdst; /* Copy of the tm->isdst input value */ save_isdst = tm->tm_isdst; loctime = mkgmtime(tm); if (loctime == -1) { tm->tm_isdst = save_isdst; return (time_t)-1; } /* Correct for the timezone and any daylight savings time. The correction is verified and repeated when not correct, to take into account the rare case that a change to or from daylight savings time occurs between when it is the time in `tm' locally and when it is that time in Greenwich. After the second correction, the "timezone & daylight" offset should be correct in all cases. To be sure, we allow a third try, but then the loop is stopped. */ bailout_cnt = 3; then = loctime; do { ltm = localtime(&then); if (ltm == (struct tm *)NULL || (tzoffset_adj = loctime - mkgmtime(ltm)) == 0L) break; then += tzoffset_adj; } while (--bailout_cnt > 0); if (ltm == (struct tm *)NULL || tzoffset_adj != 0L) { /* Signal failure if timezone adjustment did not converge. */ tm->tm_isdst = save_isdst; return (time_t)-1; } if (save_isdst >= 0) { if (ltm->tm_isdst && !save_isdst) { if (then + 3600 < then) then = (time_t)-1; else then += 3600; } else if (!ltm->tm_isdst && save_isdst) { if (then - 3600 > then) then = (time_t)-1; else then -= 3600; } ltm->tm_isdst = save_isdst; } if (tm != ltm) /* `tm' may already point to localtime's internal storage */ *tm = *ltm; return then;}#ifndef NO_TIME_T_MAX /* Provide default values for the upper limit of the time_t range. These are the result of the decomposition into a `struct tm' for the time value 0xFFFFFFFEL ( = (time_t)-2 ). Note: `(time_t)-1' is reserved for "invalid time"! */# ifndef TM_YEAR_MAX# define TM_YEAR_MAX 2106# endif# ifndef TM_MON_MAX# define TM_MON_MAX 1 /* February */# endif# ifndef TM_MDAY_MAX# define TM_MDAY_MAX 7# endif# ifndef TM_HOUR_MAX# define TM_HOUR_MAX 6# endif# ifndef TM_MIN_MAX# define TM_MIN_MAX 28# endif# ifndef TM_SEC_MAX# define TM_SEC_MAX 14# endif#endif /* NO_TIME_T_MAX *//* Adjusts out-of-range values for `tm' field `tm_member'. */#define ADJUST_TM(tm_member, tm_carry, modulus) \ if ((tm_member) < 0) { \ tm_carry -= (1 - ((tm_member)+1) / (modulus)); \ tm_member = (modulus-1) + (((tm_member)+1) % (modulus)); \ } else if ((tm_member) >= (modulus)) { \ tm_carry += (tm_member) / (modulus); \ tm_member = (tm_member) % (modulus); \ }/* Return the equivalent in seconds past 12:00:00 a.m. Jan 1, 1970 GMT of the Greenwich Mean time and date in the exploded time structure `tm'. This function does always put back normalized values into the `tm' struct, parameter, including the calculated numbers for `tm->tm_yday', `tm->tm_wday', and `tm->tm_isdst'. Returns -1 if the time in the `tm' parameter cannot be represented as valid `time_t' number. */time_t mkgmtime(tm) struct tm *tm;{ int years, months, days, hours, minutes, seconds; years = tm->tm_year + TM_YEAR_BASE; /* year - 1900 -> year */ months = tm->tm_mon; /* 0..11 */ days = tm->tm_mday - 1; /* 1..31 -> 0..30 */ hours = tm->tm_hour; /* 0..23 */ minutes = tm->tm_min; /* 0..59 */ seconds = tm->tm_sec; /* 0..61 in ANSI C. */ ADJUST_TM(seconds, minutes, 60) ADJUST_TM(minutes, hours, 60) ADJUST_TM(hours, days, 24) ADJUST_TM(months, years, 12) if (days < 0) do { if (--months < 0) { --years; months = 11; } days += monthlen(months, years); } while (days < 0); else while (days >= monthlen(months, years)) { days -= monthlen(months, years); if (++months >= 12) { ++years; months = 0; } } /* Restore adjusted values in tm structure */ tm->tm_year = years - TM_YEAR_BASE; tm->tm_mon = months; tm->tm_mday = days + 1; tm->tm_hour = hours; tm->tm_min = minutes; tm->tm_sec = seconds; /* Set `days' to the number of days into the year. */ days += YDAYS(months, years); tm->tm_yday = days; /* Now calculate `days' to the number of days since Jan 1, 1970. */ days = (unsigned)days + 365 * (unsigned)(years - EPOCH_YEAR) + (unsigned)(nleap (years)); tm->tm_wday = ((unsigned)days + EPOCH_WDAY) % 7; tm->tm_isdst = 0; if (years < EPOCH_YEAR) return (time_t)-1;#if (defined(TM_YEAR_MAX) && defined(TM_MON_MAX) && defined(TM_MDAY_MAX))#if (defined(TM_HOUR_MAX) && defined(TM_MIN_MAX) && defined(TM_SEC_MAX)) if (years > TM_YEAR_MAX || (years == TM_YEAR_MAX && (tm->tm_yday > (YDAYS(TM_MON_MAX, TM_YEAR_MAX) + (TM_MDAY_MAX - 1)) || (tm->tm_yday == (YDAYS(TM_MON_MAX, TM_YEAR_MAX) + (TM_MDAY_MAX - 1)) && (hours > TM_HOUR_MAX || (hours == TM_HOUR_MAX && (minutes > TM_MIN_MAX || (minutes == TM_MIN_MAX && seconds > TM_SEC_MAX) ))))))) return (time_t)-1;#endif#endif return (time_t)(SECSPERDAY * (unsigned long)(unsigned)days + SECSPERHOUR * (unsigned long)hours + (unsigned long)(SECSPERMIN * minutes + seconds));}#endif /* __timezone_c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -