1
/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
* you may not use this file except in compliance with the License.
6
* You may obtain a copy of the License at
8
* http://www.apache.org/licenses/LICENSE-2.0
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
17
#include "apr_portable.h"
20
#include "apr_private.h"
21
#include "apr_strings.h"
23
/* private APR headers */
24
#include "apr_arch_internal_time.h"
26
/* System Headers required for time library */
27
#if APR_HAVE_SYS_TIME_H
36
/* End System Headers */
38
#if !defined(HAVE_STRUCT_TM_TM_GMTOFF) && !defined(HAVE_STRUCT_TM___TM_GMTOFF)
39
static apr_int32_t server_gmt_offset;
40
#define NO_GMTOFF_IN_STRUCT_TM
43
static apr_int32_t get_offset(struct tm *tm)
45
#if defined(HAVE_STRUCT_TM_TM_GMTOFF)
47
#elif defined(HAVE_STRUCT_TM___TM_GMTOFF)
48
return tm->__tm_gmtoff;
51
/* Need to adjust the global variable each time otherwise
52
the web server would have to be restarted when daylight
56
return server_gmt_offset + daylightOffset;
60
return server_gmt_offset + 3600;
62
return server_gmt_offset;
66
APR_DECLARE(apr_status_t) apr_time_ansi_put(apr_time_t *result,
69
*result = (apr_time_t)input * APR_USEC_PER_SEC;
73
/* NB NB NB NB This returns GMT!!!!!!!!!! */
74
APR_DECLARE(apr_time_t) apr_time_now(void)
77
gettimeofday(&tv, NULL);
78
return tv.tv_sec * APR_USEC_PER_SEC + tv.tv_usec;
81
static void explode_time(apr_time_exp_t *xt, apr_time_t t,
82
apr_int32_t offset, int use_localtime)
85
time_t tt = (t / APR_USEC_PER_SEC) + offset;
86
xt->tm_usec = t % APR_USEC_PER_SEC;
88
#if APR_HAS_THREADS && defined (_POSIX_THREAD_SAFE_FUNCTIONS)
90
localtime_r(&tt, &tm);
100
xt->tm_sec = tm.tm_sec;
101
xt->tm_min = tm.tm_min;
102
xt->tm_hour = tm.tm_hour;
103
xt->tm_mday = tm.tm_mday;
104
xt->tm_mon = tm.tm_mon;
105
xt->tm_year = tm.tm_year;
106
xt->tm_wday = tm.tm_wday;
107
xt->tm_yday = tm.tm_yday;
108
xt->tm_isdst = tm.tm_isdst;
109
xt->tm_gmtoff = get_offset(&tm);
112
APR_DECLARE(apr_status_t) apr_time_exp_tz(apr_time_exp_t *result,
113
apr_time_t input, apr_int32_t offs)
115
explode_time(result, input, offs, 0);
116
result->tm_gmtoff = offs;
120
APR_DECLARE(apr_status_t) apr_time_exp_gmt(apr_time_exp_t *result,
123
return apr_time_exp_tz(result, input, 0);
126
APR_DECLARE(apr_status_t) apr_time_exp_lt(apr_time_exp_t *result,
130
/* EMX gcc (OS/2) has a timezone global we can use */
131
return apr_time_exp_tz(result, input, -timezone);
133
explode_time(result, input, 0, 1);
138
APR_DECLARE(apr_status_t) apr_time_exp_get(apr_time_t *t, apr_time_exp_t *xt)
140
apr_time_t year = xt->tm_year;
142
static const int dayoffset[12] =
143
{306, 337, 0, 31, 61, 92, 122, 153, 184, 214, 245, 275};
145
/* shift new year to 1st March in order to make leap year calc easy */
150
/* Find number of days since 1st March 1900 (in the Gregorian calendar). */
152
days = year * 365 + year / 4 - year / 100 + (year / 100 + 3) / 4;
153
days += dayoffset[xt->tm_mon] + xt->tm_mday - 1;
154
days -= 25508; /* 1 jan 1970 is 25508 days since 1 mar 1900 */
155
days = ((days * 24 + xt->tm_hour) * 60 + xt->tm_min) * 60 + xt->tm_sec;
160
*t = days * APR_USEC_PER_SEC + xt->tm_usec;
164
APR_DECLARE(apr_status_t) apr_time_exp_gmt_get(apr_time_t *t,
167
apr_status_t status = apr_time_exp_get(t, xt);
168
if (status == APR_SUCCESS)
169
*t -= (apr_time_t) xt->tm_gmtoff * APR_USEC_PER_SEC;
173
APR_DECLARE(apr_status_t) apr_os_imp_time_get(apr_os_imp_time_t **ostime,
176
(*ostime)->tv_usec = *aprtime % APR_USEC_PER_SEC;
177
(*ostime)->tv_sec = *aprtime / APR_USEC_PER_SEC;
181
APR_DECLARE(apr_status_t) apr_os_exp_time_get(apr_os_exp_time_t **ostime,
182
apr_time_exp_t *aprtime)
184
(*ostime)->tm_sec = aprtime->tm_sec;
185
(*ostime)->tm_min = aprtime->tm_min;
186
(*ostime)->tm_hour = aprtime->tm_hour;
187
(*ostime)->tm_mday = aprtime->tm_mday;
188
(*ostime)->tm_mon = aprtime->tm_mon;
189
(*ostime)->tm_year = aprtime->tm_year;
190
(*ostime)->tm_wday = aprtime->tm_wday;
191
(*ostime)->tm_yday = aprtime->tm_yday;
192
(*ostime)->tm_isdst = aprtime->tm_isdst;
194
#if defined(HAVE_STRUCT_TM_TM_GMTOFF)
195
(*ostime)->tm_gmtoff = aprtime->tm_gmtoff;
196
#elif defined(HAVE_STRUCT_TM___TM_GMTOFF)
197
(*ostime)->__tm_gmtoff = aprtime->tm_gmtoff;
203
APR_DECLARE(apr_status_t) apr_os_imp_time_put(apr_time_t *aprtime,
204
apr_os_imp_time_t **ostime,
207
*aprtime = (*ostime)->tv_sec * APR_USEC_PER_SEC + (*ostime)->tv_usec;
211
APR_DECLARE(apr_status_t) apr_os_exp_time_put(apr_time_exp_t *aprtime,
212
apr_os_exp_time_t **ostime,
215
aprtime->tm_sec = (*ostime)->tm_sec;
216
aprtime->tm_min = (*ostime)->tm_min;
217
aprtime->tm_hour = (*ostime)->tm_hour;
218
aprtime->tm_mday = (*ostime)->tm_mday;
219
aprtime->tm_mon = (*ostime)->tm_mon;
220
aprtime->tm_year = (*ostime)->tm_year;
221
aprtime->tm_wday = (*ostime)->tm_wday;
222
aprtime->tm_yday = (*ostime)->tm_yday;
223
aprtime->tm_isdst = (*ostime)->tm_isdst;
225
#if defined(HAVE_STRUCT_TM_TM_GMTOFF)
226
aprtime->tm_gmtoff = (*ostime)->tm_gmtoff;
227
#elif defined(HAVE_STRUCT_TM___TM_GMTOFF)
228
aprtime->tm_gmtoff = (*ostime)->__tm_gmtoff;
234
APR_DECLARE(void) apr_sleep(apr_interval_time_t t)
240
#elif defined(NETWARE)
244
tv.tv_usec = t % APR_USEC_PER_SEC;
245
tv.tv_sec = t / APR_USEC_PER_SEC;
246
select(0, NULL, NULL, NULL, &tv);
251
APR_DECLARE(apr_status_t) apr_os2_time_to_apr_time(apr_time_t *result,
257
memset(&tmpdate, 0, sizeof(tmpdate));
258
tmpdate.tm_hour = os2time.hours;
259
tmpdate.tm_min = os2time.minutes;
260
tmpdate.tm_sec = os2time.twosecs * 2;
262
tmpdate.tm_mday = os2date.day;
263
tmpdate.tm_mon = os2date.month - 1;
264
tmpdate.tm_year = os2date.year + 80;
265
tmpdate.tm_isdst = -1;
267
*result = mktime(&tmpdate) * APR_USEC_PER_SEC;
271
APR_DECLARE(apr_status_t) apr_apr_time_to_os2_time(FDATE *os2date,
275
time_t ansitime = aprtime / APR_USEC_PER_SEC;
277
lt = localtime(&ansitime);
278
os2time->hours = lt->tm_hour;
279
os2time->minutes = lt->tm_min;
280
os2time->twosecs = lt->tm_sec / 2;
282
os2date->day = lt->tm_mday;
283
os2date->month = lt->tm_mon + 1;
284
os2date->year = lt->tm_year - 80;
290
APR_DECLARE(void) apr_netware_setup_time(void)
293
server_gmt_offset = -TZONE;
296
APR_DECLARE(void) apr_unix_setup_time(void)
298
#ifdef NO_GMTOFF_IN_STRUCT_TM
299
/* Precompute the offset from GMT on systems where it's not
302
Note: This offset is normalized to be independent of daylight
303
savings time; if the calculation happens to be done in a
304
time/place where a daylight savings adjustment is in effect,
305
the returned offset has the same value that it would have
306
in the same location if daylight savings were not in effect.
307
The reason for this is that the returned offset can be
308
applied to a past or future timestamp in explode_time(),
309
so the DST adjustment obtained from the current time won't
310
necessarily be applicable.
312
mktime() is the inverse of localtime(); so, presumably,
313
passing in a struct tm made by gmtime() let's us calculate
314
the true GMT offset. However, there's a catch: if daylight
315
savings is in effect, gmtime()will set the tm_isdst field
316
and confuse mktime() into returning a time that's offset
317
by one hour. In that case, we must adjust the calculated GMT
326
gettimeofday(&now, NULL);
330
#if APR_HAS_THREADS && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
335
t.tm_isdst = 0; /* we know this GMT time isn't daylight-savings */
337
server_gmt_offset = (apr_int32_t) difftime(t1, t2);
338
#endif /* NO_GMTOFF_IN_STRUCT_TM */
343
/* A noop on all known Unix implementations */
344
APR_DECLARE(void) apr_time_clock_hires(apr_pool_t *p)