📄 localtime.c
字号:
{ if (*strp == 'J') { /* ** Julian day. */ rulep->r_type = JULIAN_DAY; ++strp; strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR); } else if (*strp == 'M') { /* ** Month, week, day. */ rulep->r_type = MONTH_NTH_DAY_OF_WEEK; ++strp; strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR); if (strp == NULL) return NULL; if (*strp++ != '.') return NULL; strp = getnum(strp, &rulep->r_week, 1, 5); if (strp == NULL) return NULL; if (*strp++ != '.') return NULL; strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1); } else if (is_digit(*strp)) { /* ** Day of year. */ rulep->r_type = DAY_OF_YEAR; strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1); } else return NULL; /* invalid format */ if (strp == NULL) return NULL; if (*strp == '/') { /* ** Time specified. */ ++strp; strp = getsecs(strp, &rulep->r_time); } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */ return strp;}/*! \brief * Given the Epoch-relative time of January 1, 00:00:00 GMT, in a year, the * year, a rule, and the offset from GMT at the time that rule takes effect, * calculate the Epoch-relative time that rule takes effect.*/static time_t transtime(janfirst, year, rulep, offset)const time_t janfirst;const int year;register const struct rule * const rulep;const long offset;{ register int leapyear; register time_t value = 0; register int i; int d, m1, yy0, yy1, yy2, dow; leapyear = isleap(year); switch (rulep->r_type) { case JULIAN_DAY: /* ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap ** years. ** In non-leap years, or if the day number is 59 or less, just ** add SECSPERDAY times the day number-1 to the time of ** January 1, midnight, to get the day. */ value = janfirst + (rulep->r_day - 1) * SECSPERDAY; if (leapyear && rulep->r_day >= 60) value += SECSPERDAY; break; case DAY_OF_YEAR: /* ** n - day of year. ** Just add SECSPERDAY times the day number to the time of ** January 1, midnight, to get the day. */ value = janfirst + rulep->r_day * SECSPERDAY; break; case MONTH_NTH_DAY_OF_WEEK: /* ** Mm.n.d - nth "dth day" of month m. */ value = janfirst; for (i = 0; i < rulep->r_mon - 1; ++i) value += mon_lengths[leapyear][i] * SECSPERDAY; /* ** Use Zeller's Congruence to get day-of-week of first day of ** month. */ m1 = (rulep->r_mon + 9) % 12 + 1; yy0 = (rulep->r_mon <= 2) ? (year - 1) : year; yy1 = yy0 / 100; yy2 = yy0 % 100; dow = ((26 * m1 - 2) / 10 + 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7; if (dow < 0) dow += DAYSPERWEEK; /* ** "dow" is the day-of-week of the first day of the month. Get ** the day-of-month (zero-origin) of the first "dow" day of the ** month. */ d = rulep->r_day - dow; if (d < 0) d += DAYSPERWEEK; for (i = 1; i < rulep->r_week; ++i) { if (d + DAYSPERWEEK >= mon_lengths[leapyear][rulep->r_mon - 1]) break; d += DAYSPERWEEK; } /* ** "d" is the day-of-month (zero-origin) of the day we want. */ value += d * SECSPERDAY; break; } /* ** "value" is the Epoch-relative time of 00:00:00 GMT on the day in ** question. To get the Epoch-relative time of the specified local ** time on that day, add the transition time and the current offset ** from GMT. */ return value + rulep->r_time + offset;}/*** Given a POSIX section 8-style TZ string, fill in the rule tables as** appropriate.*/static inttzparse(name, sp, lastditch)const char * name;register struct state * const sp;const int lastditch;{ const char * stdname; const char * dstname = NULL; size_t stdlen = 0; size_t dstlen = 0; long stdoffset = 0L; long dstoffset = 0L; register time_t * atp; register unsigned char * typep; register char * cp; register int load_result; stdname = name;#ifdef DEBUG fprintf(stderr, "tzparse(): loading default rules\n");#endif load_result = tzload(TZDEFRULES, sp); if (load_result != 0) sp->leapcnt = 0; /* so, we're off a little */ if (*name != '\0') { if (*name != '\0' && *name != ',' && *name != ';') { name = getoffset(name, &dstoffset); if (name == NULL) return -1; } else dstoffset = stdoffset - SECSPERHOUR; 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 to 2037. */ sp->timecnt = 2 * (2037 - EPOCH_YEAR + 1); if (sp->timecnt > TZ_MAX_TIMES) return -1; 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; year <= 2037; ++year) { 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 */ } janfirst += year_lengths[isleap(year)] * SECSPERDAY; } } else { register long theirstdoffset; register long theirdstoffset; register long theiroffset; register int isdst; register int i; register int j; if (*name != '\0') return -1; if (load_result != 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; } } 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 (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) != 0) (void) tzparse(gmt, sp, TRUE);}/*** A non-static declaration of ast_tzsetwall in a system header file** may cause a warning about this upcoming static declaration...*/static#ifdef _THREAD_SAFEintast_tzsetwall_basic P((void))#elseintast_tzsetwall P((void))#endif{ struct state *cur_state = lclptr; /* Find the appropriate structure, if already parsed */ while (cur_state != NULL) { if (cur_state->name[0] == '\0') break; cur_state = cur_state->next; } if (cur_state != NULL) return 0; cur_state = malloc(sizeof(struct state)); if (cur_state == NULL) { return -1; } memset(cur_state,0,sizeof(struct state)); if (tzload((char *) NULL, cur_state) != 0)#ifdef DEBUG { fprintf(stderr, "ast_tzsetwall: calling gmtload()\n");#endif gmtload(cur_state);#ifdef DEBUG }#endif if (last_lclptr) last_lclptr->next = cur_state; else lclptr = cur_state; last_lclptr = cur_state; return 0;}#ifdef _THREAD_SAFEintast_tzsetwall P((void)){ ast_mutex_lock(&tzsetwall_mutex); ast_tzsetwall_basic(); ast_mutex_unlock(&tzsetwall_mutex); return 0;}#endif#ifdef _THREAD_SAFEstatic intast_tzset_basic P((const char *name))#elseintast_tzset P((const char *name))#endif{ struct state *cur_state = lclptr; /* Not set at all */ if (name == NULL) { return ast_tzsetwall(); } /* Find the appropriate structure, if already parsed */ while (cur_state != NULL) { if (!strcmp(cur_state->name,name)) break; cur_state = cur_state->next; } if (cur_state != NULL) return 0; cur_state = malloc(sizeof(struct state)); if (cur_state == NULL) { return -1; } memset(cur_state,0,sizeof(*cur_state)); /* Name is set, but set to the empty string == no adjustments */ if (name[0] == '\0') { /* ** User wants it fast rather than right. */ cur_state->leapcnt = 0; /* so, we're off a little */ cur_state->timecnt = 0; cur_state->ttis[0].tt_gmtoff = 0; cur_state->ttis[0].tt_abbrind = 0; (void) strncpy(cur_state->chars, gmt, sizeof(cur_state->chars) - 1); } else if (tzload(name, cur_state) != 0) { if (name[0] == ':') { (void) gmtload(cur_state); } else if (tzparse(name, cur_state, FALSE) != 0) { /* If not found, load localtime */ if (tzload("/etc/localtime", cur_state) != 0) /* Last ditch, get GMT */ (void) gmtload(cur_state); } } strncpy(cur_state->name, name, sizeof(cur_state->name) - 1); if (last_lclptr) last_lclptr->next = cur_state; else lclptr = cur_state; last_lclptr = cur_state; return 0;}#ifdef _THREAD_SAFEvoidast_tzset P((const char *name)){ ast_mutex_lock(&tzset_mutex); ast_tzset_basic(name); ast_mutex_unlock(&tzset_mutex);}#endif/*** 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 voidlocalsub(timep, offset, tmp, zone)const time_t * const timep;const long offset;struct tm * const tmp;const char * const zone;{ register struct state * sp; register const struct ttinfo * ttisp; register int i; const time_t t = *timep; sp = lclptr; /* Find the right zone record */ if (zone == NULL) sp = NULL; else while (sp != NULL) { if (!strcmp(sp->name,zone)) break; sp = sp->next; } if (sp == NULL) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -