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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 25 - (hide annotations) (download)
Sat Oct 8 06:43:03 2016 UTC (7 years, 8 months ago) by dashley
Original Path: sf_code/esrgpcpj/shared/tcl_base/tclwintime.c
File MIME type: text/plain
File size: 10793 byte(s)
Initial commit.
1 dashley 25 /* $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