Line data Source code
1 : // Found in DeSmuME
2 : // Alexis modified it a tad bit so it would compile as C (opposed to C++)
3 :
4 : /* lib/mkgmtime.c
5 :
6 : Copyright (C) 2010 DeSmuME team
7 :
8 : This file is part of DeSmuME
9 :
10 : DeSmuME is free software; you can redistribute it and/or modify
11 : it under the terms of the GNU General Public License as published by
12 : the Free Software Foundation; either version 2 of the License, or
13 : (at your option) any later version.
14 :
15 : DeSmuME is distributed in the hope that it will be useful,
16 : but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : GNU General Public License for more details.
19 :
20 : You should have received a copy of the GNU General Public License
21 : along with DeSmuME; if not, write to the Free Software
22 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 : */
24 :
25 : //Taken from newlib 1.18.0 which is licensed under GPL 2 and modified for desmume
26 :
27 : /*
28 : * mktime.c
29 : * Original Author: G. Haley
30 : *
31 : * Converts the broken-down time, expressed as local time, in the structure
32 : * pointed to by tim_p into a calendar time value. The original values of the
33 : * tm_wday and tm_yday fields of the structure are ignored, and the original
34 : * values of the other fields have no restrictions. On successful completion
35 : * the fields of the structure are set to represent the specified calendar
36 : * time. Returns the specified calendar time. If the calendar time can not be
37 : * represented, returns the value (time_t) -1.
38 : *
39 : * Modifications: Fixed tm_isdst usage - 27 August 2008 Craig Howland.
40 : */
41 :
42 : #include "edhttp/mkgmtime.h"
43 :
44 : #include <stdlib.h>
45 :
46 : #define _SEC_IN_MINUTE 60L
47 : #define _SEC_IN_HOUR 3600L
48 : #define _SEC_IN_DAY 86400L
49 :
50 : static const int DAYS_IN_MONTH[12] =
51 : {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
52 :
53 : #define _DAYS_IN_MONTH(x) ((x == 1) ? days_in_feb : DAYS_IN_MONTH[x])
54 :
55 : static const int _DAYS_BEFORE_MONTH[12] =
56 : {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
57 :
58 : #define _ISLEAP(y) (((y) % 4) == 0 && (((y) % 100) != 0 || (((y)+1900) % 400) == 0))
59 : #define _DAYS_IN_YEAR(year) (_ISLEAP(year) ? 366 : 365)
60 :
61 0 : static void validate_structure(struct tm *tim_p)
62 : {
63 : div_t res;
64 0 : int days_in_feb = 28;
65 :
66 : /* calculate time & date to account for out of range values */
67 0 : if (tim_p->tm_sec < 0 || tim_p->tm_sec > 59)
68 : {
69 0 : res = div (tim_p->tm_sec, 60);
70 0 : tim_p->tm_min += res.quot;
71 0 : if ((tim_p->tm_sec = res.rem) < 0)
72 : {
73 0 : tim_p->tm_sec += 60;
74 0 : --tim_p->tm_min;
75 : }
76 : }
77 :
78 0 : if (tim_p->tm_min < 0 || tim_p->tm_min > 59)
79 : {
80 0 : res = div (tim_p->tm_min, 60);
81 0 : tim_p->tm_hour += res.quot;
82 0 : if ((tim_p->tm_min = res.rem) < 0)
83 : {
84 0 : tim_p->tm_min += 60;
85 0 : --tim_p->tm_hour;
86 : }
87 : }
88 :
89 0 : if (tim_p->tm_hour < 0 || tim_p->tm_hour > 23)
90 : {
91 0 : res = div (tim_p->tm_hour, 24);
92 0 : tim_p->tm_mday += res.quot;
93 0 : if ((tim_p->tm_hour = res.rem) < 0)
94 : {
95 0 : tim_p->tm_hour += 24;
96 0 : --tim_p->tm_mday;
97 : }
98 : }
99 :
100 0 : if (tim_p->tm_mon > 11)
101 : {
102 0 : res = div (tim_p->tm_mon, 12);
103 0 : tim_p->tm_year += res.quot;
104 0 : if ((tim_p->tm_mon = res.rem) < 0)
105 : {
106 0 : tim_p->tm_mon += 12;
107 0 : --tim_p->tm_year;
108 : }
109 : }
110 :
111 0 : if (_DAYS_IN_YEAR (tim_p->tm_year) == 366)
112 0 : days_in_feb = 29;
113 :
114 0 : if (tim_p->tm_mday <= 0)
115 : {
116 0 : while (tim_p->tm_mday <= 0)
117 : {
118 0 : if (--tim_p->tm_mon == -1)
119 : {
120 0 : tim_p->tm_year--;
121 0 : tim_p->tm_mon = 11;
122 0 : days_in_feb =
123 0 : ((_DAYS_IN_YEAR (tim_p->tm_year) == 366) ?
124 0 : 29 : 28);
125 : }
126 0 : tim_p->tm_mday += _DAYS_IN_MONTH (tim_p->tm_mon);
127 : }
128 : }
129 : else
130 : {
131 0 : while (tim_p->tm_mday > _DAYS_IN_MONTH (tim_p->tm_mon))
132 : {
133 0 : tim_p->tm_mday -= _DAYS_IN_MONTH (tim_p->tm_mon);
134 0 : if (++tim_p->tm_mon == 12)
135 : {
136 0 : tim_p->tm_year++;
137 0 : tim_p->tm_mon = 0;
138 0 : days_in_feb =
139 0 : ((_DAYS_IN_YEAR (tim_p->tm_year) == 366) ?
140 0 : 29 : 28);
141 : }
142 : }
143 : }
144 0 : }
145 :
146 0 : time_t mkgmtime(struct tm *tim_p)
147 : {
148 0 : time_t tim = 0;
149 0 : long days = 0;
150 : int year, isdst, tm_isdst;
151 :
152 : /* validate structure */
153 0 : validate_structure (tim_p);
154 :
155 : /* compute hours, minutes, seconds */
156 0 : tim += tim_p->tm_sec + (tim_p->tm_min * _SEC_IN_MINUTE) +
157 0 : (tim_p->tm_hour * _SEC_IN_HOUR);
158 :
159 : /* compute days in year */
160 0 : days += tim_p->tm_mday - 1;
161 0 : days += _DAYS_BEFORE_MONTH[tim_p->tm_mon];
162 0 : if (tim_p->tm_mon > 1 && _DAYS_IN_YEAR (tim_p->tm_year) == 366)
163 0 : days++;
164 :
165 : /* compute day of the year */
166 0 : tim_p->tm_yday = days;
167 :
168 0 : if (tim_p->tm_year > 10000
169 0 : || tim_p->tm_year < -10000)
170 : {
171 0 : return (time_t) -1;
172 : }
173 :
174 : /* compute days in other years */
175 0 : if (tim_p->tm_year > 70)
176 : {
177 0 : for (year = 70; year < tim_p->tm_year; year++)
178 0 : days += _DAYS_IN_YEAR (year);
179 : }
180 0 : else if (tim_p->tm_year < 70)
181 : {
182 0 : for (year = 69; year > tim_p->tm_year; year--)
183 0 : days -= _DAYS_IN_YEAR (year);
184 0 : days -= _DAYS_IN_YEAR (year);
185 : }
186 :
187 : /* compute day of the week */
188 0 : if ((tim_p->tm_wday = (days + 4) % 7) < 0)
189 0 : tim_p->tm_wday += 7;
190 :
191 : /* compute total seconds */
192 0 : tim += (days * _SEC_IN_DAY);
193 :
194 : /* Convert user positive into 1 */
195 0 : tm_isdst = tim_p->tm_isdst > 0 ? 1 : tim_p->tm_isdst;
196 0 : isdst = tm_isdst;
197 :
198 : //screw this!
199 :
200 : // if (_daylight)
201 : // {
202 : // int y = tim_p->tm_year + YEAR_BASE;
203 : // if (y == tz->__tzyear || __tzcalc_limits (y))
204 : //{
205 : // /* calculate start of dst in dst local time and
206 : // start of std in both std local time and dst local time */
207 : // time_t startdst_dst = tz->__tzrule[0].change
208 : // - (time_t) tz->__tzrule[1].offset;
209 : // time_t startstd_dst = tz->__tzrule[1].change
210 : // - (time_t) tz->__tzrule[1].offset;
211 : // time_t startstd_std = tz->__tzrule[1].change
212 : // - (time_t) tz->__tzrule[0].offset;
213 : // /* if the time is in the overlap between dst and std local times */
214 : // if (tim >= startstd_std && tim < startstd_dst)
215 : // ; /* we let user decide or leave as -1 */
216 : // else
217 : // {
218 : // isdst = (tz->__tznorth
219 : // ? (tim >= startdst_dst && tim < startstd_std)
220 : // : (tim >= startdst_dst || tim < startstd_std));
221 : // /* if user committed and was wrong, perform correction, but not
222 : // * if the user has given a negative value (which
223 : // * asks mktime() to determine if DST is in effect or not) */
224 : // if (tm_isdst >= 0 && (isdst ^ tm_isdst) == 1)
225 : // {
226 : // /* we either subtract or add the difference between
227 : // time zone offsets, depending on which way the user got it
228 : // wrong. The diff is typically one hour, or 3600 seconds,
229 : // and should fit in a 16-bit int, even though offset
230 : // is a long to accomodate 12 hours. */
231 : // int diff = (int) (tz->__tzrule[0].offset
232 : // - tz->__tzrule[1].offset);
233 : // if (!isdst)
234 : // diff = -diff;
235 : // tim_p->tm_sec += diff;
236 : // validate_structure (tim_p);
237 : // tim += diff; /* we also need to correct our current time calculation */
238 : // }
239 : // }
240 : //}
241 : // }
242 :
243 : //screw this also
244 : /* add appropriate offset to put time in gmt format */
245 : //if (isdst == 1)
246 : // tim += (time_t) tz->__tzrule[1].offset;
247 : //else /* otherwise assume std time */
248 : // tim += (time_t) tz->__tzrule[0].offset;
249 :
250 : //and screw this too
251 : /* reset isdst flag to what we have calculated */
252 0 : tim_p->tm_isdst = isdst;
253 :
254 0 : return tim;
255 : }
256 :
257 : // vim: ts=4 sw=4 et
|