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

Diff of /projs/ets/trunk/src/c_tcl_base_7_5_w_mods/tclwintime.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.67  
changed lines
  Added in v.71

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25