📄 localtime.c
字号:
ast_tzsetwall(); sp = lclptr; /* Find the default zone record */ while (sp != NULL) { if (sp->name[0] == '\0') break; sp = sp->next; } } /* Last ditch effort, use GMT */ if (sp == NULL) { gmtsub(timep, offset, tmp, zone); return; } if (sp->timecnt == 0 || t < sp->ats[0]) { i = 0; while (sp->ttis[i].tt_isdst) if (++i >= sp->typecnt) { i = 0; break; } } else { for (i = 1; i < sp->timecnt; ++i) if (t < sp->ats[i]) break; i = sp->types[i - 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); */ timesub(&t, ttisp->tt_gmtoff, sp, tmp); tmp->tm_isdst = ttisp->tt_isdst; tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind];#ifdef TM_ZONE tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];#endif /* defined TM_ZONE */}struct tm *ast_localtime(timep, p_tm, zone)const time_t * const timep;struct tm *p_tm;const char * const zone;{#ifdef _THREAD_SAFE ast_mutex_lock(&lcl_mutex);#endif ast_tzset(ast_strlen_zero(zone) ? "/etc/localtime" : zone); localsub(timep, 0L, p_tm, zone);#ifdef _THREAD_SAFE ast_mutex_unlock(&lcl_mutex);#endif return(p_tm);}/*** gmtsub is to gmtime as localsub is to localtime.*/static voidgmtsub(timep, offset, tmp, zone)const time_t * const timep;const long offset;struct tm * const tmp;const char * const zone;{#ifdef _THREAD_SAFE ast_mutex_lock(&gmt_mutex);#endif if (!gmt_is_set) { gmt_is_set = TRUE; gmtptr = (struct state *) malloc(sizeof *gmtptr); if (gmtptr != NULL) gmtload(gmtptr); } ast_mutex_unlock(&gmt_mutex); timesub(timep, offset, gmtptr, tmp);#ifdef TM_ZONE /* ** Could get fancy here and deliver something such as ** "GMT+xxxx" or "GMT-xxxx" if offset is non-zero, ** but this is no time for a treasure hunt. */ if (offset != 0) tmp->TM_ZONE = wildabbr; else { if (gmtptr == NULL) tmp->TM_ZONE = gmt; else tmp->TM_ZONE = gmtptr->chars; }#endif /* defined TM_ZONE */}static voidtimesub(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 long days; register long rem; register int y; register int yleap; register const int * ip; register long corr; register int hit; register int i; corr = 0; hit = 0; i = (sp == NULL) ? 0 : sp->leapcnt; 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; } } days = *timep / SECSPERDAY; rem = *timep % SECSPERDAY;#ifdef mc68k if (*timep == 0x80000000) { /* ** A 3B1 muffs the division on the most negative number. */ days = -24855; rem = -11648; }#endif /* defined mc68k */ rem += (offset - corr); while (rem < 0) { rem += SECSPERDAY; --days; } while (rem >= SECSPERDAY) { rem -= SECSPERDAY; ++days; } tmp->tm_hour = (int) (rem / SECSPERHOUR); rem = rem % SECSPERHOUR; tmp->tm_min = (int) (rem / SECSPERMIN); /* ** A positive leap second requires a special ** representation. This uses "... ??:59:60" et seq. */ tmp->tm_sec = (int) (rem % SECSPERMIN) + hit; tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK); if (tmp->tm_wday < 0) tmp->tm_wday += DAYSPERWEEK; y = EPOCH_YEAR;#define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400) while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) { register int newy; newy = y + days / DAYSPERNYEAR; if (days < 0) --newy; days -= (newy - y) * DAYSPERNYEAR + LEAPS_THRU_END_OF(newy - 1) - LEAPS_THRU_END_OF(y - 1); y = newy; } tmp->tm_year = y - TM_YEAR_BASE; tmp->tm_yday = (int) days; ip = mon_lengths[yleap]; for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon)) days = days - (long) ip[tmp->tm_mon]; tmp->tm_mday = (int) (days + 1); tmp->tm_isdst = 0;#ifdef TM_GMTOFF tmp->TM_GMTOFF = offset;#endif /* defined TM_GMTOFF */}char *ast_ctime(timep)const time_t * const timep;{/*** Section 4.12.3.2 of X3.159-1989 requires that** The ctime funciton converts the calendar time pointed to by timer** to local time in the form of a string. It is equivalent to** asctime(localtime(timer))*/ return asctime(localtime(timep));}char *ast_ctime_r(timep, buf)const time_t * const timep;char *buf;{ struct tm tm; return asctime_r(localtime_r(timep, &tm), buf);}/*** Adapted from code provided by Robert Elz, who writes:** The "best" way to do mktime I think is based on an idea of Bob** Kridle's (so its said...) from a long time ago.** [kridle@xinet.com as of 1996-01-16.]** It does a binary search of the time_t space. Since time_t's are** just 32 bits, its a max of 32 iterations (even at 64 bits it** would still be very reasonable).*/#ifndef WRONG#define WRONG (-1)#endif /* !defined WRONG *//*** Simplified normalize logic courtesy Paul Eggert (eggert@twinsun.com).*/static intincrement_overflow(number, delta)int * number;int delta;{ int number0; number0 = *number; *number += delta; return (*number < number0) != (delta < 0);}static intnormalize_overflow(tensptr, unitsptr, base)int * const tensptr;int * const unitsptr;const int base;{ register int tensdelta; tensdelta = (*unitsptr >= 0) ? (*unitsptr / base) : (-1 - (-1 - *unitsptr) / base); *unitsptr -= tensdelta * base; return increment_overflow(tensptr, tensdelta);}static inttmcomp(atmp, btmp)register const struct tm * const atmp;register const struct tm * const btmp;{ register int result; if ((result = (atmp->tm_year - btmp->tm_year)) == 0 && (result = (atmp->tm_mon - btmp->tm_mon)) == 0 && (result = (atmp->tm_mday - btmp->tm_mday)) == 0 && (result = (atmp->tm_hour - btmp->tm_hour)) == 0 && (result = (atmp->tm_min - btmp->tm_min)) == 0) result = atmp->tm_sec - btmp->tm_sec; return result;}static time_ttime2(tmp, funcp, offset, okayp, zone)struct tm * const tmp;void (* const funcp) P((const time_t*, long, struct tm*, const char*));const long offset;int * const okayp;const char * const zone;{ register const struct state * sp; register int dir; register int bits; register int i, j ; register int saved_seconds; time_t newt; time_t t; struct tm yourtm, mytm; *okayp = FALSE; yourtm = *tmp; if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR)) return WRONG; if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY)) return WRONG; if (normalize_overflow(&yourtm.tm_year, &yourtm.tm_mon, MONSPERYEAR)) return WRONG; /* ** Turn yourtm.tm_year into an actual year number for now. ** It is converted back to an offset from TM_YEAR_BASE later. */ if (increment_overflow(&yourtm.tm_year, TM_YEAR_BASE)) return WRONG; while (yourtm.tm_mday <= 0) { if (increment_overflow(&yourtm.tm_year, -1)) return WRONG; i = yourtm.tm_year + (1 < yourtm.tm_mon); yourtm.tm_mday += year_lengths[isleap(i)]; } while (yourtm.tm_mday > DAYSPERLYEAR) { i = yourtm.tm_year + (1 < yourtm.tm_mon); yourtm.tm_mday -= year_lengths[isleap(i)]; if (increment_overflow(&yourtm.tm_year, 1)) return WRONG; } for ( ; ; ) { i = mon_lengths[isleap(yourtm.tm_year)][yourtm.tm_mon]; if (yourtm.tm_mday <= i) break; yourtm.tm_mday -= i; if (++yourtm.tm_mon >= MONSPERYEAR) { yourtm.tm_mon = 0; if (increment_overflow(&yourtm.tm_year, 1)) return WRONG; } } if (increment_overflow(&yourtm.tm_year, -TM_YEAR_BASE)) return WRONG; if (yourtm.tm_year + TM_YEAR_BASE < EPOCH_YEAR) { /* ** We can't set tm_sec to 0, because that might push the ** time below the minimum representable time. ** Set tm_sec to 59 instead. ** This assumes that the minimum representable time is ** not in the same minute that a leap second was deleted from, ** which is a safer assumption than using 58 would be. */ if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN)) return WRONG; saved_seconds = yourtm.tm_sec; yourtm.tm_sec = SECSPERMIN - 1; } else { saved_seconds = yourtm.tm_sec; yourtm.tm_sec = 0; } /* ** Divide the search space in half ** (this works whether time_t is signed or unsigned). */ bits = TYPE_BIT(time_t) - 1; /* ** If time_t is signed, then 0 is just above the median, ** assuming two's complement arithmetic. ** If time_t is unsigned, then (1 << bits) is just above the median. */ t = TYPE_SIGNED(time_t) ? 0 : (((time_t) 1) << bits); for ( ; ; ) { (*funcp)(&t, offset, &mytm, zone); dir = tmcomp(&mytm, &yourtm); if (dir != 0) { if (bits-- < 0) return WRONG; if (bits < 0) --t; /* may be needed if new t is minimal */ else if (dir > 0) t -= ((time_t) 1) << bits; else t += ((time_t) 1) << bits; continue; } if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst) break; /* ** Right time, wrong type. ** Hunt for right time, right type. ** It's okay to guess wrong since the guess ** gets checked. */ /* ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's. */ sp = (const struct state *) (((void *) funcp == (void *) localsub) ? lclptr : gmtptr); if (sp == NULL) return WRONG; for (i = sp->typecnt - 1; i >= 0; --i) { if (sp->ttis[i].tt_isdst != yourtm.tm_isdst) continue; for (j = sp->typecnt - 1; j >= 0; --j) { if (sp->ttis[j].tt_isdst == yourtm.tm_isdst) continue; newt = t + sp->ttis[j].tt_gmtoff - sp->ttis[i].tt_gmtoff; (*funcp)(&newt, offset, &mytm, zone); if (tmcomp(&mytm, &yourtm) != 0) continue; if (mytm.tm_isdst != yourtm.tm_isdst) continue; /* ** We have a match. */ t = newt; goto label; } } return WRONG; }label: newt = t + saved_seconds; if ((newt < t) != (saved_seconds < 0)) return WRONG; t = newt; (*funcp)(&t, offset, tmp, zone); *okayp = TRUE; return t;}static time_ttime1(tmp, funcp, offset, zone)struct tm * const tmp;void (* const funcp) P((const time_t *, long, struct tm *, const char*));const long offset;const char * const zone;{ register time_t t; register const struct state * sp; register int samei, otheri; int okay; if (tmp->tm_isdst > 1) tmp->tm_isdst = 1; t = time2(tmp, funcp, offset, &okay, zone);#ifdef PCTS /* ** PCTS code courtesy Grant Sullivan (grant@osf.org). */ if (okay) return t; if (tmp->tm_isdst < 0) tmp->tm_isdst = 0; /* reset to std and try again */#endif /* defined PCTS */#ifndef PCTS if (okay || tmp->tm_isdst < 0) return t;#endif /* !defined PCTS */ /* ** We're supposed to assume that somebody took a time of one type ** and did some math on it that yielded a "struct tm" that's bad. ** We try to divine the type they started from and adjust to the ** type they need. */ /* ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's. */ sp = (const struct state *) (((void *) funcp == (void *) localsub) ? lclptr : gmtptr); if (sp == NULL) return WRONG; for (samei = sp->typecnt - 1; samei >= 0; --samei) { if (sp->ttis[samei].tt_isdst != tmp->tm_isdst) continue; for (otheri = sp->typecnt - 1; otheri >= 0; --otheri) { if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst) continue; tmp->tm_sec += sp->ttis[otheri].tt_gmtoff - sp->ttis[samei].tt_gmtoff; tmp->tm_isdst = !tmp->tm_isdst; t = time2(tmp, funcp, offset, &okay, zone); if (okay) return t; tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff - sp->ttis[samei].tt_gmtoff; tmp->tm_isdst = !tmp->tm_isdst; } } return WRONG;}time_tast_mktime(tmp,zone)struct tm * const tmp;const char * const zone;{ time_t mktime_return_value;#ifdef _THREAD_SAFE ast_mutex_lock(&lcl_mutex);#endif ast_tzset(!ast_strlen_zero(zone) ? zone : "/etc/localtime"); mktime_return_value = time1(tmp, localsub, 0L, !ast_strlen_zero(zone) ? zone : "/etc/localtime");#ifdef _THREAD_SAFE ast_mutex_unlock(&lcl_mutex);#endif return(mktime_return_value);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -