📄 ctime.c
字号:
return; } }#endif /* defined ALL_STATE */ if (tzload((char *) NULL, lclptr) != 0) gmtload(lclptr); settzname();}/*** 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)const time_t * const timep;const long offset;struct tm * const tmp;{ register struct state * sp; register const struct ttinfo * ttisp; 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]; tmp->tm_zone = &sp->chars[ttisp->tt_abbrind];}struct tm *localtime(timep)const time_t * const timep;{ static struct tm tm; localsub(timep, 0L, &tm); return &tm;}/*** gmtsub is to gmtime as localsub is to localtime.*/static voidgmtsub(timep, offset, tmp)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); /* ** 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 */ }}struct tm *gmtime(timep)const time_t * const timep;{ static struct tm tm; gmtsub(timep, 0L, &tm); return &tm;}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 = 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; tmp->tm_gmtoff = offset;}/*** A la X3J11*/char *asctime(timeptr)register const struct tm * timeptr;{ static const char wday_name[DAYSPERWEEK][3] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; static const char mon_name[MONSPERYEAR][3] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; static char result[26]; (void) sprintf(result, "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %d\n", wday_name[timeptr->tm_wday], mon_name[timeptr->tm_mon], timeptr->tm_mday, timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec, TM_YEAR_BASE + timeptr->tm_year); return result;}char *ctime(timep)const time_t * const timep;{ return asctime(localtime(timep));}/*** 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 voidnormalize(tensptr, unitsptr, base)int * const tensptr;int * const unitsptr;const int base;{ if (*unitsptr >= base) { *tensptr += *unitsptr / base; *unitsptr %= base; } else if (*unitsptr < 0) { *tensptr -= 1 + (-(*unitsptr + 1)) / base; *unitsptr = base - 1 - (-(*unitsptr + 1)) % base; }}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)struct tm * const tmp;void (* const funcp)();const long offset;int * const 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); while (yourtm.tm_mday <= 0) { --yourtm.tm_year; yourtm.tm_mday += year_lengths[isleap(yourtm.tm_year + TM_YEAR_BASE)]; } while (yourtm.tm_mday > DAYSPERLYEAR) { yourtm.tm_mday -= year_lengths[isleap(yourtm.tm_year + TM_YEAR_BASE)]; ++yourtm.tm_year; } 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_ttime1(tmp, funcp, offset)struct tm * const tmp;void (* const funcp)();const long offset;{ 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); 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_tmktime(tmp)struct tm * const tmp;{ return time1(tmp, localsub, 0L);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -