📄 time.c
字号:
double difftime(time_t time1, time_t time0){#if (LONG_MAX >> DBL_MANT_DIG) == 0 /* time_t fits in the mantissa of a double. */ return ((double) time1) - time0;#elif ((LONG_MAX >> DBL_MANT_DIG) >> DBL_MANT_DIG) == 0 /* time_t can overflow the mantissa of a double. */ time_t t1, t0, d; d = ((time_t) 1) << DBL_MANT_DIG; t1 = time1 / d; time1 -= (t1 * d); t0 = time0 / d; time0 -= (t0*d); /* Since FLT_RADIX==2 and d is a power of 2, the only possible * rounding error in the expression below would occur from the * addition. */ return (((double) t1) - t0) * d + (((double) time1) - time0);#else#error difftime needs special implementation on your arch.#endif}#endif/**********************************************************************/#ifdef L_gmtimestruct tm *gmtime(const time_t *timer){ register struct tm *ptm = &__time_tm; _time_t2tm(timer, 0, ptm); /* Can return NULL... */ return ptm;}#endif/**********************************************************************/#ifdef L_gmtime_rstruct tm *gmtime_r(const time_t *__restrict timer, struct tm *__restrict result){ return _time_t2tm(timer, 0, result);}#endif/**********************************************************************/#ifdef L_localtimestruct tm *localtime(const time_t *timer){ register struct tm *ptm = &__time_tm; /* In this implementation, tzset() is called by localtime_r(). */ localtime_r(timer, ptm); /* Can return NULL... */ return ptm;}#endif/**********************************************************************/#ifdef L_localtime_rstruct tm *localtime_r(register const time_t *__restrict timer, register struct tm *__restrict result){ TZLOCK; tzset(); __time_localtime_tzi(timer, result, _time_tzinfo); TZUNLOCK; return result;}#endif/**********************************************************************/#ifdef L__time_localtime_tzi#ifdef __UCLIBC_HAS_TM_EXTENSIONS__struct ll_tzname_item;typedef struct ll_tzname_item { struct ll_tzname_item *next; char tzname[TZNAME_MAX+1];} ll_tzname_item_t;static ll_tzname_item_t ll_tzname[] = { { ll_tzname + 1, "UTC" }, /* Always 1st. */ { NULL, "???" } /* Always 2nd. (invalid or out-of-memory) */};static const char *lookup_tzname(const char *key){ ll_tzname_item_t *p; for (p=ll_tzname ; p ; p=p->next) { if (!strcmp(p->tzname, key)) { return p->tzname; } } /* Hmm... a new name. */ if (strnlen(key, TZNAME_MAX+1) < TZNAME_MAX+1) { /* Verify legal length */ if ((p = malloc(sizeof(ll_tzname_item_t))) != NULL) { /* Insert as 3rd item in the list. */ p->next = ll_tzname[1].next; ll_tzname[1].next = p; strcpy(p->tzname, key); return p->tzname; } } /* Either invalid or couldn't alloc. */ return ll_tzname[1].tzname;}#endif /* __UCLIBC_HAS_TM_EXTENSIONS__ */static const unsigned char day_cor[] = { /* non-leap */ 31, 31, 34, 34, 35, 35, 36, 36, 36, 37, 37, 38, 38/* 0, 0, 3, 3, 4, 4, 5, 5, 5, 6, 6, 7, 7 *//* 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 */};/* Note: timezone locking is done by localtime_r. */static int tm_isdst(register const struct tm *__restrict ptm, register rule_struct *r){ long sec; int i, isdst, isleap, day, day0, monlen, mday; int oday; /* Note: oday can be uninitialized. */ isdst = 0; if (r[1].tzname[0] != 0) { /* First, get the current seconds offset from the start of the year. * Fields of ptm are assumed to be in their normal ranges. */ sec = ptm->tm_sec + 60 * (ptm->tm_min + 60 * (long)(ptm->tm_hour + 24 * ptm->tm_yday)); /* Do some prep work. */ i = (ptm->tm_year % 400) + 1900; /* Make sure we don't overflow. */ isleap = __isleap(i); --i; day0 = (1 + i /* Normal years increment 1 wday. */ + (i/4) - (i/100) + (i/400) ) % 7; i = 0; do { day = r->day; /* Common for 'J' and # case. */ if (r->rule_type == 'J') { if (!isleap || (day < (31+29))) { --day; } } else if (r->rule_type == 'M') { /* Find 0-based day number for 1st of the month. */ day = 31*r->month - day_cor[r->month -1]; if (isleap && (day >= 59)) { ++day; } monlen = 31 + day_cor[r->month -1] - day_cor[r->month]; if (isleap && (r->month > 1)) { ++monlen; } /* Wweekday (0 is Sunday) of 1st of the month * is (day0 + day) % 7. */ if ((mday = r->day - ((day0 + day) % 7)) >= 0) { mday -= 7; /* Back up into prev month since r->week>0. */ } if ((mday += 7 * r->week) >= monlen) { mday -= 7; } /* So, 0-based day number is... */ day += mday; } if (i != 0) { /* Adjust sec since dst->std change time is in dst. */ sec += (r[-1].gmt_offset - r->gmt_offset); if (oday > day) { ++isdst; /* Year starts in dst. */ } } oday = day; /* Now convert day to seconds and add offset and compare. */ if (sec >= (day * 86400L) + r->dst_offset) { ++isdst; } ++r; } while (++i < 2); } return (isdst & 1);}struct tm *__time_localtime_tzi(register const time_t *__restrict timer, register struct tm *__restrict result, rule_struct *tzi){ time_t x[1]; long offset; int days, dst; dst = 0; do { days = -7; offset = 604800L - tzi[dst].gmt_offset; if (*timer > (LONG_MAX - 604800L)) { days = -days; offset = -offset; } *x = *timer + offset; _time_t2tm(x, days, result); result->tm_isdst = dst;#ifdef __UCLIBC_HAS_TM_EXTENSIONS__ result->tm_gmtoff = - tzi[dst].gmt_offset; result->tm_zone = lookup_tzname(tzi[dst].tzname);#endif /* __UCLIBC_HAS_TM_EXTENSIONS__ */ } while ((++dst < 2) && ((result->tm_isdst = tm_isdst(result, tzi)) != 0)); return result;}#endif/**********************************************************************/#ifdef L_mktime/* Another name for `mktime'. *//* time_t timelocal(struct tm *tp) */weak_alias(mktime,timelocal);time_t mktime(struct tm *timeptr){ return _time_mktime(timeptr, 1);}#endif/**********************************************************************/#ifdef L_timegm/* Like `mktime' but timeptr represents Universal Time, not local time. */time_t timegm(struct tm *timeptr){ rule_struct gmt_tzinfo[2]; memset(gmt_tzinfo, 0, sizeof(gmt_tzinfo)); strcpy(gmt_tzinfo[0].tzname, "GMT"); /* Match glibc behavior here. */ return _time_mktime_tzi(timeptr, 1, gmt_tzinfo);}#endif/**********************************************************************/#if defined(L_strftime) || defined(L_strftime_l)#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE)size_t strftime(char *__restrict s, size_t maxsize, const char *__restrict format, const struct tm *__restrict timeptr){ return __strftime_l(s, maxsize, format, timeptr, __UCLIBC_CURLOCALE);}#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */#define NO_E_MOD 0x80#define NO_O_MOD 0x40#define ILLEGAL_SPEC 0x3f#define INT_SPEC 0x00 /* must be 0x00!! */#define STRING_SPEC 0x10 /* must be 0x10!! */#define CALC_SPEC 0x20#define STACKED_SPEC 0x30#define MASK_SPEC 0x30/* Compatibility: * * No alternate digit (%O?) handling. Always uses 0-9. * Alternate locale format (%E?) handling is broken for nontrivial ERAs. * glibc's %P is currently faked by %p. This means it doesn't do lower case. * glibc's %k, %l, and %s are handled. * glibc apparently allows (and ignores) extraneous 'E' and 'O' modifiers, * while they are flagged as illegal conversions here. *//* Warning: Assumes ASCII values! (as do lots of other things in the lib...) */static const unsigned char spec[] = { /* A */ 0x03 | STRING_SPEC | NO_E_MOD | NO_O_MOD, /* B */ 0x04 | STRING_SPEC | NO_E_MOD | NO_O_MOD, /* C */ 0x0a | INT_SPEC | NO_O_MOD, /* D */ 0x02 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, /* E */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, /* F */ 0x03 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, /* G */ 0x03 | CALC_SPEC | NO_E_MOD | NO_O_MOD, /* H */ 0x0b | INT_SPEC | NO_E_MOD, /* I */ 0x0c | INT_SPEC | NO_E_MOD, /* J */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, /* K */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, /* L */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, /* M */ 0x0d | INT_SPEC | NO_E_MOD, /* N */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, /* O */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, /* P */ 0x05 | STRING_SPEC | NO_E_MOD | NO_O_MOD, /* glibc ; use %p */ /* Q */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, /* R */ 0x04 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, /* S */ 0x0e | INT_SPEC | NO_E_MOD, /* T */ 0x05 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, /* U */ 0x04 | CALC_SPEC | NO_E_MOD, /* V */ 0x05 | CALC_SPEC | NO_E_MOD, /* W */ 0x06 | CALC_SPEC | NO_E_MOD, /* X */ 0x0a | STACKED_SPEC | NO_O_MOD, /* Y */ 0x0f | INT_SPEC | NO_O_MOD, /* Z */ 0x01 | CALC_SPEC | NO_E_MOD | NO_O_MOD, '?', /* 26 */ '?', /* 27 */ '?', /* 28 */ '?', /* 29 */ 0, /* 30 */ 0, /* 31 */ /* a */ 0x00 | STRING_SPEC | NO_E_MOD | NO_O_MOD, /* b */ 0x01 | STRING_SPEC | NO_E_MOD | NO_O_MOD, /* c */ 0x08 | STACKED_SPEC | NO_O_MOD, /* d */ 0x00 | INT_SPEC | NO_E_MOD, /* e */ 0x01 | INT_SPEC | NO_E_MOD, /* f */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, /* g */ 0x02 | CALC_SPEC | NO_E_MOD | NO_O_MOD, /* h */ 0x01 | STRING_SPEC | NO_E_MOD | NO_O_MOD, /* same as b */ /* i */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, /* j */ 0x08 | INT_SPEC | NO_E_MOD | NO_O_MOD, /* k */ 0x03 | INT_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ /* l */ 0x04 | INT_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ /* m */ 0x05 | INT_SPEC | NO_E_MOD, /* n */ 0x00 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, /* o */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, /* p */ 0x02 | STRING_SPEC | NO_E_MOD | NO_O_MOD, /* q */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, /* r */ 0x0b | STACKED_SPEC | NO_E_MOD | NO_O_MOD, /* s */ 0x07 | CALC_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ /* t */ 0x01 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, /* u */ 0x07 | INT_SPEC | NO_E_MOD, /* v */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, /* w */ 0x02 | INT_SPEC | NO_E_MOD, /* x */ 0x09 | STACKED_SPEC | NO_O_MOD, /* y */ 0x09 | INT_SPEC, /* z */ 0x00 | CALC_SPEC | NO_E_MOD | NO_O_MOD, /* WARNING!!! These are dependent on the layout of struct tm!!! */#define FIELD_MAX (26+6+26) 60 /* 61? */, 59, 23, 31, 11, 0 /* 9999 */, 6, 0 /* 365 */,#define TP_OFFSETS (FIELD_MAX+8) 3, /* d */ 3, /* e */ 6, /* w */ 2, /* k */ 2, /* l */ 4, /* m */ 0, /* CURRENTLY UNUSED */ /* NOTE: u,j,y order must be preserved as 6,7,5 seq is used in the code! */#define CALC_OFFSETS (TP_OFFSETS + 7) 6, /* u */ 7, /* j */ 5, /* y */ 5, /* C */ 2, /* H */ 2, /* I */ 1, /* M */ 0, /* S */ 5, /* Y */ 6, /* a */ 4, /* b, h */ 2, /* p */ 6, /* A */ 4, /* B */ 2, /* P */#define TP_CODES (TP_OFFSETS + 16 + 6) 2 | 16, /* d */ 2, /* e */ 0 | 16, /* w */ 2, /* k */ 2 | 32 | 0, /* l */ 2 | 16 | 1, /* m */ 0, /* CURRENTLY UNUSED */ 0 | 16 | 8 , /* u */ 4 | 16 | 1, /* j */ 2 | 128 | 32 | 16 , /* y */ 2 | 128 | 64 | 32 | 16 , /* C */ 2 | 16, /* H */ 2 | 32 | 16 | 0, /* I */ 2 | 16, /* M */ 2 | 16, /* S */ 6 | 16, /* Y */ 2, /* a */ 2, /* b, h */ 2 | 64, /* p */ 2, /* A */ 2, /* B */ 2 | 64, /* P */#define STRINGS_NL_ITEM_START (TP_CODES + 16 + 6) _NL_ITEM_INDEX(ABDAY_1), /* a */ _NL_ITEM_INDEX(ABMON_1), /* b, h */ _NL_ITEM_INDEX(AM_STR), /* p */ _NL_ITEM_INDEX(DAY_1), /* A */ _NL_ITEM_INDEX(MON_1), /* B */ _NL_ITEM_INDEX(AM_STR), /* P -- wrong! need lower case */#define STACKED_STRINGS_START (STRINGS_NL_ITEM_START+6) 6, 7, 8, 16, 24, 29, /* 6 - offsets from offset-count to strings */ '\n', 0, /* 2 */ '\t', 0, /* 2 */ '%', 'm', '/', '%', 'd', '/', '%', 'y', 0, /* 9 - %D */ '%', 'Y', '-', '%', 'm', '-', '%', 'd', 0, /* 9 - %F (glibc extension) */ '%', 'H', ':', '%', 'M', 0, /* 6 - %R*/ '%', 'H', ':', '%', 'M', ':', '%', 'S', 0, /* 9 - %T */#define STACKED_STRINGS_NL_ITEM_START (STACKED_STRINGS_START + 43) _NL_ITEM_INDEX(D_T_FMT), /* c */ _NL_ITEM_INDEX(D_FMT), /* x */ _NL_ITEM_INDEX(T_FMT), /* X */ _NL_ITEM_INDEX(T_FMT_AMPM), /* r */#ifdef ENABLE_ERA_CODE _NL_ITEM_INDEX(ERA_D_T_FMT), /* Ec */ _NL_ITEM_INDEX(ERA_D_FMT), /* Ex */ _NL_ITEM_INDEX(ERA_T_FMT), /* EX */#endif};static int load_field(int k, const struct tm *__restrict timeptr){ int r; int r_max; r = ((int *) timeptr)[k]; r_max = spec[FIELD_MAX + k]; if (k == 7) { r_max = 365; } else if (k == 5) { r += 1900; r_max = 9999; } if ((((unsigned int) r) > r_max) || ((k == 3) && !r)) { r = -1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -