📄 tztime.c
字号:
dstname = name; name = getzname(name); dstlen = name - dstname; /* length of DST zone name */ } if (*name != '\0' && *name != ',' && *name != ';') { name = getoffset(name, &dstoffset); if (name == NULL) return -1; } else dstoffset = stdoffset - SECSPERHOUR; if (*name == '\0' && load_result != 0) name = TZDEFRULESTRING; if (*name == ',' || *name == ';') { struct rule start; struct rule end; register int year; register time_t janfirst; time_t starttime; time_t endtime; ++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 */ /* ** Two transitions per year, from EPOCH_YEAR forward. */ sp->ttis[0].tt_gmtoff = -dstoffset; sp->ttis[0].tt_isdst = 1; sp->ttis[0].tt_abbrind = stdlen + 1; sp->ttis[1].tt_gmtoff = -stdoffset; sp->ttis[1].tt_isdst = 0; sp->ttis[1].tt_abbrind = 0; atp = sp->ats; typep = sp->types; janfirst = 0; for (year = EPOCH_YEAR; sp->timecnt + 2 <= TZ_MAX_TIMES; ++year) { time_t newfirst; starttime = transtime(janfirst, year, &start, stdoffset); endtime = transtime(janfirst, year, &end, dstoffset); if (starttime > endtime) { *atp++ = endtime; *typep++ = 1; /* DST ends */ *atp++ = starttime; *typep++ = 0; /* DST begins */ } else { *atp++ = starttime; *typep++ = 0; /* DST begins */ *atp++ = endtime; *typep++ = 1; /* DST ends */ } sp->timecnt += 2; newfirst = janfirst; newfirst += year_lengths[isleap(year)] * SECSPERDAY; if (newfirst <= janfirst) break; janfirst = newfirst; } } else { register long theirstdoffset; register long theirdstoffset; register long theiroffset; register int isdst; register int i; register int j; if (*name != '\0') return -1; /* ** Initial values of theirstdoffset and theirdstoffset. */ theirstdoffset = 0; for (i = 0; i < sp->timecnt; ++i) { j = sp->types[i]; if (!sp->ttis[j].tt_isdst) { theirstdoffset = -sp->ttis[j].tt_gmtoff; break; } } theirdstoffset = 0; for (i = 0; i < sp->timecnt; ++i) { j = sp->types[i]; if (sp->ttis[j].tt_isdst) { theirdstoffset = -sp->ttis[j].tt_gmtoff; break; } } /* ** Initially we're assumed to be in standard time. */ isdst = FALSE; theiroffset = theirstdoffset; /* ** Now juggle transition times and types ** tracking offsets as you do. */ for (i = 0; i < sp->timecnt; ++i) { j = sp->types[i]; sp->types[i] = sp->ttis[j].tt_isdst; if (sp->ttis[j].tt_ttisgmt) { /* No adjustment to transition time */ } else { /* ** If summer time is in effect, and the ** transition time was not specified as ** standard time, add the summer time ** offset to the transition time; ** otherwise, add the standard time ** offset to the transition time. */ /* ** Transitions from DST to DDST ** will effectively disappear since ** POSIX provides for only one DST ** offset. */ if (isdst && !sp->ttis[j].tt_ttisstd) { sp->ats[i] += dstoffset - theirdstoffset; } else { sp->ats[i] += stdoffset - theirstdoffset; } } theiroffset = -sp->ttis[j].tt_gmtoff; if (sp->ttis[j].tt_isdst) theirdstoffset = theiroffset; else theirstdoffset = theiroffset; } /* ** Finally, fill in ttis. ** ttisstd and ttisgmt need not be handled. */ sp->ttis[0].tt_gmtoff = -stdoffset; sp->ttis[0].tt_isdst = FALSE; sp->ttis[0].tt_abbrind = 0; sp->ttis[1].tt_gmtoff = -dstoffset; sp->ttis[1].tt_isdst = TRUE; sp->ttis[1].tt_abbrind = stdlen + 1; sp->typecnt = 2; } } 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;}static voidgmtload(sp)struct state * const sp;{ if (tzload(gmt, sp, TRUE) != 0) (void) tzparse(gmt, sp, TRUE);}/*** The easy way to behave "as if no library function calls" localtime** is to not call it--so we drop its guts into "localsub", which can be** freely called. (And no, the PANS doesn't require the above behavior--** but it *is* desirable.)**** The unused offset argument is for the benefit of mktime variants.*//*ARGSUSED*/static struct tm *localsub(timep, offset, tmp, sp)const time_t * const timep;const long offset;struct tm * const tmp;struct state * sp;{ register const struct ttinfo * ttisp; register int i; register struct tm * result; const time_t t = *timep;#ifdef ALL_STATE if (sp == NULL) return gmtsub(timep, offset, tmp);#endif /* defined ALL_STATE */ if ((sp->goback && t < sp->ats[0]) || (sp->goahead && t > sp->ats[sp->timecnt - 1])) { time_t newt = t; register time_t seconds; register time_t tcycles; register int_fast64_t icycles; if (t < sp->ats[0]) seconds = sp->ats[0] - t; else seconds = t - sp->ats[sp->timecnt - 1]; --seconds; tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR; ++tcycles; icycles = tcycles; if (tcycles - icycles >= 1 || icycles - tcycles >= 1) return NULL; seconds = icycles; seconds *= YEARSPERREPEAT; seconds *= AVGSECSPERYEAR; if (t < sp->ats[0]) newt += seconds; else newt -= seconds; if (newt < sp->ats[0] || newt > sp->ats[sp->timecnt - 1]) return NULL; /* "cannot happen" */ result = localsub(&newt, offset, tmp, sp); if (result == tmp) { register time_t newy; newy = tmp->tm_year; if (t < sp->ats[0]) newy -= icycles * YEARSPERREPEAT; else newy += icycles * YEARSPERREPEAT; tmp->tm_year = newy; if (tmp->tm_year != newy) return NULL; } return result; } if (sp->timecnt == 0 || t < sp->ats[0]) { i = 0; while (sp->ttis[i].tt_isdst) if (++i >= sp->typecnt) { i = 0; break; } } else { register int lo = 1; register int hi = sp->timecnt; while (lo < hi) { register int mid = (lo + hi) >> 1; if (t < sp->ats[mid]) hi = mid; else lo = mid + 1; } i = (int) sp->types[lo - 1]; } ttisp = &sp->ttis[i]; /* ** To get (wrong) behavior that's compatible with System V Release 2.0 ** you'd replace the statement below with ** t += ttisp->tt_gmtoff; ** timesub(&t, 0L, sp, tmp); */ result = timesub(&t, ttisp->tt_gmtoff, sp, tmp); tmp->tm_isdst = ttisp->tt_isdst;#ifdef HAVE_TM_GMTOFF tmp->tm_gmtoff = ttisp->tt_gmtoff;#endif tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind];#ifdef TM_ZONE tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];#endif /* defined TM_ZONE */ return result;}// ============================================================================#if 0struct tm *localtime(timep)const time_t * const timep;{ tzset(); return localsub(timep, 0L, &tm);}#endif/*** Re-entrant version of localtime.*/// ============================================================================voidlocaltime_tz(const time_t * const timep, struct tm * tmp, const char* tz){ struct state st; if (tzload(tz, &st, TRUE) != 0) { // not sure what's best here, but for now, we fall back to gmt gmtload(&st); } localsub(timep, 0L, tmp, &st);}/*** gmtsub is to gmtime as localsub is to localtime.*/static struct tm *gmtsub(timep, offset, tmp)const time_t * const timep;const long offset;struct tm * const tmp;{ register struct tm * result; if (!gmt_is_set) { gmt_is_set = TRUE;#ifdef ALL_STATE gmtptr = (struct state *) malloc(sizeof *gmtptr); if (gmtptr != NULL)#endif /* defined ALL_STATE */ gmtload(gmtptr); } result = timesub(timep, offset, gmtptr, tmp);#ifdef TM_ZONE /* ** Could get fancy here and deliver something such as ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero, ** but this is no time for a treasure hunt. */ if (offset != 0) tmp->TM_ZONE = wildabbr; else {#ifdef ALL_STATE if (gmtptr == NULL) tmp->TM_ZONE = gmt; else tmp->TM_ZONE = gmtptr->chars;#endif /* defined ALL_STATE */#ifndef ALL_STATE tmp->TM_ZONE = gmtptr->chars;#endif /* State Farm */ }#endif /* defined TM_ZONE */ return result;}// ============================================================================#if 0struct tm *gmtime(timep)const time_t * const timep;{ return gmtsub(timep, 0L, &tm);}#endif/** Re-entrant version of gmtime.*/// ============================================================================#if 0struct tm *gmtime_r(timep, tmp)const time_t * const timep;struct tm * tmp;{ return gmtsub(timep, 0L, tmp);}#endif#ifdef STD_INSPIRED// ============================================================================#if 0struct tm *offtime(timep, offset)const time_t * const timep;const long offset;{ return gmtsub(timep, offset, &tm);}#endif#endif /* defined STD_INSPIRED *//*** Return the number of leap years through the end of the given year** where, to make the math easy, the answer for year zero is defined as zero.*/static intleaps_thru_end_of(y)register const int y;{ return (y >= 0) ? (y / 4 - y / 100 + y / 400) : -(leaps_thru_end_of(-(y + 1)) + 1);}static struct tm *timesub(timep, offset, sp, tmp)const time_t * const timep;const long offset;register const struct state * const sp;register struct tm * const tmp;{ register const struct lsinfo * lp; register time_t tdays; register int idays; /* unsigned would be so 2003 */ register long rem; int y; register const int * ip; register long corr; register int hit; register int i; corr = 0; hit = 0;#ifdef ALL_STATE i = (sp == NULL) ? 0 : sp->leapcnt;#endif /* defined ALL_STATE */#ifndef ALL_STATE i = sp->leapcnt;#endif /* State Farm */ while (--i >= 0) { lp = &sp->lsis[i]; if (*timep >= lp->ls_trans) { if (*timep == lp->ls_trans) { hit = ((i == 0 && lp->ls_corr > 0) || lp->ls_corr > sp->lsis[i - 1].ls_corr); if (hit) while (i > 0 && sp->lsis[i].ls_trans == sp->lsis[i - 1].ls_trans + 1 && sp->lsis[i].ls_corr == sp->lsis[i - 1].ls_corr + 1) { ++hit; --i; } } corr = lp->ls_corr; break; } } y = EPOCH_YEAR; tdays = *timep / SECSPERDAY; rem = *timep - tdays * SECSPERDAY; while (tdays < 0 || tdays >= year_lengths[isleap(y)]) { int newy; register time_t tdelta; register int idelta; register int leapdays; tdelta = tdays / DAYSPERLYEAR; idelta = tdelta; if (tdelta - idelta >= 1 || idelta - tdelta >= 1) return NULL; if (idelta == 0) idelta = (tdays < 0) ? -1 : 1; newy = y; if (increment_overflow(&newy, idelta)) return NULL; leapdays = leaps_thru_end_of(newy - 1) -
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -