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