1 #include <stdbool.h>
2 #include <time.h>
3
4 /*
5 * Returns the number of leap years prior to the given year.
6 */
leap_years(int year)7 static int leap_years(int year)
8 {
9 return (year-1)/4 + (year-1)/400 - (year-1)/100;
10 }
11
is_leap_year(int year)12 static int is_leap_year(int year)
13 {
14 return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
15 }
16
days_in_month(int month,int year)17 static int days_in_month(int month, int year)
18 {
19 static char month_days[] = {
20 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
21 };
22
23 /* we may need to update this in the year 4000, pending a
24 * decision on whether or not it's a leap year */
25 if (month == 1)
26 return is_leap_year(year) ? 29 : 28;
27
28 return month_days[month];
29 }
30
31 static const int days_per_month[2][13] =
32 {{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
33 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}};
34
35 #define SECS_PER_MIN 60
36 #define SECS_PER_HOUR (SECS_PER_MIN*60)
37 #define SECS_PER_DAY (24*SECS_PER_HOUR)
38 #define DAYS_PER_YEAR 365
gmtime_r(const time_t * timep,struct tm * result)39 struct tm *gmtime_r(const time_t *timep, struct tm *result)
40 {
41 int i;
42 int Y;
43 int M;
44 int D;
45 int h;
46 int m;
47 int s;
48
49 D = *timep / SECS_PER_DAY;
50 s = *timep % SECS_PER_DAY;
51 m = s / 60;
52 h = m / 60;
53 m %= 60;
54 s %= 60;
55
56 /*
57 * Work out the year. We subtract one day for every four years
58 * and every 400 years after 1969. However as leap years don't
59 * occur every 100 years we add one day back to counteract the
60 * the subtraction for every 4 years.
61 */
62 Y = (D - (1+D/365)/4 + (69+D/365)/100 - (369+D/365)/400)/365;
63
64 /*
65 * Remember we're doing integer arithmetic here so
66 * leap_years(Y+1970) - leap_years(1970) != leap_years(Y)
67 */
68 D = D - Y*365 - (leap_years(Y+1970) - leap_years(1970)) + 1;
69 Y += 1970;
70
71 M = 0;
72 for (i = 0; i < 13; i++)
73 if (D <= days_per_month[is_leap_year(Y) ? 1 : 0][i]) {
74 M = i;
75 break;
76 }
77
78 D -= days_per_month[is_leap_year(Y)][M-1];
79 result->tm_year = Y;
80 result->tm_mon = M - 1;
81 result->tm_mday = D;
82 result->tm_hour = h;
83 result->tm_min = m;
84 result->tm_sec = s;
85 return result;
86 }
87
mktime(struct tm * tm)88 time_t mktime(struct tm *tm)
89 {
90 unsigned long year, month, mday, hour, minute, second, d;
91 static const unsigned long sec_in_400_years =
92 ((3903ul * 365) + (97 * 366)) * 24 * 60 * 60;
93
94 second = tm->tm_sec;
95 minute = tm->tm_min;
96 hour = tm->tm_hour;
97 mday = tm->tm_mday;
98 month = tm->tm_mon;
99 year = tm->tm_year;
100
101 /* There are the same number of seconds in any 400-year block; this
102 * limits the iterations in the loop below */
103 year += 400 * (second / sec_in_400_years);
104 second = second % sec_in_400_years;
105
106 if (second >= 60) {
107 minute += second / 60;
108 second = second % 60;
109 }
110
111 if (minute >= 60) {
112 hour += minute / 60;
113 minute = minute % 60;
114 }
115
116 if (hour >= 24) {
117 mday += hour / 24;
118 hour = hour % 24;
119 }
120
121 for (d = days_in_month(month, year); mday > d;
122 d = days_in_month(month, year)) {
123 month++;
124 if (month > 11) {
125 month = 0;
126 year++;
127 }
128 mday -= d;
129 }
130
131 tm->tm_year = year;
132 tm->tm_mon = month;
133 tm->tm_mday = mday;
134 tm->tm_hour = hour;
135 tm->tm_min = minute;
136 tm->tm_sec = second;
137
138 d = mday;
139 d += days_per_month[is_leap_year(year)][month];
140 d += (year-1970)*DAYS_PER_YEAR + leap_years(year) - leap_years(1970) - 1;
141 return d*SECS_PER_DAY + hour*SECS_PER_HOUR + minute*SECS_PER_MIN + second;
142 }
143