OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [newlib-1.17.0/] [newlib/] [libc/] [time/] [mktime.c] - Blame information for rev 868

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 148 jeremybenn
/*
2
 * mktime.c
3
 * Original Author:     G. Haley
4
 *
5
 * Converts the broken-down time, expressed as local time, in the structure
6
 * pointed to by tim_p into a calendar time value. The original values of the
7
 * tm_wday and tm_yday fields of the structure are ignored, and the original
8
 * values of the other fields have no restrictions. On successful completion
9
 * the fields of the structure are set to represent the specified calendar
10
 * time. Returns the specified calendar time. If the calendar time can not be
11
 * represented, returns the value (time_t) -1.
12
 *
13
 * Modifications:       Fixed tm_isdst usage - 27 August 2008 Craig Howland.
14
 */
15
 
16
/*
17
FUNCTION
18
<<mktime>>---convert time to arithmetic representation
19
 
20
INDEX
21
        mktime
22
 
23
ANSI_SYNOPSIS
24
        #include <time.h>
25
        time_t mktime(struct tm *<[timp]>);
26
 
27
TRAD_SYNOPSIS
28
        #include <time.h>
29
        time_t mktime(<[timp]>)
30
        struct tm *<[timp]>;
31
 
32
DESCRIPTION
33
<<mktime>> assumes the time at <[timp]> is a local time, and converts
34
its representation from the traditional representation defined by
35
<<struct tm>> into a representation suitable for arithmetic.
36
 
37
<<localtime>> is the inverse of <<mktime>>.
38
 
39
RETURNS
40
If the contents of the structure at <[timp]> do not form a valid
41
calendar time representation, the result is <<-1>>.  Otherwise, the
42
result is the time, converted to a <<time_t>> value.
43
 
44
PORTABILITY
45
ANSI C requires <<mktime>>.
46
 
47
<<mktime>> requires no supporting OS subroutines.
48
*/
49
 
50
#include <stdlib.h>
51
#include <time.h>
52
#include "local.h"
53
 
54
#define _SEC_IN_MINUTE 60L
55
#define _SEC_IN_HOUR 3600L
56
#define _SEC_IN_DAY 86400L
57
 
58
static _CONST int DAYS_IN_MONTH[12] =
59
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
60
 
61
#define _DAYS_IN_MONTH(x) ((x == 1) ? days_in_feb : DAYS_IN_MONTH[x])
62
 
63
static _CONST int _DAYS_BEFORE_MONTH[12] =
64
{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
65
 
66
#define _ISLEAP(y) (((y) % 4) == 0 && (((y) % 100) != 0 || (((y)+1900) % 400) == 0))
67
#define _DAYS_IN_YEAR(year) (_ISLEAP(year) ? 366 : 365)
68
 
69
static void
70
_DEFUN(validate_structure, (tim_p),
71
     struct tm *tim_p)
72
{
73
  div_t res;
74
  int days_in_feb = 28;
75
 
76
  /* calculate time & date to account for out of range values */
77
  if (tim_p->tm_sec < 0 || tim_p->tm_sec > 59)
78
    {
79
      res = div (tim_p->tm_sec, 60);
80
      tim_p->tm_min += res.quot;
81
      if ((tim_p->tm_sec = res.rem) < 0)
82
        {
83
          tim_p->tm_sec += 60;
84
          --tim_p->tm_min;
85
        }
86
    }
87
 
88
  if (tim_p->tm_min < 0 || tim_p->tm_min > 59)
89
    {
90
      res = div (tim_p->tm_min, 60);
91
      tim_p->tm_hour += res.quot;
92
      if ((tim_p->tm_min = res.rem) < 0)
93
        {
94
          tim_p->tm_min += 60;
95
          --tim_p->tm_hour;
96
        }
97
    }
98
 
99
  if (tim_p->tm_hour < 0 || tim_p->tm_hour > 23)
100
    {
101
      res = div (tim_p->tm_hour, 24);
102
      tim_p->tm_mday += res.quot;
103
      if ((tim_p->tm_hour = res.rem) < 0)
104
        {
105
          tim_p->tm_hour += 24;
106
          --tim_p->tm_mday;
107
        }
108
    }
109
 
110
  if (tim_p->tm_mon > 11)
111
    {
112
      res = div (tim_p->tm_mon, 12);
113
      tim_p->tm_year += res.quot;
114
      if ((tim_p->tm_mon = res.rem) < 0)
115
        {
116
          tim_p->tm_mon += 12;
117
          --tim_p->tm_year;
118
        }
119
    }
120
 
121
  if (_DAYS_IN_YEAR (tim_p->tm_year) == 366)
122
    days_in_feb = 29;
123
 
124
  if (tim_p->tm_mday <= 0)
125
    {
126
      while (tim_p->tm_mday <= 0)
127
        {
128
          if (--tim_p->tm_mon == -1)
129
            {
130
              tim_p->tm_year--;
131
              tim_p->tm_mon = 11;
132
              days_in_feb =
133
                ((_DAYS_IN_YEAR (tim_p->tm_year) == 366) ?
134
                 29 : 28);
135
            }
136
          tim_p->tm_mday += _DAYS_IN_MONTH (tim_p->tm_mon);
137
        }
138
    }
139
  else
140
    {
141
      while (tim_p->tm_mday > _DAYS_IN_MONTH (tim_p->tm_mon))
142
        {
143
          tim_p->tm_mday -= _DAYS_IN_MONTH (tim_p->tm_mon);
144
          if (++tim_p->tm_mon == 12)
145
            {
146
              tim_p->tm_year++;
147
              tim_p->tm_mon = 0;
148
              days_in_feb =
149
                ((_DAYS_IN_YEAR (tim_p->tm_year) == 366) ?
150
                 29 : 28);
151
            }
152
        }
153
    }
154
}
155
 
156
time_t
157
_DEFUN(mktime, (tim_p),
158
     struct tm *tim_p)
159
{
160
  time_t tim = 0;
161
  long days = 0;
162
  int year, isdst, tm_isdst;
163
  __tzinfo_type *tz = __gettzinfo ();
164
 
165
  /* validate structure */
166
  validate_structure (tim_p);
167
 
168
  /* compute hours, minutes, seconds */
169
  tim += tim_p->tm_sec + (tim_p->tm_min * _SEC_IN_MINUTE) +
170
    (tim_p->tm_hour * _SEC_IN_HOUR);
171
 
172
  /* compute days in year */
173
  days += tim_p->tm_mday - 1;
174
  days += _DAYS_BEFORE_MONTH[tim_p->tm_mon];
175
  if (tim_p->tm_mon > 1 && _DAYS_IN_YEAR (tim_p->tm_year) == 366)
176
    days++;
177
 
178
  /* compute day of the year */
179
  tim_p->tm_yday = days;
180
 
181
  if (tim_p->tm_year > 10000
182
      || tim_p->tm_year < -10000)
183
    {
184
      return (time_t) -1;
185
    }
186
 
187
  /* compute days in other years */
188
  if (tim_p->tm_year > 70)
189
    {
190
      for (year = 70; year < tim_p->tm_year; year++)
191
        days += _DAYS_IN_YEAR (year);
192
    }
193
  else if (tim_p->tm_year < 70)
194
    {
195
      for (year = 69; year > tim_p->tm_year; year--)
196
        days -= _DAYS_IN_YEAR (year);
197
      days -= _DAYS_IN_YEAR (year);
198
    }
199
 
200
  /* compute day of the week */
201
  if ((tim_p->tm_wday = (days + 4) % 7) < 0)
202
    tim_p->tm_wday += 7;
203
 
204
  /* compute total seconds */
205
  tim += (days * _SEC_IN_DAY);
206
 
207
  /* Convert user positive into 1 */
208
  tm_isdst = tim_p->tm_isdst > 0  ?  1 : tim_p->tm_isdst;
209
  isdst = tm_isdst;
210
 
211
  if (_daylight)
212
    {
213
      int y = tim_p->tm_year + YEAR_BASE;
214
      if (y == tz->__tzyear || __tzcalc_limits (y))
215
        {
216
          /* calculate start of dst in dst local time and
217
             start of std in both std local time and dst local time */
218
          time_t startdst_dst = tz->__tzrule[0].change
219
            - (time_t) tz->__tzrule[1].offset;
220
          time_t startstd_dst = tz->__tzrule[1].change
221
            - (time_t) tz->__tzrule[1].offset;
222
          time_t startstd_std = tz->__tzrule[1].change
223
            - (time_t) tz->__tzrule[0].offset;
224
          /* if the time is in the overlap between dst and std local times */
225
          if (tim >= startstd_std && tim < startstd_dst)
226
            ; /* we let user decide or leave as -1 */
227
          else
228
            {
229
              isdst = (tz->__tznorth
230
                       ? (tim >= startdst_dst && tim < startstd_std)
231
                       : (tim >= startdst_dst || tim < startstd_std));
232
              /* if user committed and was wrong, perform correction, but not
233
               * if the user has given a negative value (which
234
               * asks mktime() to determine if DST is in effect or not) */
235
              if (tm_isdst >= 0  &&  (isdst ^ tm_isdst) == 1)
236
                {
237
                  /* we either subtract or add the difference between
238
                     time zone offsets, depending on which way the user got it
239
                     wrong. The diff is typically one hour, or 3600 seconds,
240
                     and should fit in a 16-bit int, even though offset
241
                     is a long to accomodate 12 hours. */
242
                  int diff = (int) (tz->__tzrule[0].offset
243
                                    - tz->__tzrule[1].offset);
244
                  if (!isdst)
245
                    diff = -diff;
246
                  tim_p->tm_sec += diff;
247
                  validate_structure (tim_p);
248
                  tim += diff;  /* we also need to correct our current time calculation */
249
                }
250
            }
251
        }
252
    }
253
 
254
  /* add appropriate offset to put time in gmt format */
255
  if (isdst == 1)
256
    tim += (time_t) tz->__tzrule[1].offset;
257
  else /* otherwise assume std time */
258
    tim += (time_t) tz->__tzrule[0].offset;
259
 
260
  /* reset isdst flag to what we have calculated */
261
  tim_p->tm_isdst = isdst;
262
 
263
  return tim;
264
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.