fixed more binutils issues (newer gcc/libc)
[zpugcc/jano.git] / toolchain / gcc / newlib / libc / time / mktm_r.c
blob4fdfb9b7bb8a29927bafe575922bf4f46ff3602e
1 /*
2 * mktm_r.c
3 * Original Author: Adapted from tzcode maintained by Arthur David Olson.
4 * Modifications: Changed to mktm_r and added __tzcalc_limits - 04/10/02, Jeff Johnston
6 * Converts the calendar time pointed to by tim_p into a broken-down time
7 * expressed as local time. Returns a pointer to a structure containing the
8 * broken-down time.
9 */
11 #include <stdlib.h>
12 #include <time.h>
13 #include "local.h"
15 static _CONST int mon_lengths[2][MONSPERYEAR] = {
16 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
17 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
18 } ;
20 static _CONST int year_lengths[2] = {
21 365,
22 366
23 } ;
25 struct tm *
26 _DEFUN (_mktm_r, (tim_p, res, is_gmtime),
27 _CONST time_t * tim_p _AND
28 struct tm *res _AND
29 int is_gmtime)
31 long days, rem;
32 time_t lcltime;
33 int i;
34 int y;
35 int yleap;
36 _CONST int *ip;
38 /* base decision about std/dst time on current time */
39 lcltime = *tim_p;
41 days = ((long)lcltime) / SECSPERDAY;
42 rem = ((long)lcltime) % SECSPERDAY;
43 while (rem < 0)
45 rem += SECSPERDAY;
46 --days;
48 while (rem >= SECSPERDAY)
50 rem -= SECSPERDAY;
51 ++days;
54 /* compute hour, min, and sec */
55 res->tm_hour = (int) (rem / SECSPERHOUR);
56 rem %= SECSPERHOUR;
57 res->tm_min = (int) (rem / SECSPERMIN);
58 res->tm_sec = (int) (rem % SECSPERMIN);
60 /* compute day of week */
61 if ((res->tm_wday = ((EPOCH_WDAY + days) % DAYSPERWEEK)) < 0)
62 res->tm_wday += DAYSPERWEEK;
64 /* compute year & day of year */
65 y = EPOCH_YEAR;
66 if (days >= 0)
68 for (;;)
70 yleap = isleap(y);
71 if (days < year_lengths[yleap])
72 break;
73 y++;
74 days -= year_lengths[yleap];
77 else
81 --y;
82 yleap = isleap(y);
83 days += year_lengths[yleap];
84 } while (days < 0);
87 res->tm_year = y - YEAR_BASE;
88 res->tm_yday = days;
89 ip = mon_lengths[yleap];
90 for (res->tm_mon = 0; days >= ip[res->tm_mon]; ++res->tm_mon)
91 days -= ip[res->tm_mon];
92 res->tm_mday = days + 1;
94 if (!is_gmtime)
96 int offset;
97 int hours, mins, secs;
99 TZ_LOCK;
100 if (_daylight)
102 if (y == __tzyear || __tzcalc_limits (y))
103 res->tm_isdst = (__tznorth
104 ? (*tim_p >= __tzrule[0].change && *tim_p < __tzrule[1].change)
105 : (*tim_p >= __tzrule[0].change || *tim_p < __tzrule[1].change));
106 else
107 res->tm_isdst = -1;
109 else
110 res->tm_isdst = 0;
112 offset = (res->tm_isdst == 1 ? __tzrule[1].offset : __tzrule[0].offset);
114 hours = offset / SECSPERHOUR;
115 offset = offset % SECSPERHOUR;
117 mins = offset / SECSPERMIN;
118 secs = offset % SECSPERMIN;
120 res->tm_sec -= secs;
121 res->tm_min -= mins;
122 res->tm_hour -= hours;
124 if (res->tm_sec >= SECSPERMIN)
126 res->tm_min += 1;
127 res->tm_sec -= SECSPERMIN;
129 else if (res->tm_sec < 0)
131 res->tm_min -= 1;
132 res->tm_sec += SECSPERMIN;
134 if (res->tm_min >= MINSPERHOUR)
136 res->tm_hour += 1;
137 res->tm_min -= MINSPERHOUR;
139 else if (res->tm_min < 0)
141 res->tm_hour -= 1;
142 res->tm_min += MINSPERHOUR;
144 if (res->tm_hour >= HOURSPERDAY)
146 ++res->tm_yday;
147 ++res->tm_wday;
148 if (res->tm_wday > 6)
149 res->tm_wday = 0;
150 ++res->tm_mday;
151 res->tm_hour -= HOURSPERDAY;
152 if (res->tm_mday >= ip[res->tm_mon])
154 res->tm_mday -= ip[res->tm_mon] - 1;
155 res->tm_mon += 1;
156 if (res->tm_mon == 12)
158 res->tm_mon = 0;
159 res->tm_year += 1;
160 res->tm_yday = 0;
164 else if (res->tm_hour < 0)
166 res->tm_yday -= 1;
167 res->tm_wday -= 1;
168 if (res->tm_wday < 0)
169 res->tm_wday = 6;
170 res->tm_mday -= 1;
171 res->tm_hour += 24;
172 if (res->tm_mday == 0)
174 res->tm_mon -= 1;
175 if (res->tm_mon < 0)
177 res->tm_mon = 11;
178 res->tm_year -= 1;
179 res->tm_yday = 365 + isleap(res->tm_year);
181 res->tm_mday = ip[res->tm_mon];
184 TZ_UNLOCK;
186 else
187 res->tm_isdst = 0;
189 return (res);
193 _DEFUN (__tzcalc_limits, (year),
194 int year)
196 int days, year_days, years;
197 int i, j;
199 if (year < EPOCH_YEAR)
200 return 0;
202 __tzyear = year;
204 years = (year - EPOCH_YEAR);
206 year_days = years * 365 +
207 (years - 1 + EPOCH_YEARS_SINCE_LEAP) / 4 - (years - 1 + EPOCH_YEARS_SINCE_CENTURY) / 100 +
208 (years - 1 + EPOCH_YEARS_SINCE_LEAP_CENTURY) / 400;
210 for (i = 0; i < 2; ++i)
212 if (__tzrule[i].ch == 'J')
213 days = year_days + __tzrule[i].d + (isleap(year) && __tzrule[i].d >= 60);
214 else if (__tzrule[i].ch == 'D')
215 days = year_days + __tzrule[i].d;
216 else
218 int yleap = isleap(year);
219 int m_day, m_wday, wday_diff;
220 _CONST int *ip = mon_lengths[yleap];
222 days = year_days;
224 for (j = 1; j < __tzrule[i].m; ++j)
225 days += ip[j-1];
227 m_wday = (EPOCH_WDAY + days) % DAYSPERWEEK;
229 wday_diff = __tzrule[i].d - m_wday;
230 if (wday_diff < 0)
231 wday_diff += DAYSPERWEEK;
232 m_day = (__tzrule[i].n - 1) * DAYSPERWEEK + wday_diff;
234 while (m_day >= ip[j])
235 m_day -= DAYSPERWEEK;
237 days += m_day;
240 /* store the change-over time in GMT form by adding offset */
241 __tzrule[i].change = days * SECSPERDAY + __tzrule[i].s + __tzrule[i].offset;
244 __tznorth = (__tzrule[0].change < __tzrule[1].change);
246 return 1;