Rev

Rev 2386 | Details | Compare with Previous | Last modification | View Log | SVN | Bug Tracker

Rev Author Line No. Line
2386 filatov 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
#ifdef _MSC_VER
43
#define _CRT_SECURE_NO_WARNINGS
44
#endif
45
 
46
#include <stdlib.h>
47
#include <time.h>
48
#include <stdio.h>
49
#include "mkgmtime.h"
50
 
51
#define _SEC_IN_MINUTE 60L
52
#define _SEC_IN_HOUR 3600L
53
#define _SEC_IN_DAY 86400L
54
 
55
static const int DAYS_IN_MONTH[12] =
56
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
57
 
58
#define _DAYS_IN_MONTH(x) ((x == 1) ? days_in_feb : DAYS_IN_MONTH[x])
59
 
60
static const int _DAYS_BEFORE_MONTH[12] =
61
{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
62
 
63
#define _ISLEAP(y) (((y) % 4) == 0 && (((y) % 100) != 0 || (((y)+1900) % 400) == 0))
64
#define _DAYS_IN_YEAR(year) (_ISLEAP(year) ? 366 : 365)
65
 
66
static void validate_structure(struct tm *tim_p)
67
{
68
  div_t res;
69
  int days_in_feb = 28;
70
 
71
  /* calculate time & date to account for out of range values */
72
  if (tim_p->tm_sec < 0 || tim_p->tm_sec > 59)
73
    {
74
      res = div (tim_p->tm_sec, 60);
75
      tim_p->tm_min += res.quot;
76
      if ((tim_p->tm_sec = res.rem) < 0)
77
        {
78
          tim_p->tm_sec += 60;
79
          --tim_p->tm_min;
80
        }
81
    }
82
 
83
  if (tim_p->tm_min < 0 || tim_p->tm_min > 59)
84
    {
85
      res = div (tim_p->tm_min, 60);
86
      tim_p->tm_hour += res.quot;
87
      if ((tim_p->tm_min = res.rem) < 0)
88
        {
89
          tim_p->tm_min += 60;
90
          --tim_p->tm_hour;
91
        }
92
    }
93
 
94
  if (tim_p->tm_hour < 0 || tim_p->tm_hour > 23)
95
    {
96
      res = div (tim_p->tm_hour, 24);
97
      tim_p->tm_mday += res.quot;
98
      if ((tim_p->tm_hour = res.rem) < 0)
99
        {
100
          tim_p->tm_hour += 24;
101
          --tim_p->tm_mday;
102
        }
103
    }
104
 
105
  if (tim_p->tm_mon > 11)
106
    {
107
      res = div (tim_p->tm_mon, 12);
108
      tim_p->tm_year += res.quot;
109
      if ((tim_p->tm_mon = res.rem) < 0)
110
        {
111
          tim_p->tm_mon += 12;
112
          --tim_p->tm_year;
113
        }
114
    }
115
 
116
  if (_DAYS_IN_YEAR (tim_p->tm_year) == 366)
117
    days_in_feb = 29;
118
 
119
  if (tim_p->tm_mday <= 0)
120
    {
121
      while (tim_p->tm_mday <= 0)
122
        {
123
          if (--tim_p->tm_mon == -1)
124
            {
125
              tim_p->tm_year--;
126
              tim_p->tm_mon = 11;
127
              days_in_feb =
128
                ((_DAYS_IN_YEAR (tim_p->tm_year) == 366) ?
129
                 29 : 28);
130
            }
131
          tim_p->tm_mday += _DAYS_IN_MONTH (tim_p->tm_mon);
132
        }
133
    }
134
  else
135
    {
136
      while (tim_p->tm_mday > _DAYS_IN_MONTH (tim_p->tm_mon))
137
        {
138
          tim_p->tm_mday -= _DAYS_IN_MONTH (tim_p->tm_mon);
139
          if (++tim_p->tm_mon == 12)
140
            {
141
              tim_p->tm_year++;
142
              tim_p->tm_mon = 0;
143
              days_in_feb =
144
                ((_DAYS_IN_YEAR (tim_p->tm_year) == 366) ?
145
                 29 : 28);
146
            }
147
        }
148
    }
149
}
150
 
151
 
152
static const unsigned long _leap_moments[] = {
153
        1136073600,
154
        1230768000,
155
        1341100800,
156
        1435708800,
157
};
158
 
159
time_t addleapseconds(time_t t)
160
{
161
        int i;
162
        for (i = 0; i < sizeof(_leap_moments) / sizeof(_leap_moments[0]); i++){
163
                if (t < _leap_moments[i]) break;
164
        }
165
        return t + i;
166
}
167
 
168
time_t removeleapseconds(time_t t)
169
{
170
        int i;
171
        for (i = 0; i < sizeof(_leap_moments) / sizeof(_leap_moments[0]); i++){
172
                if (t < _leap_moments[i]) break;
173
                t--;
174
        }
175
        return t;
176
}
177
 
178
#define ITS_UTC_EPOCH 1072915200
179
 
180
unsigned long mkitstime32(struct tm *tim_p)
181
{
182
        time_t ret = mktaitime(tim_p);
183
        if (ret > 0){
184
                ret -= ITS_UTC_EPOCH;
185
        }
186
        return (unsigned long)ret;
187
}
188
 
189
unsigned long long mkitstime64(struct tm *tim_p)
190
{
191
        unsigned long long ret = mktaitime64(tim_p);
192
        if (ret > 0){
193
                ret -= ((unsigned long long)ITS_UTC_EPOCH) * 1000;
194
        }
195
        return ret;
196
}
197
 
198
time_t mktaitime(struct tm *tim_p)
199
{
200
        time_t t = mkgmtime(tim_p);
201
        if (t >= 0){
202
                t = addleapseconds(t);
203
        }
204
        return t;
205
}
206
 
207
unsigned long long mktaitime64(struct tm *tim_p)
208
{
209
        time_t t = mkgmtime(tim_p);
210
        if (t >= 0){
211
                t = addleapseconds(t);
212
        }
213
        return ((unsigned long long)t)*1000;
214
}
215
 
216
unsigned long unix2itstime32(time_t t)
217
{
218
        return ((unsigned long) addleapseconds(t)) - ITS_UTC_EPOCH;
219
}
220
 
221
unsigned long long unix2itstime64(time_t t)
222
{
223
        return (((unsigned long long) addleapseconds(t)) - ITS_UTC_EPOCH) * 1000;
224
}
225
 
226
static char _datebuf[8][16];
227
static int _datebufidx = 0;
228
const char * strgmtdate(time_t t)
229
{
230
        struct tm * tm;
231
        char * b = _datebuf[_datebufidx];
232
        _datebufidx = (_datebufidx + 1) & 7;
233
 
234
        tm = gmtime(&t);
235
        sprintf(b, "%u-%02u-%02u", 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday);
236
        return b;
237
}
238
 
239
const char * strtaidate(time_t t)
240
{
241
        return strgmtdate(removeleapseconds(t));
242
}
243
 
244
const char * stritsdate32(time_t t)
245
{
246
        return strtaidate(t + ITS_UTC_EPOCH);
247
}
248
 
249
time_t mkgmtime(struct tm *tim_p)
250
{
251
  time_t tim = 0;
252
  long days = 0;
253
  int year, isdst, tm_isdst;
254
 
255
  /* validate structure */
256
  validate_structure (tim_p);
257
 
258
  /* compute hours, minutes, seconds */
259
  tim += tim_p->tm_sec + (tim_p->tm_min * _SEC_IN_MINUTE) +
260
    (tim_p->tm_hour * _SEC_IN_HOUR);
261
 
262
  /* compute days in year */
263
  days += tim_p->tm_mday - 1;
264
  days += _DAYS_BEFORE_MONTH[tim_p->tm_mon];
265
  if (tim_p->tm_mon > 1 && _DAYS_IN_YEAR (tim_p->tm_year) == 366)
266
    days++;
267
 
268
  /* compute day of the year */
269
  tim_p->tm_yday = days;
270
 
271
  if (tim_p->tm_year > 10000
272
      || tim_p->tm_year < -10000)
273
    {
274
      return (time_t) -1;
275
    }
276
 
277
  /* compute days in other years */
278
  if (tim_p->tm_year > 70)
279
    {
280
      for (year = 70; year < tim_p->tm_year; year++)
281
        days += _DAYS_IN_YEAR (year);
282
    }
283
  else if (tim_p->tm_year < 70)
284
    {
285
      for (year = 69; year > tim_p->tm_year; year--)
286
        days -= _DAYS_IN_YEAR (year);
287
      days -= _DAYS_IN_YEAR (year);
288
    }
289
 
290
  /* compute day of the week */
291
  if ((tim_p->tm_wday = (days + 4) % 7) < 0)
292
    tim_p->tm_wday += 7;
293
 
294
  /* compute total seconds */
295
  tim += (days * _SEC_IN_DAY);
296
 
297
  /* Convert user positive into 1 */
298
  tm_isdst = tim_p->tm_isdst > 0  ?  1 : tim_p->tm_isdst;
299
  isdst = tm_isdst;
300
 
301
  //screw this!
302
 
303
 // if (_daylight)
304
 //   {
305
 //     int y = tim_p->tm_year + YEAR_BASE;
306
 //     if (y == tz->__tzyear || __tzcalc_limits (y))
307
        //{
308
        //  /* calculate start of dst in dst local time and 
309
        //     start of std in both std local time and dst local time */
310
 //         time_t startdst_dst = tz->__tzrule[0].change
311
        //    - (time_t) tz->__tzrule[1].offset;
312
        //  time_t startstd_dst = tz->__tzrule[1].change
313
        //    - (time_t) tz->__tzrule[1].offset;
314
        //  time_t startstd_std = tz->__tzrule[1].change
315
        //    - (time_t) tz->__tzrule[0].offset;
316
        //  /* if the time is in the overlap between dst and std local times */
317
        //  if (tim >= startstd_std && tim < startstd_dst)
318
        //    ; /* we let user decide or leave as -1 */
319
 //         else
320
        //    {
321
        //      isdst = (tz->__tznorth
322
        //               ? (tim >= startdst_dst && tim < startstd_std)
323
        //               : (tim >= startdst_dst || tim < startstd_std));
324
 //              /* if user committed and was wrong, perform correction, but not
325
 //               * if the user has given a negative value (which
326
 //               * asks mktime() to determine if DST is in effect or not) */
327
 //              if (tm_isdst >= 0  &&  (isdst ^ tm_isdst) == 1)
328
        //        {
329
        //          /* we either subtract or add the difference between
330
        //             time zone offsets, depending on which way the user got it
331
        //             wrong. The diff is typically one hour, or 3600 seconds,
332
        //             and should fit in a 16-bit int, even though offset
333
        //             is a long to accomodate 12 hours. */
334
        //          int diff = (int) (tz->__tzrule[0].offset
335
        //                            - tz->__tzrule[1].offset);
336
        //          if (!isdst)
337
        //            diff = -diff;
338
        //          tim_p->tm_sec += diff;
339
        //          validate_structure (tim_p);
340
        //          tim += diff;  /* we also need to correct our current time calculation */
341
        //        }
342
        //    }
343
        //}
344
 //   }
345
 
346
  //screw this also 
347
  /* add appropriate offset to put time in gmt format */
348
  //if (isdst == 1)
349
  //  tim += (time_t) tz->__tzrule[1].offset;
350
  //else /* otherwise assume std time */
351
  //  tim += (time_t) tz->__tzrule[0].offset;
352
 
353
  //and screw this too
354
  /* reset isdst flag to what we have calculated */
355
  tim_p->tm_isdst = isdst;
356
 
357
  return tim;
358
}
359
 
360
// vim: ts=2 sw=2 et