Subversion Repositories Kolibri OS

Rev

Rev 1906 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1906 serge 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
5
 *                      Fixed bug in mday computations - 08/12/04, Alex Mogilnikov 
6
 *                      Fixed bug in __tzcalc_limits - 08/12/04, Alex Mogilnikov 
7
 *
8
 * Converts the calendar time pointed to by tim_p into a broken-down time
9
 * expressed as local time. Returns a pointer to a structure containing the
10
 * broken-down time.
11
 */
12
 
13
#include 
14
#include 
15
#include "local.h"
16
 
17
static _CONST int mon_lengths[2][MONSPERYEAR] = {
18
  {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
19
  {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
20
} ;
21
 
22
static _CONST int year_lengths[2] = {
23
  365,
24
  366
25
} ;
26
 
27
struct tm *
28
_DEFUN (_mktm_r, (tim_p, res, is_gmtime),
29
	_CONST time_t * tim_p _AND
30
	struct tm *res _AND
31
	int is_gmtime)
32
{
33
  long days, rem;
34
  time_t lcltime;
35
  int y;
36
  int yleap;
37
  _CONST int *ip;
38
   __tzinfo_type *tz = __gettzinfo ();
39
 
40
  /* base decision about std/dst time on current time */
41
  lcltime = *tim_p;
42
 
43
  days = ((long)lcltime) / SECSPERDAY;
44
  rem = ((long)lcltime) % SECSPERDAY;
45
  while (rem < 0)
46
    {
47
      rem += SECSPERDAY;
48
      --days;
49
    }
50
  while (rem >= SECSPERDAY)
51
    {
52
      rem -= SECSPERDAY;
53
      ++days;
54
    }
55
 
56
  /* compute hour, min, and sec */
57
  res->tm_hour = (int) (rem / SECSPERHOUR);
58
  rem %= SECSPERHOUR;
59
  res->tm_min = (int) (rem / SECSPERMIN);
60
  res->tm_sec = (int) (rem % SECSPERMIN);
61
 
62
  /* compute day of week */
63
  if ((res->tm_wday = ((EPOCH_WDAY + days) % DAYSPERWEEK)) < 0)
64
    res->tm_wday += DAYSPERWEEK;
65
 
66
  /* compute year & day of year */
67
  y = EPOCH_YEAR;
68
  if (days >= 0)
69
    {
70
      for (;;)
71
	{
72
	  yleap = isleap(y);
73
	  if (days < year_lengths[yleap])
74
	    break;
75
	  y++;
76
	  days -= year_lengths[yleap];
77
	}
78
    }
79
  else
80
    {
81
      do
82
	{
83
	  --y;
84
	  yleap = isleap(y);
85
	  days += year_lengths[yleap];
86
	} while (days < 0);
87
    }
88
 
89
  res->tm_year = y - YEAR_BASE;
90
  res->tm_yday = days;
91
  ip = mon_lengths[yleap];
92
  for (res->tm_mon = 0; days >= ip[res->tm_mon]; ++res->tm_mon)
93
    days -= ip[res->tm_mon];
94
  res->tm_mday = days + 1;
95
 
96
  if (!is_gmtime)
97
    {
98
      long offset;
99
      int hours, mins, secs;
100
 
101
      TZ_LOCK;
102
      if (_daylight)
103
	{
104
	  if (y == tz->__tzyear || __tzcalc_limits (y))
105
	    res->tm_isdst = (tz->__tznorth
106
			     ? (*tim_p >= tz->__tzrule[0].change
107
				&& *tim_p < tz->__tzrule[1].change)
108
			     : (*tim_p >= tz->__tzrule[0].change
109
				|| *tim_p < tz->__tzrule[1].change));
110
	  else
111
	    res->tm_isdst = -1;
112
	}
113
      else
114
	res->tm_isdst = 0;
115
 
116
      offset = (res->tm_isdst == 1
117
		  ? tz->__tzrule[1].offset
118
		  : tz->__tzrule[0].offset);
119
 
120
      hours = (int) (offset / SECSPERHOUR);
121
      offset = offset % SECSPERHOUR;
122
 
123
      mins = (int) (offset / SECSPERMIN);
124
      secs = (int) (offset % SECSPERMIN);
125
 
126
      res->tm_sec -= secs;
127
      res->tm_min -= mins;
128
      res->tm_hour -= hours;
129
 
130
      if (res->tm_sec >= SECSPERMIN)
131
	{
132
	  res->tm_min += 1;
133
	  res->tm_sec -= SECSPERMIN;
134
	}
135
      else if (res->tm_sec < 0)
136
	{
137
	  res->tm_min -= 1;
138
	  res->tm_sec += SECSPERMIN;
139
	}
140
      if (res->tm_min >= MINSPERHOUR)
141
	{
142
	  res->tm_hour += 1;
143
	  res->tm_min -= MINSPERHOUR;
144
	}
145
      else if (res->tm_min < 0)
146
	{
147
	  res->tm_hour -= 1;
148
	  res->tm_min += MINSPERHOUR;
149
	}
150
      if (res->tm_hour >= HOURSPERDAY)
151
	{
152
	  ++res->tm_yday;
153
	  ++res->tm_wday;
154
	  if (res->tm_wday > 6)
155
	    res->tm_wday = 0;
156
	  ++res->tm_mday;
157
	  res->tm_hour -= HOURSPERDAY;
158
	  if (res->tm_mday > ip[res->tm_mon])
159
	    {
160
	      res->tm_mday -= ip[res->tm_mon];
161
	      res->tm_mon += 1;
162
	      if (res->tm_mon == 12)
163
		{
164
		  res->tm_mon = 0;
165
		  res->tm_year += 1;
166
		  res->tm_yday = 0;
167
		}
168
	    }
169
	}
170
       else if (res->tm_hour < 0)
171
	{
172
	  res->tm_yday -= 1;
173
	  res->tm_wday -= 1;
174
	  if (res->tm_wday < 0)
175
	    res->tm_wday = 6;
176
	  res->tm_mday -= 1;
177
	  res->tm_hour += 24;
178
	  if (res->tm_mday == 0)
179
	    {
180
	      res->tm_mon -= 1;
181
	      if (res->tm_mon < 0)
182
		{
183
		  res->tm_mon = 11;
184
		  res->tm_year -= 1;
3065 serge 185
		  res->tm_yday = 364 + isleap(res->tm_year + 1900);
1906 serge 186
		}
187
	      res->tm_mday = ip[res->tm_mon];
188
	    }
189
	}
190
      TZ_UNLOCK;
191
    }
192
  else
193
    res->tm_isdst = 0;
194
 
195
  return (res);
196
}
197
 
198
int
199
_DEFUN (__tzcalc_limits, (year),
200
	int year)
201
{
202
  int days, year_days, years;
203
  int i, j;
204
  __tzinfo_type *tz = __gettzinfo ();
205
 
206
  if (year < EPOCH_YEAR)
207
    return 0;
208
 
209
  tz->__tzyear = year;
210
 
211
  years = (year - EPOCH_YEAR);
212
 
213
  year_days = years * 365 +
214
    (years - 1 + EPOCH_YEARS_SINCE_LEAP) / 4 - (years - 1 + EPOCH_YEARS_SINCE_CENTURY) / 100 +
215
    (years - 1 + EPOCH_YEARS_SINCE_LEAP_CENTURY) / 400;
216
 
217
  for (i = 0; i < 2; ++i)
218
    {
3065 serge 219
	if (tz->__tzrule[i].ch == 'J') {
220
        /* The Julian day n (1 <= n <= 365). */
1906 serge 221
	days = year_days + tz->__tzrule[i].d +
222
		(isleap(year) && tz->__tzrule[i].d >= 60);
3065 serge 223
        /* Convert to yday */
224
        --days;
225
	} else if (tz->__tzrule[i].ch == 'D')
1906 serge 226
	days = year_days + tz->__tzrule[i].d;
227
      else
228
	{
229
	  int yleap = isleap(year);
230
	  int m_day, m_wday, wday_diff;
231
	  _CONST int *ip = mon_lengths[yleap];
232
 
233
	  days = year_days;
234
 
235
	  for (j = 1; j < tz->__tzrule[i].m; ++j)
236
	    days += ip[j-1];
237
 
238
	  m_wday = (EPOCH_WDAY + days) % DAYSPERWEEK;
239
 
240
	  wday_diff = tz->__tzrule[i].d - m_wday;
241
	  if (wday_diff < 0)
242
	    wday_diff += DAYSPERWEEK;
243
	  m_day = (tz->__tzrule[i].n - 1) * DAYSPERWEEK + wday_diff;
244
 
245
	  while (m_day >= ip[j-1])
246
	    m_day -= DAYSPERWEEK;
247
 
248
	  days += m_day;
249
	}
250
 
251
      /* store the change-over time in GMT form by adding offset */
252
      tz->__tzrule[i].change = days * SECSPERDAY +
253
	      			tz->__tzrule[i].s + tz->__tzrule[i].offset;
254
    }
255
 
256
  tz->__tznorth = (tz->__tzrule[0].change < tz->__tzrule[1].change);
257
 
258
  return 1;
259
}