1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
|
/* metaprogramming */
#if !defined INCLUDED_gmtime_h_
#define INCLUDED_gmtime_h_
#include <stdint.h>
/* UTC has a constant day length */
#define UTC_SECS_PER_DAY (86400)
static void
ffff_gmtime(struct tm *tm, const time_t t)
{
static uint16_t __mon_yday[] = {
/* this is \sum ml,
* first element is a bit set of leap days to add */
0xfff8, 0,
31, 59, 90, 120, 151, 181,
212, 243, 273, 304, 334, 365
};
register int days;
register unsigned int yy;
const uint16_t *ip;
#if defined FFFF_GMTIME_SUBDAY
int secs;
#endif /* FFFF_GMTIME_SUBDAY */
/* just go to day computation */
days = (int)(t / UTC_SECS_PER_DAY);
#if defined FFFF_GMTIME_SUBDAY
secs = (int)(t % UTC_SECS_PER_DAY);
#endif /* FFFF_GMTIME_SUBDAY */
/* week day computation, that one's easy, 1 jan '70 was Thu */
tm->tm_wday = (days + 4) % GREG_DAYS_P_WEEK;
/* gotta do the date now */
yy = 1970;
/* stolen from libc */
#define DIV(a, b) ((a) / (b))
/* we only care about 1901 to 2099 and there are no bullshit leap years */
#define LEAPS_TILL(y) (DIV(y, 4))
while (days < 0 || days >= (!__leapp(yy) ? 365 : 366)) {
/* Guess a corrected year, assuming 365 days per year. */
register unsigned int yg = yy + days / 365 - (days % 365 < 0);
/* Adjust DAYS and Y to match the guessed year. */
days -= (yg - yy) * 365 +
LEAPS_TILL(yg - 1) - LEAPS_TILL(yy - 1);
yy = yg;
}
/* set the year */
tm->tm_year = (int)yy;
ip = __mon_yday;
/* unrolled */
yy = 13;
if (days < ip[--yy] &&
days < ip[--yy] &&
days < ip[--yy] &&
days < ip[--yy] &&
days < ip[--yy] &&
days < ip[--yy] &&
days < ip[--yy] &&
days < ip[--yy] &&
days < ip[--yy] &&
days < ip[--yy] &&
days < ip[--yy]) {
yy = 1;
}
/* set the rest of the tm structure */
tm->tm_mday = days - ip[yy] + 1;
tm->tm_yday = days;
tm->tm_mon = (int)yy;
/* fix up leap years */
if (UNLIKELY(__leapp(tm->tm_year))) {
if ((ip[0] >> (yy)) & 1) {
if (UNLIKELY(tm->tm_yday == 59)) {
tm->tm_mon = 2;
tm->tm_mday = 29;
} else if (UNLIKELY(tm->tm_yday == ip[yy])) {
tm->tm_mday = tm->tm_yday - ip[--tm->tm_mon];
} else {
tm->tm_mday--;
}
}
}
#if defined FFFF_GMTIME_SUBDAY
tm->tm_sec = secs % 60U;
secs /= 60U;
tm->tm_min = secs % 60U;
secs /= 60U;
tm->tm_hour = secs;
#endif /* FFFF_GMTIME_SUBDAY */
return;
}
#endif /* INCLUDED_gmtime_h_ */
|