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 "snapwebsites/mkgmtime.h"
43 :
44 : #include <stdlib.h>
45 : #include <time.h>
46 :
47 : #define _SEC_IN_MINUTE 60L
48 : #define _SEC_IN_HOUR 3600L
49 : #define _SEC_IN_DAY 86400L
50 :
51 : static const int DAYS_IN_MONTH[12] =
52 : {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
53 :
54 : #define _DAYS_IN_MONTH(x) ((x == 1) ? days_in_feb : DAYS_IN_MONTH[x])
55 :
56 : static const int _DAYS_BEFORE_MONTH[12] =
57 : {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
58 :
59 : #define _ISLEAP(y) (((y) % 4) == 0 && (((y) % 100) != 0 || (((y)+1900) % 400) == 0))
60 : #define _DAYS_IN_YEAR(year) (_ISLEAP(year) ? 366 : 365)
61 :
62 0 : static void validate_structure(struct tm *tim_p)
63 : {
64 : div_t res;
65 0 : int days_in_feb = 28;
66 :
67 : /* calculate time & date to account for out of range values */
68 0 : if (tim_p->tm_sec < 0 || tim_p->tm_sec > 59)
69 : {
70 0 : res = div (tim_p->tm_sec, 60);
71 0 : tim_p->tm_min += res.quot;
72 0 : if ((tim_p->tm_sec = res.rem) < 0)
73 : {
74 0 : tim_p->tm_sec += 60;
75 0 : --tim_p->tm_min;
76 : }
77 : }
78 :
79 0 : if (tim_p->tm_min < 0 || tim_p->tm_min > 59)
80 : {
81 0 : res = div (tim_p->tm_min, 60);
82 0 : tim_p->tm_hour += res.quot;
83 0 : if ((tim_p->tm_min = res.rem) < 0)
84 : {
85 0 : tim_p->tm_min += 60;
86 0 : --tim_p->tm_hour;
87 : }
88 : }
89 :
90 0 : if (tim_p->tm_hour < 0 || tim_p->tm_hour > 23)
91 : {
92 0 : res = div (tim_p->tm_hour, 24);
93 0 : tim_p->tm_mday += res.quot;
94 0 : if ((tim_p->tm_hour = res.rem) < 0)
95 : {
96 0 : tim_p->tm_hour += 24;
97 0 : --tim_p->tm_mday;
98 : }
99 : }
100 :
101 0 : if (tim_p->tm_mon > 11)
102 : {
103 0 : res = div (tim_p->tm_mon, 12);
104 0 : tim_p->tm_year += res.quot;
105 0 : if ((tim_p->tm_mon = res.rem) < 0)
106 : {
107 0 : tim_p->tm_mon += 12;
108 0 : --tim_p->tm_year;
109 : }
110 : }
111 :
112 0 : if (_DAYS_IN_YEAR (tim_p->tm_year) == 366)
113 0 : days_in_feb = 29;
114 :
115 0 : if (tim_p->tm_mday <= 0)
116 : {
117 0 : while (tim_p->tm_mday <= 0)
118 : {
119 0 : if (--tim_p->tm_mon == -1)
120 : {
121 0 : tim_p->tm_year--;
122 0 : tim_p->tm_mon = 11;
123 0 : days_in_feb =
124 0 : ((_DAYS_IN_YEAR (tim_p->tm_year) == 366) ?
125 0 : 29 : 28);
126 : }
127 0 : tim_p->tm_mday += _DAYS_IN_MONTH (tim_p->tm_mon);
128 : }
129 : }
130 : else
131 : {
132 0 : while (tim_p->tm_mday > _DAYS_IN_MONTH (tim_p->tm_mon))
133 : {
134 0 : tim_p->tm_mday -= _DAYS_IN_MONTH (tim_p->tm_mon);
135 0 : if (++tim_p->tm_mon == 12)
136 : {
137 0 : tim_p->tm_year++;
138 0 : tim_p->tm_mon = 0;
139 0 : days_in_feb =
140 0 : ((_DAYS_IN_YEAR (tim_p->tm_year) == 366) ?
141 0 : 29 : 28);
142 : }
143 : }
144 : }
145 0 : }
146 :
147 0 : time_t mkgmtime(struct tm *tim_p)
148 : {
149 0 : time_t tim = 0;
150 0 : long days = 0;
151 : int year, isdst, tm_isdst;
152 :
153 : /* validate structure */
154 0 : validate_structure (tim_p);
155 :
156 : /* compute hours, minutes, seconds */
157 0 : tim += tim_p->tm_sec + (tim_p->tm_min * _SEC_IN_MINUTE) +
158 0 : (tim_p->tm_hour * _SEC_IN_HOUR);
159 :
160 : /* compute days in year */
161 0 : days += tim_p->tm_mday - 1;
162 0 : days += _DAYS_BEFORE_MONTH[tim_p->tm_mon];
163 0 : if (tim_p->tm_mon > 1 && _DAYS_IN_YEAR (tim_p->tm_year) == 366)
164 0 : days++;
165 :
166 : /* compute day of the year */
167 0 : tim_p->tm_yday = days;
168 :
169 0 : if (tim_p->tm_year > 10000
170 0 : || tim_p->tm_year < -10000)
171 : {
172 0 : return (time_t) -1;
173 : }
174 :
175 : /* compute days in other years */
176 0 : if (tim_p->tm_year > 70)
177 : {
178 0 : for (year = 70; year < tim_p->tm_year; year++)
179 0 : days += _DAYS_IN_YEAR (year);
180 : }
181 0 : else if (tim_p->tm_year < 70)
182 : {
183 0 : for (year = 69; year > tim_p->tm_year; year--)
184 0 : days -= _DAYS_IN_YEAR (year);
185 0 : days -= _DAYS_IN_YEAR (year);
186 : }
187 :
188 : /* compute day of the week */
189 0 : if ((tim_p->tm_wday = (days + 4) % 7) < 0)
190 0 : tim_p->tm_wday += 7;
191 :
192 : /* compute total seconds */
193 0 : tim += (days * _SEC_IN_DAY);
194 :
195 : /* Convert user positive into 1 */
196 0 : tm_isdst = tim_p->tm_isdst > 0 ? 1 : tim_p->tm_isdst;
197 0 : isdst = tm_isdst;
198 :
199 : //screw this!
200 :
201 : // if (_daylight)
202 : // {
203 : // int y = tim_p->tm_year + YEAR_BASE;
204 : // if (y == tz->__tzyear || __tzcalc_limits (y))
205 : //{
206 : // /* calculate start of dst in dst local time and
207 : // start of std in both std local time and dst local time */
208 : // time_t startdst_dst = tz->__tzrule[0].change
209 : // - (time_t) tz->__tzrule[1].offset;
210 : // time_t startstd_dst = tz->__tzrule[1].change
211 : // - (time_t) tz->__tzrule[1].offset;
212 : // time_t startstd_std = tz->__tzrule[1].change
213 : // - (time_t) tz->__tzrule[0].offset;
214 : // /* if the time is in the overlap between dst and std local times */
215 : // if (tim >= startstd_std && tim < startstd_dst)
216 : // ; /* we let user decide or leave as -1 */
217 : // else
218 : // {
219 : // isdst = (tz->__tznorth
220 : // ? (tim >= startdst_dst && tim < startstd_std)
221 : // : (tim >= startdst_dst || tim < startstd_std));
222 : // /* if user committed and was wrong, perform correction, but not
223 : // * if the user has given a negative value (which
224 : // * asks mktime() to determine if DST is in effect or not) */
225 : // if (tm_isdst >= 0 && (isdst ^ tm_isdst) == 1)
226 : // {
227 : // /* we either subtract or add the difference between
228 : // time zone offsets, depending on which way the user got it
229 : // wrong. The diff is typically one hour, or 3600 seconds,
230 : // and should fit in a 16-bit int, even though offset
231 : // is a long to accomodate 12 hours. */
232 : // int diff = (int) (tz->__tzrule[0].offset
233 : // - tz->__tzrule[1].offset);
234 : // if (!isdst)
235 : // diff = -diff;
236 : // tim_p->tm_sec += diff;
237 : // validate_structure (tim_p);
238 : // tim += diff; /* we also need to correct our current time calculation */
239 : // }
240 : // }
241 : //}
242 : // }
243 :
244 : //screw this also
245 : /* add appropriate offset to put time in gmt format */
246 : //if (isdst == 1)
247 : // tim += (time_t) tz->__tzrule[1].offset;
248 : //else /* otherwise assume std time */
249 : // tim += (time_t) tz->__tzrule[0].offset;
250 :
251 : //and screw this too
252 : /* reset isdst flag to what we have calculated */
253 0 : tim_p->tm_isdst = isdst;
254 :
255 0 : return tim;
256 : }
257 :
258 : // vim: ts=2 sw=2 et
|