📄 localtime.c
字号:
register int i; const time_t t = *timep; if (!lcl_is_set) __tzset(); sp = lclptr;#ifdef ALL_STATE if (sp == NULL) { __gmtsub(timep, offset, tmp); return; }#endif /* defined ALL_STATE */ 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] = (char *) &sp->chars[ttisp->tt_abbrind];#ifdef TM_ZONE tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];#endif /* defined TM_ZONE */}struct tm *localtime(const time_t *timer){ static struct tm tm; __localsub(timer, 0L, &tm); return &tm;}/*** __gmtsub is to gmtime as __localsub is to localtime.*/static void __gmtsub(const time_t * const timep, const long offset, struct tm * const tmp){ 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); } __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 {#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 */}struct tm *gmtime(const time_t *timer){ static struct tm tm; __gmtsub(timer, 0L, &tm); return &tm;}#ifdef STD_INSPIREDstruct tm *__offtime (const time_t * const timep, const long offset){ static struct tm tm; __gmtsub(timep, offset, &tm); return &tm;}#endif /* defined STD_INSPIRED */static void __timesub( const time_t *timep, long offset, const struct state *sp, struct tm *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 = FALSE;#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); 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 /* 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); tmp->tm_sec = (int) (rem % SECSPERMIN); if (hit) /* ** A positive leap second requires a special ** representation. This uses "... ??:59:60". */ ++(tmp->tm_sec); tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK); if (tmp->tm_wday < 0) tmp->tm_wday += DAYSPERWEEK; y = EPOCH_YEAR; if (days >= 0) for ( ; ; ) { yleap = isleap(y); if (days < (long) year_lengths[yleap]) break; ++y; days = days - (long) year_lengths[yleap]; } else do { --y; yleap = isleap(y); days = days + (long) year_lengths[yleap]; } while (days < 0); 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 *ctime(const time_t *timer){ return asctime(localtime(timer));}/*** 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. (mtxinu!kridle now).** 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 */static void __normalize( int *tensptr, int *unitsptr, int base ){ if (*unitsptr >= base) { *tensptr += *unitsptr / base; *unitsptr %= base; } else if (*unitsptr < 0) { --*tensptr; *unitsptr += base; if (*unitsptr < 0) { *tensptr -= 1 + (-*unitsptr) / base; *unitsptr = base - (-*unitsptr) % base; } }}static int __tmcomp( const struct tm *atmp, const struct tm *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_t __time2( struct tm *tmp, void (*funcp)(), long offset, int *okayp ){ 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 (yourtm.tm_sec >= SECSPERMIN + 2 || yourtm.tm_sec < 0) __normalize(&yourtm.tm_min, &yourtm.tm_sec, SECSPERMIN); __normalize(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR); __normalize(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY); __normalize(&yourtm.tm_year, &yourtm.tm_mon, MONSPERYEAR); /* * Sanity check the range of the year argument, not very precisely. * This does not necessarily return WRONG for some inputs near the * EPOCH_BEGIN or EPOCH_END boundaries, but at least it gets rid * of totally bogus input values. */ if (yourtm.tm_year < EPOCH_BEGIN - TM_YEAR_BASE || yourtm.tm_year > EPOCH_END - TM_YEAR_BASE) return (time_t)WRONG; while (yourtm.tm_mday <= 0) { --yourtm.tm_year; yourtm.tm_mday += year_lengths[isleap(yourtm.tm_year + TM_YEAR_BASE)]; } for ( ; ; ) { i = mon_lengths[isleap(yourtm.tm_year + TM_YEAR_BASE)][yourtm.tm_mon]; if (yourtm.tm_mday <= i) break; yourtm.tm_mday -= i; if (++yourtm.tm_mon >= MONSPERYEAR) { yourtm.tm_mon = 0; ++yourtm.tm_year; } } saved_seconds = yourtm.tm_sec; yourtm.tm_sec = 0; /* ** Calculate the number of magnitude bits in a time_t ** (this works regardless of whether time_t is ** signed or unsigned, though lint complains if unsigned). */ for (bits = 0, t = 1; t > 0; ++bits, t <<= 1) ; /* ** If time_t is signed, then 0 is the median value, ** if time_t is unsigned, then 1 << bits is median. */ t = (t < 0) ? 0 : ((time_t) 1 << bits); for ( ; ; ) { (*funcp)(&t, offset, &mytm); dir = __tmcomp(&mytm, &yourtm); if (dir != 0) { if (bits-- < 0) return WRONG; if (bits < 0) --t; 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. */ sp = (const struct state *) ((funcp == __localsub) ? lclptr : gmtptr);#ifdef ALL_STATE if (sp == NULL) return WRONG;#endif /* defined ALL_STATE */ for (i = 0; i < sp->typecnt; ++i) { if (sp->ttis[i].tt_isdst != yourtm.tm_isdst) continue; for (j = 0; j < sp->typecnt; ++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); 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: t += saved_seconds; (*funcp)(&t, offset, tmp); *okayp = TRUE; return t;}static time_t __time1( struct tm *tmp, void (*funcp)(), long offset){ register time_t t; register const struct state * sp; register int samei, otheri; int okay; if (tmp->tm_isdst > 1) return WRONG; t = __time2(tmp, funcp, offset, &okay); if (okay || tmp->tm_isdst < 0) return t; /* ** 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. */ sp = (const struct state *) ((funcp == __localsub) ? lclptr : gmtptr);#ifdef ALL_STATE if (sp == NULL) return WRONG;#endif /* defined ALL_STATE */ for (samei = 0; samei < sp->typecnt; ++samei) { if (sp->ttis[samei].tt_isdst != tmp->tm_isdst) continue; for (otheri = 0; otheri < sp->typecnt; ++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); 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_t mktime( struct tm *timeptr ){ return __time1(timeptr, __localsub, 0L);}#ifdef STD_INSPIREDtime_t __timelocal( const struct tm *tmp ){ return mktime(tmp);}time_t __timegm( struct tm *tmp ){ return __time1(tmp, __gmtsub, 0L);}time_t __timeoff(struct tm *tmp, long offset){ return __time1(tmp, __gmtsub, offset);}#endif /* defined STD_INSPIRED *//* end of lib-src/ansi/time/localtime.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -