/[dtapublic]/projs/trunk/shared_source/c_tcl_base_7_5_w_mods/tclwintime.c
ViewVC logotype

Contents of /projs/trunk/shared_source/c_tcl_base_7_5_w_mods/tclwintime.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 67 - (show annotations) (download)
Mon Oct 31 00:57:34 2016 UTC (6 years, 2 months ago) by dashley
File MIME type: text/plain
File size: 10461 byte(s)
Header and footer cleanup.
1 /* $Header$ */
2 /*
3 * tclWinTime.c --
4 *
5 * Contains Windows specific versions of Tcl functions that
6 * obtain time values from the operating system.
7 *
8 * Copyright 1995-1998 by Sun Microsystems, Inc.
9 *
10 * See the file "license.terms" for information on usage and redistribution
11 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12 *
13 * RCS: @(#) $Id: tclwintime.c,v 1.1.1.1 2001/06/13 04:50:48 dtashley Exp $
14 */
15
16 #include "tclWinInt.h"
17
18 #define SECSPERDAY (60L * 60L * 24L)
19 #define SECSPERYEAR (SECSPERDAY * 365L)
20 #define SECSPER4YEAR (SECSPERYEAR * 4L + SECSPERDAY)
21
22 /*
23 * The following arrays contain the day of year for the last day of
24 * each month, where index 1 is January.
25 */
26
27 static int normalDays[] = {
28 -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364
29 };
30
31 static int leapDays[] = {
32 -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
33 };
34
35 typedef struct ThreadSpecificData {
36 char tzName[64]; /* Time zone name */
37 struct tm tm; /* time information */
38 } ThreadSpecificData;
39 static Tcl_ThreadDataKey dataKey;
40
41 /*
42 * Declarations for functions defined later in this file.
43 */
44
45 static struct tm * ComputeGMT _ANSI_ARGS_((const time_t *tp));
46
47 /*
48 *----------------------------------------------------------------------
49 *
50 * TclpGetSeconds --
51 *
52 * This procedure returns the number of seconds from the epoch.
53 * On most Unix systems the epoch is Midnight Jan 1, 1970 GMT.
54 *
55 * Results:
56 * Number of seconds from the epoch.
57 *
58 * Side effects:
59 * None.
60 *
61 *----------------------------------------------------------------------
62 */
63
64 unsigned long
65 TclpGetSeconds()
66 {
67 return (unsigned long) time((time_t *) NULL);
68 }
69
70 /*
71 *----------------------------------------------------------------------
72 *
73 * TclpGetClicks --
74 *
75 * This procedure returns a value that represents the highest
76 * resolution clock available on the system. There are no
77 * guarantees on what the resolution will be. In Tcl we will
78 * call this value a "click". The start time is also system
79 * dependant.
80 *
81 * Results:
82 * Number of clicks from some start time.
83 *
84 * Side effects:
85 * None.
86 *
87 *----------------------------------------------------------------------
88 */
89
90 unsigned long
91 TclpGetClicks()
92 {
93 return GetTickCount();
94 }
95
96 /*
97 *----------------------------------------------------------------------
98 *
99 * TclpGetTimeZone --
100 *
101 * Determines the current timezone. The method varies wildly
102 * between different Platform implementations, so its hidden in
103 * this function.
104 *
105 * Results:
106 * Minutes west of GMT.
107 *
108 * Side effects:
109 * None.
110 *
111 *----------------------------------------------------------------------
112 */
113
114 int
115 TclpGetTimeZone (currentTime)
116 unsigned long currentTime;
117 {
118 int timeZone;
119
120 tzset();
121 timeZone = _timezone / 60;
122
123 return timeZone;
124 }
125
126 /*
127 *----------------------------------------------------------------------
128 *
129 * TclpGetTime --
130 *
131 * Gets the current system time in seconds and microseconds
132 * since the beginning of the epoch: 00:00 UCT, January 1, 1970.
133 *
134 * Results:
135 * Returns the current time in timePtr.
136 *
137 * Side effects:
138 * None.
139 *
140 *----------------------------------------------------------------------
141 */
142
143 void
144 TclpGetTime(timePtr)
145 Tcl_Time *timePtr; /* Location to store time information. */
146 {
147 struct timeb t;
148
149 ftime(&t);
150 timePtr->sec = t.time;
151 timePtr->usec = t.millitm * 1000;
152 }
153
154 /*
155 *----------------------------------------------------------------------
156 *
157 * TclpGetTZName --
158 *
159 * Gets the current timezone string.
160 *
161 * Results:
162 * Returns a pointer to a static string, or NULL on failure.
163 *
164 * Side effects:
165 * None.
166 *
167 *----------------------------------------------------------------------
168 */
169
170 char *
171 TclpGetTZName(int dst)
172 {
173 int len;
174 char *zone, *p;
175 TIME_ZONE_INFORMATION tz;
176 Tcl_Encoding encoding;
177 ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
178 char *name = tsdPtr->tzName;
179
180 /*
181 * tzset() under Borland doesn't seem to set up tzname[] at all.
182 * tzset() under MSVC has the following weird observed behavior:
183 * First time we call "clock format [clock seconds] -format %Z -gmt 1"
184 * we get "GMT", but on all subsequent calls we get the current time
185 * zone string, even though env(TZ) is GMT and the variable _timezone
186 * is 0.
187 */
188
189 name[0] = '\0';
190
191 zone = getenv("TZ");
192 if (zone != NULL) {
193 /*
194 * TZ is of form "NST-4:30NDT", where "NST" would be the
195 * name of the standard time zone for this area, "-4:30" is
196 * the offset from GMT in hours, and "NDT is the name of
197 * the daylight savings time zone in this area. The offset
198 * and DST strings are optional.
199 */
200
201 len = strlen(zone);
202 if (len > 3) {
203 len = 3;
204 }
205 if (dst != 0) {
206 /*
207 * Skip the offset string and get the DST string.
208 */
209
210 p = zone + len;
211 p += strspn(p, "+-:0123456789");
212 if (*p != '\0') {
213 zone = p;
214 len = strlen(zone);
215 if (len > 3) {
216 len = 3;
217 }
218 }
219 }
220 Tcl_ExternalToUtf(NULL, NULL, zone, len, 0, NULL, name,
221 sizeof(tsdPtr->tzName), NULL, NULL, NULL);
222 }
223 if (name[0] == '\0') {
224 if (GetTimeZoneInformation(&tz) == TIME_ZONE_ID_UNKNOWN) {
225 /*
226 * MSDN: On NT this is returned if DST is not used in
227 * the current TZ
228 */
229 dst = 0;
230 }
231 encoding = Tcl_GetEncoding(NULL, "unicode");
232 Tcl_ExternalToUtf(NULL, encoding,
233 (char *) ((dst) ? tz.DaylightName : tz.StandardName), -1,
234 0, NULL, name, sizeof(tsdPtr->tzName), NULL, NULL, NULL);
235 Tcl_FreeEncoding(encoding);
236 }
237 return name;
238 }
239
240 /*
241 *----------------------------------------------------------------------
242 *
243 * TclpGetDate --
244 *
245 * This function converts between seconds and struct tm. If
246 * useGMT is true, then the returned date will be in Greenwich
247 * Mean Time (GMT). Otherwise, it will be in the local time zone.
248 *
249 * Results:
250 * Returns a static tm structure.
251 *
252 * Side effects:
253 * None.
254 *
255 *----------------------------------------------------------------------
256 */
257
258 struct tm *
259 TclpGetDate(t, useGMT)
260 TclpTime_t t;
261 int useGMT;
262 {
263 const time_t *tp = (const time_t *) t;
264 struct tm *tmPtr;
265 long time;
266
267 if (!useGMT) {
268 tzset();
269
270 /*
271 * If we are in the valid range, let the C run-time library
272 * handle it. Otherwise we need to fake it. Note that this
273 * algorithm ignores daylight savings time before the epoch.
274 */
275
276 if (*tp >= 0) {
277 return localtime(tp);
278 }
279
280 time = *tp - _timezone;
281
282 /*
283 * If we aren't near to overflowing the long, just add the bias and
284 * use the normal calculation. Otherwise we will need to adjust
285 * the result at the end.
286 */
287
288 if (*tp < (LONG_MAX - 2 * SECSPERDAY)
289 && *tp > (LONG_MIN + 2 * SECSPERDAY)) {
290 tmPtr = ComputeGMT(&time);
291 } else {
292 tmPtr = ComputeGMT(tp);
293
294 tzset();
295
296 /*
297 * Add the bias directly to the tm structure to avoid overflow.
298 * Propagate seconds overflow into minutes, hours and days.
299 */
300
301 time = tmPtr->tm_sec - _timezone;
302 tmPtr->tm_sec = (int)(time % 60);
303 if (tmPtr->tm_sec < 0) {
304 tmPtr->tm_sec += 60;
305 time -= 60;
306 }
307
308 time = tmPtr->tm_min + time/60;
309 tmPtr->tm_min = (int)(time % 60);
310 if (tmPtr->tm_min < 0) {
311 tmPtr->tm_min += 60;
312 time -= 60;
313 }
314
315 time = tmPtr->tm_hour + time/60;
316 tmPtr->tm_hour = (int)(time % 24);
317 if (tmPtr->tm_hour < 0) {
318 tmPtr->tm_hour += 24;
319 time -= 24;
320 }
321
322 time /= 24;
323 tmPtr->tm_mday += time;
324 tmPtr->tm_yday += time;
325 tmPtr->tm_wday = (tmPtr->tm_wday + time) % 7;
326 }
327 } else {
328 tmPtr = ComputeGMT(tp);
329 }
330 return tmPtr;
331 }
332
333 /*
334 *----------------------------------------------------------------------
335 *
336 * ComputeGMT --
337 *
338 * This function computes GMT given the number of seconds since
339 * the epoch (midnight Jan 1 1970).
340 *
341 * Results:
342 * Returns a (per thread) statically allocated struct tm.
343 *
344 * Side effects:
345 * Updates the values of the static struct tm.
346 *
347 *----------------------------------------------------------------------
348 */
349
350 static struct tm *
351 ComputeGMT(tp)
352 const time_t *tp;
353 {
354 struct tm *tmPtr;
355 long tmp, rem;
356 int isLeap;
357 int *days;
358 ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
359
360 tmPtr = &tsdPtr->tm;
361
362 /*
363 * Compute the 4 year span containing the specified time.
364 */
365
366 tmp = *tp / SECSPER4YEAR;
367 rem = *tp % SECSPER4YEAR;
368
369 /*
370 * Correct for weird mod semantics so the remainder is always positive.
371 */
372
373 if (rem < 0) {
374 tmp--;
375 rem += SECSPER4YEAR;
376 }
377
378 /*
379 * Compute the year after 1900 by taking the 4 year span and adjusting
380 * for the remainder. This works because 2000 is a leap year, and
381 * 1900/2100 are out of the range.
382 */
383
384 tmp = (tmp * 4) + 70;
385 isLeap = 0;
386 if (rem >= SECSPERYEAR) { /* 1971, etc. */
387 tmp++;
388 rem -= SECSPERYEAR;
389 if (rem >= SECSPERYEAR) { /* 1972, etc. */
390 tmp++;
391 rem -= SECSPERYEAR;
392 if (rem >= SECSPERYEAR + SECSPERDAY) { /* 1973, etc. */
393 tmp++;
394 rem -= SECSPERYEAR + SECSPERDAY;
395 } else {
396 isLeap = 1;
397 }
398 }
399 }
400 tmPtr->tm_year = tmp;
401
402 /*
403 * Compute the day of year and leave the seconds in the current day in
404 * the remainder.
405 */
406
407 tmPtr->tm_yday = rem / SECSPERDAY;
408 rem %= SECSPERDAY;
409
410 /*
411 * Compute the time of day.
412 */
413
414 tmPtr->tm_hour = rem / 3600;
415 rem %= 3600;
416 tmPtr->tm_min = rem / 60;
417 tmPtr->tm_sec = rem % 60;
418
419 /*
420 * Compute the month and day of month.
421 */
422
423 days = (isLeap) ? leapDays : normalDays;
424 for (tmp = 1; days[tmp] < tmPtr->tm_yday; tmp++) {
425 }
426 tmPtr->tm_mon = --tmp;
427 tmPtr->tm_mday = tmPtr->tm_yday - days[tmp];
428
429 /*
430 * Compute day of week. Epoch started on a Thursday.
431 */
432
433 tmPtr->tm_wday = (*tp / SECSPERDAY) + 4;
434 if ((*tp % SECSPERDAY) < 0) {
435 tmPtr->tm_wday--;
436 }
437 tmPtr->tm_wday %= 7;
438 if (tmPtr->tm_wday < 0) {
439 tmPtr->tm_wday += 7;
440 }
441
442 return tmPtr;
443 }
444
445 /* End of tclwintime.c */

Properties

Name Value
svn:keywords Header

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25