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

Annotation of /projs/dtats/trunk/shared_source/c_tcl_base_7_5_w_mods/tclwintime.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 67 - (hide annotations) (download)
Mon Oct 31 00:57:34 2016 UTC (7 years, 8 months ago) by dashley
Original Path: projs/trunk/shared_source/c_tcl_base_7_5_w_mods/tclwintime.c
File MIME type: text/plain
File size: 10461 byte(s)
Header and footer cleanup.
1 dashley 64 /* $Header$ */
2 dashley 25 /*
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 dashley 67 /* End of tclwintime.c */

Properties

Name Value
svn:keywords Header

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25