13e12c5d1SDavid du Colombier #include <time.h>
23e12c5d1SDavid du Colombier
33e12c5d1SDavid du Colombier /*
43e12c5d1SDavid du Colombier * BUG: Doesn't do leap years in full glory,
53e12c5d1SDavid du Colombier * or calendar changes. In 2038 the sign bit
6*950da38cSDavid du Colombier * will be needed in time_t, but we say it
73e12c5d1SDavid du Colombier * can't be represented.
83e12c5d1SDavid du Colombier */
93e12c5d1SDavid du Colombier static int
dysize(int y)103e12c5d1SDavid du Colombier dysize(int y)
113e12c5d1SDavid du Colombier {
123e12c5d1SDavid du Colombier y += 1900; /* arg is a tm_year, number of years since 1900 */
133e12c5d1SDavid du Colombier if((y%4) == 0 && ((y%100) !=0 || (y%400) == 0))
143e12c5d1SDavid du Colombier return 366;
153e12c5d1SDavid du Colombier return 365;
163e12c5d1SDavid du Colombier }
173e12c5d1SDavid du Colombier
183e12c5d1SDavid du Colombier static int
dmsize(int m,int y)193e12c5d1SDavid du Colombier dmsize(int m, int y)
203e12c5d1SDavid du Colombier {
213e12c5d1SDavid du Colombier static char sizes[12] =
223e12c5d1SDavid du Colombier { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
233e12c5d1SDavid du Colombier
243e12c5d1SDavid du Colombier if(m == 1)
253e12c5d1SDavid du Colombier return (dysize(y)==366)? 29 : 28;
263e12c5d1SDavid du Colombier else
273e12c5d1SDavid du Colombier return sizes[m];
283e12c5d1SDavid du Colombier }
293e12c5d1SDavid du Colombier
303e12c5d1SDavid du Colombier /* Reduce *v to [0, mult), adding 1 to *next for every mult
313e12c5d1SDavid du Colombier * subtracted from *v, and return 1 if reduction worked (no overflow)
323e12c5d1SDavid du Colombier */
333e12c5d1SDavid du Colombier static int
reduce(int * v,int * next,int mult)343e12c5d1SDavid du Colombier reduce(int *v, int *next, int mult)
353e12c5d1SDavid du Colombier {
363e12c5d1SDavid du Colombier int oldnext;
373e12c5d1SDavid du Colombier
383e12c5d1SDavid du Colombier while(*v < 0){
393e12c5d1SDavid du Colombier *v += mult;
403e12c5d1SDavid du Colombier oldnext = *next;
41*950da38cSDavid du Colombier --*next;
423e12c5d1SDavid du Colombier if(!(*next < oldnext))
433e12c5d1SDavid du Colombier return 0;
443e12c5d1SDavid du Colombier }
453e12c5d1SDavid du Colombier while(*v >= mult){
463e12c5d1SDavid du Colombier *v -= mult;
473e12c5d1SDavid du Colombier oldnext = *next;
48*950da38cSDavid du Colombier ++*next;
493e12c5d1SDavid du Colombier if(!(*next > oldnext))
503e12c5d1SDavid du Colombier return 0;
513e12c5d1SDavid du Colombier }
523e12c5d1SDavid du Colombier return 1;
533e12c5d1SDavid du Colombier }
543e12c5d1SDavid du Colombier
553e12c5d1SDavid du Colombier static int
jan1(int yr)563e12c5d1SDavid du Colombier jan1(int yr)
573e12c5d1SDavid du Colombier {
583e12c5d1SDavid du Colombier int y, d;
593e12c5d1SDavid du Colombier
603e12c5d1SDavid du Colombier y = yr+1900;
613e12c5d1SDavid du Colombier d = (4+y+(y+3)/4-(y-1701)/100+(y-1601)/400+3)%7;
623e12c5d1SDavid du Colombier return d;
633e12c5d1SDavid du Colombier }
643e12c5d1SDavid du Colombier
653e12c5d1SDavid du Colombier time_t
mktime(struct tm * t)663e12c5d1SDavid du Colombier mktime(struct tm *t)
673e12c5d1SDavid du Colombier {
683e12c5d1SDavid du Colombier time_t a;
693e12c5d1SDavid du Colombier int i, d;
703e12c5d1SDavid du Colombier struct tm *ptm;
713e12c5d1SDavid du Colombier
723e12c5d1SDavid du Colombier if(!(reduce(&t->tm_sec, &t->tm_min, 60) &&
733e12c5d1SDavid du Colombier reduce(&t->tm_min, &t->tm_hour, 60) &&
743e12c5d1SDavid du Colombier reduce(&t->tm_hour, &t->tm_mday, 24) &&
753e12c5d1SDavid du Colombier reduce(&t->tm_mon, &t->tm_year, 12)))
76*950da38cSDavid du Colombier return -1;
773e12c5d1SDavid du Colombier while(t->tm_mday < 1){
783e12c5d1SDavid du Colombier if(--t->tm_mon == -1){
793e12c5d1SDavid du Colombier t->tm_mon = 11;
803e12c5d1SDavid du Colombier t->tm_year--;
813e12c5d1SDavid du Colombier }
823e12c5d1SDavid du Colombier t->tm_mday += dmsize(t->tm_mon, t->tm_year);
833e12c5d1SDavid du Colombier }
843e12c5d1SDavid du Colombier while(t->tm_mday > dmsize(t->tm_mon, t->tm_year)){
853e12c5d1SDavid du Colombier t->tm_mday -= dmsize(t->tm_mon, t->tm_year);
863e12c5d1SDavid du Colombier if(++t->tm_mon == 12){
873e12c5d1SDavid du Colombier t->tm_mon = 0;
883e12c5d1SDavid du Colombier t->tm_year++;
893e12c5d1SDavid du Colombier }
903e12c5d1SDavid du Colombier }
913e12c5d1SDavid du Colombier a = t->tm_sec + 60*t->tm_min + 3600*t->tm_hour;
923e12c5d1SDavid du Colombier t->tm_yday = t->tm_mday-1;
933e12c5d1SDavid du Colombier for(i=0; i<t->tm_mon; i++)
943e12c5d1SDavid du Colombier t->tm_yday += dmsize(i, t->tm_year);
953e12c5d1SDavid du Colombier a += t->tm_yday*86400L;
963e12c5d1SDavid du Colombier if(t->tm_year < 70){
973e12c5d1SDavid du Colombier for(i=t->tm_year; i<70; i++)
983e12c5d1SDavid du Colombier if((a -= dysize(i)*86400L) < 0)
99*950da38cSDavid du Colombier return -1;
1003e12c5d1SDavid du Colombier }else if(t->tm_year > 70){
1013e12c5d1SDavid du Colombier for(i=70; i<t->tm_year; i++)
1023e12c5d1SDavid du Colombier if((a += dysize(i)*86400L) < 0)
103*950da38cSDavid du Colombier return -1;
1043e12c5d1SDavid du Colombier }
1053e12c5d1SDavid du Colombier /*
1063e12c5d1SDavid du Colombier * Now a is number of seconds past Jan 1 1970.
1073e12c5d1SDavid du Colombier * Convert to GMT.
1083e12c5d1SDavid du Colombier */
1093e12c5d1SDavid du Colombier ptm = gmtime(&a);
1103e12c5d1SDavid du Colombier d = ptm->tm_hour;
1113e12c5d1SDavid du Colombier ptm = localtime(&a);
1123e12c5d1SDavid du Colombier d -= ptm->tm_hour;
1133e12c5d1SDavid du Colombier if(d < 0)
1143e12c5d1SDavid du Colombier d += 24;
1153e12c5d1SDavid du Colombier if(t->tm_isdst == 0 && ptm->tm_isdst)
1163e12c5d1SDavid du Colombier d--;
1173e12c5d1SDavid du Colombier if(t->tm_isdst > 0 && !ptm->tm_isdst)
1183e12c5d1SDavid du Colombier d++;
1193e12c5d1SDavid du Colombier a += d*3600;
1203e12c5d1SDavid du Colombier t->tm_wday = (jan1(t->tm_year)+t->tm_yday)%7;
1213e12c5d1SDavid du Colombier return a;
1223e12c5d1SDavid du Colombier }
123