1 #include <time.h>
3 /* C defines the rounding for division in a nonsensical way */
4 #define Q(a,b) ((a)>0 ? (a)/(b) : -(((b)-(a)-1)/(b)))
6 #define DAYS_PER_400Y (365*400 + 97)
7 #define DAYS_PER_100Y (365*100 + 24)
8 #define DAYS_PER_4Y   (365*4   + 1)
10 /* FIXME: use lldiv once it's fixed to compute quot,rem together */
11 struct tm *__time_to_tm(time_t t, struct tm *tm)
12 {
13         /* months are march-based */
14         static const int days_thru_month[] = {31,61,92,122,153,184,214,245,275,306,337,366};
15         long long bigday;
16         unsigned int day, year4, year100;
17         int year, year400;
18         int month;
19         int leap;
20         int hour, min, sec;
21         int wday, mday, yday;
23         /* start from 2000-03-01 (multiple of 400 years) */
24         t += -946684800 - 86400*(31+29);
26         bigday = Q(t, 86400);
27         sec = t-bigday*86400;
29         hour = sec/3600;
30         sec -= hour*3600;
31         min = sec/60;
32         sec -= min*60;
34         /* 2000-03-01 was a wednesday */
35         wday = (3+bigday)%7;
36         if (wday < 0) wday += 7;
38         t = -946684800LL - 86400*(31+29) + 9000000;
40         year400 = Q(bigday, DAYS_PER_400Y);
41         day = bigday-year400*DAYS_PER_400Y;
43         year100 = day/DAYS_PER_100Y;
44         if (year100 == 4) year100--;
45         day -= year100*DAYS_PER_100Y;
47         year4 = day/DAYS_PER_4Y;
48         if (year4 == 25) year4--;
49         day -= year4*DAYS_PER_4Y;
51         year = day/365;
52         if (year == 4) year--;
53         day -= year*365;
55         leap = !year && (year4 || !year100);
56         yday = day + 31+28 + leap;
57         if (yday >= 365+leap) yday -= 365+leap;
59         year += 4*year4 + 100*year100 + 400*year400 + 2000-1900;
61         for (month=0; days_thru_month[month] <= day; month++);
62         if (month) day -= days_thru_month[month-1];
63         month += 2;
64         if (month >= 12) {
65                 month -= 12;
66                 year++;
67         }
69         mday = day+1;
71         tm->tm_sec = sec;
72         tm->tm_min = min;
73         tm->tm_hour= hour;
74         tm->tm_mday= mday;
75         tm->tm_mon = month;
76         tm->tm_year= year;
77         tm->tm_wday= wday;
78         tm->tm_yday= yday;
79         tm->__tm_zone = 0;
80         tm->__tm_gmtoff = 0;
82         return tm;
83 }