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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25