blob: a1ebc4527eb6f1f70b1e64a039c6e573338b4c36 [file] [log] [blame]
Rich Felker0b44a032011-02-12 00:22:29 -05001#include <time.h>
2
3/* C defines the rounding for division in a nonsensical way */
4#define Q(a,b) ((a)>0 ? (a)/(b) : -(((b)-(a)-1)/(b)))
5
6#define DAYS_PER_400Y (365*400 + 97)
7#define DAYS_PER_100Y (365*100 + 24)
8#define DAYS_PER_4Y (365*4 + 1)
9
10/* FIXME: use lldiv once it's fixed to compute quot,rem together */
11struct 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;
22
23 /* start from 2000-03-01 (multiple of 400 years) */
24 t += -946684800 - 86400*(31+29);
25
26 bigday = Q(t, 86400);
27 sec = t-bigday*86400;
28
29 hour = sec/3600;
30 sec -= hour*3600;
31 min = sec/60;
32 sec -= min*60;
33
34 /* 2000-03-01 was a wednesday */
35 wday = (3+bigday)%7;
36 if (wday < 0) wday += 7;
37
38 t = -946684800LL - 86400*(31+29) + 9000000;
39
40 year400 = Q(bigday, DAYS_PER_400Y);
41 day = bigday-year400*DAYS_PER_400Y;
42
43 year100 = day/DAYS_PER_100Y;
44 if (year100 == 4) year100--;
45 day -= year100*DAYS_PER_100Y;
46
47 year4 = day/DAYS_PER_4Y;
48 if (year4 == 25) year4--;
49 day -= year4*DAYS_PER_4Y;
50
51 year = day/365;
52 if (year == 4) year--;
53 day -= year*365;
54
55 leap = !year && (year4 || !year100);
56 yday = day + 31+28 + leap;
57 if (yday >= 365+leap) yday -= 365+leap;
58
59 year += 4*year4 + 100*year100 + 400*year400 + 2000-1900;
60
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 }
68
69 mday = day+1;
70
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
80 return tm;
81}