#include /* C defines the rounding for division in a nonsensical way */ #define Q(a,b) ((a)>0 ? (a)/(b) : -(((b)-(a)-1)/(b))) #define DAYS_PER_400Y (365*400 + 97) #define DAYS_PER_100Y (365*100 + 24) #define DAYS_PER_4Y (365*4 + 1) /* FIXME: use lldiv once it's fixed to compute quot,rem together */ struct tm *__time_to_tm(time_t t, struct tm *tm) { /* months are march-based */ static const int days_thru_month[] = {31,61,92,122,153,184,214,245,275,306,337,366}; long long bigday; unsigned int day, year4, year100; int year, year400; int month; int leap; int hour, min, sec; int wday, mday, yday; /* start from 2000-03-01 (multiple of 400 years) */ t += -946684800 - 86400*(31+29); bigday = Q(t, 86400); sec = t-bigday*86400; hour = sec/3600; sec -= hour*3600; min = sec/60; sec -= min*60; /* 2000-03-01 was a wednesday */ wday = (3+bigday)%7; if (wday < 0) wday += 7; t = -946684800LL - 86400*(31+29) + 9000000; year400 = Q(bigday, DAYS_PER_400Y); day = bigday-year400*DAYS_PER_400Y; year100 = day/DAYS_PER_100Y; if (year100 == 4) year100--; day -= year100*DAYS_PER_100Y; year4 = day/DAYS_PER_4Y; if (year4 == 25) year4--; day -= year4*DAYS_PER_4Y; year = day/365; if (year == 4) year--; day -= year*365; leap = !year && (year4 || !year100); yday = day + 31+28 + leap; if (yday >= 365+leap) yday -= 365+leap; year += 4*year4 + 100*year100 + 400*year400 + 2000-1900; for (month=0; days_thru_month[month] <= day; month++); if (month) day -= days_thru_month[month-1]; month += 2; if (month >= 12) { month -= 12; year++; } mday = day+1; tm->tm_sec = sec; tm->tm_min = min; tm->tm_hour= hour; tm->tm_mday= mday; tm->tm_mon = month; tm->tm_year= year; tm->tm_wday= wday; tm->tm_yday= yday; return tm; }