home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Tcl-Tk 8.0 / Pre-installed version / tcl8.0 / win / tclWinTime.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-15  |  7.8 KB  |  374 lines  |  [TEXT/CWIE]

  1. /* 
  2.  * tclWinTime.c --
  3.  *
  4.  *    Contains Windows specific versions of Tcl functions that
  5.  *    obtain time values from the operating system.
  6.  *
  7.  * Copyright 1995 by Sun Microsystems, Inc.
  8.  *
  9.  * See the file "license.terms" for information on usage and redistribution
  10.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  11.  *
  12.  * SCCS: @(#) tclWinTime.c 1.6 97/04/14 17:25:56
  13.  */
  14.  
  15. #include "tclInt.h"
  16. #include "tclPort.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. /*
  36.  * Declarations for functions defined later in this file.
  37.  */
  38.  
  39. static struct tm *    ComputeGMT _ANSI_ARGS_((const time_t *tp));
  40.  
  41. /*
  42.  *----------------------------------------------------------------------
  43.  *
  44.  * TclpGetSeconds --
  45.  *
  46.  *    This procedure returns the number of seconds from the epoch.
  47.  *    On most Unix systems the epoch is Midnight Jan 1, 1970 GMT.
  48.  *
  49.  * Results:
  50.  *    Number of seconds from the epoch.
  51.  *
  52.  * Side effects:
  53.  *    None.
  54.  *
  55.  *----------------------------------------------------------------------
  56.  */
  57.  
  58. unsigned long
  59. TclpGetSeconds()
  60. {
  61.     return (unsigned long) time((time_t *) NULL);
  62. }
  63.  
  64. /*
  65.  *----------------------------------------------------------------------
  66.  *
  67.  * TclpGetClicks --
  68.  *
  69.  *    This procedure returns a value that represents the highest
  70.  *    resolution clock available on the system.  There are no
  71.  *    guarantees on what the resolution will be.  In Tcl we will
  72.  *    call this value a "click".  The start time is also system
  73.  *    dependant.
  74.  *
  75.  * Results:
  76.  *    Number of clicks from some start time.
  77.  *
  78.  * Side effects:
  79.  *    None.
  80.  *
  81.  *----------------------------------------------------------------------
  82.  */
  83.  
  84. unsigned long
  85. TclpGetClicks()
  86. {
  87.     return GetTickCount();
  88. }
  89.  
  90. /*
  91.  *----------------------------------------------------------------------
  92.  *
  93.  * TclpGetTimeZone --
  94.  *
  95.  *    Determines the current timezone.  The method varies wildly
  96.  *    between different Platform implementations, so its hidden in
  97.  *    this function.
  98.  *
  99.  * Results:
  100.  *    Minutes west of GMT.
  101.  *
  102.  * Side effects:
  103.  *    None.
  104.  *
  105.  *----------------------------------------------------------------------
  106.  */
  107.  
  108. int
  109. TclpGetTimeZone (currentTime)
  110.     unsigned long  currentTime;
  111. {
  112.     int timeZone;
  113.  
  114.     tzset();
  115.     timeZone = _timezone / 60;
  116.  
  117.     return timeZone;
  118. }
  119.  
  120. /*
  121.  *----------------------------------------------------------------------
  122.  *
  123.  * TclpGetTime --
  124.  *
  125.  *    Gets the current system time in seconds and microseconds
  126.  *    since the beginning of the epoch: 00:00 UCT, January 1, 1970.
  127.  *
  128.  * Results:
  129.  *    Returns the current time in timePtr.
  130.  *
  131.  * Side effects:
  132.  *    None.
  133.  *
  134.  *----------------------------------------------------------------------
  135.  */
  136.  
  137. void
  138. TclpGetTime(timePtr)
  139.     Tcl_Time *timePtr;        /* Location to store time information. */
  140. {
  141.     struct timeb t;
  142.  
  143.     ftime(&t);
  144.     timePtr->sec = t.time;
  145.     timePtr->usec = t.millitm * 1000;
  146. }
  147.  
  148. /*
  149.  *----------------------------------------------------------------------
  150.  *
  151.  * TclpGetTZName --
  152.  *
  153.  *    Gets the current timezone string.
  154.  *
  155.  * Results:
  156.  *    Returns a pointer to a static string, or NULL on failure.
  157.  *
  158.  * Side effects:
  159.  *    None.
  160.  *
  161.  *----------------------------------------------------------------------
  162.  */
  163.  
  164. char *
  165. TclpGetTZName()
  166. {
  167.     tzset();
  168.     if (_daylight && _tzname[1] != NULL) {
  169.     return _tzname[1];
  170.     } else {
  171.     return _tzname[0];
  172.     }
  173. }
  174.  
  175. /*
  176.  *----------------------------------------------------------------------
  177.  *
  178.  * TclpGetDate --
  179.  *
  180.  *    This function converts between seconds and struct tm.  If
  181.  *    useGMT is true, then the returned date will be in Greenwich
  182.  *    Mean Time (GMT).  Otherwise, it will be in the local time zone.
  183.  *
  184.  * Results:
  185.  *    Returns a static tm structure.
  186.  *
  187.  * Side effects:
  188.  *    None.
  189.  *
  190.  *----------------------------------------------------------------------
  191.  */
  192.  
  193. struct tm *
  194. TclpGetDate(tp, useGMT)
  195.     const time_t *tp;
  196.     int useGMT;
  197. {
  198.     struct tm *tmPtr;
  199.     long time;
  200.  
  201.     if (!useGMT) {
  202.     tzset();
  203.  
  204.     /*
  205.      * If we are in the valid range, let the C run-time library
  206.      * handle it.  Otherwise we need to fake it.  Note that this
  207.      * algorithm ignores daylight savings time before the epoch.
  208.      */
  209.  
  210.     time = *tp - _timezone;
  211.     if (time >= 0) {
  212.         return localtime(tp);
  213.     }
  214.     
  215.     /*
  216.      * If we aren't near to overflowing the long, just add the bias and
  217.      * use the normal calculation.  Otherwise we will need to adjust
  218.      * the result at the end.
  219.      */
  220.  
  221.     if (*tp < (LONG_MAX - 2 * SECSPERDAY)
  222.         && *tp > (LONG_MIN + 2 * SECSPERDAY)) {
  223.         tmPtr = ComputeGMT(&time);
  224.     } else {
  225.         tmPtr = ComputeGMT(tp);
  226.  
  227.         tzset();
  228.  
  229.         /*
  230.          * Add the bias directly to the tm structure to avoid overflow.
  231.          * Propagate seconds overflow into minutes, hours and days.
  232.          */
  233.  
  234.         time = tmPtr->tm_sec - _timezone;
  235.         tmPtr->tm_sec = (int)(time % 60);
  236.         if (tmPtr->tm_sec < 0) {
  237.         tmPtr->tm_sec += 60;
  238.         time -= 60;
  239.         }
  240.     
  241.         time = tmPtr->tm_min + time/60;
  242.         tmPtr->tm_min = (int)(time % 60);
  243.         if (tmPtr->tm_min < 0) {
  244.         tmPtr->tm_min += 60;
  245.         time -= 60;
  246.         }
  247.  
  248.         time = tmPtr->tm_hour + time/60;
  249.         tmPtr->tm_hour = (int)(time % 24);
  250.         if (tmPtr->tm_hour < 0) {
  251.         tmPtr->tm_hour += 24;
  252.         time -= 24;
  253.         }
  254.  
  255.         time /= 24;
  256.         tmPtr->tm_mday += time;
  257.         tmPtr->tm_yday += time;
  258.         tmPtr->tm_wday = (tmPtr->tm_wday + time) % 7;
  259.     }
  260.     } else {
  261.     tmPtr = ComputeGMT(tp);
  262.     }
  263.     return tmPtr;
  264. }
  265.  
  266. /*
  267.  *----------------------------------------------------------------------
  268.  *
  269.  * ComputeGMT --
  270.  *
  271.  *    This function computes GMT given the number of seconds since
  272.  *    the epoch (midnight Jan 1 1970).
  273.  *
  274.  * Results:
  275.  *    Returns a statically allocated struct tm.
  276.  *
  277.  * Side effects:
  278.  *    Updates the values of the static struct tm.
  279.  *
  280.  *----------------------------------------------------------------------
  281.  */
  282.  
  283. static struct tm *
  284. ComputeGMT(tp)
  285.     const time_t *tp;
  286. {
  287.     static struct tm tm;      /* This should be allocated per thread.*/
  288.     long tmp, rem;
  289.     int isLeap;
  290.     int *days;
  291.  
  292.     /*
  293.      * Compute the 4 year span containing the specified time.
  294.      */
  295.  
  296.     tmp = *tp / SECSPER4YEAR;
  297.     rem = *tp % SECSPER4YEAR;
  298.  
  299.     /*
  300.      * Correct for weird mod semantics so the remainder is always positive.
  301.      */
  302.  
  303.     if (rem < 0) {
  304.     tmp--;
  305.     rem += SECSPER4YEAR;
  306.     }
  307.  
  308.     /*
  309.      * Compute the year after 1900 by taking the 4 year span and adjusting
  310.      * for the remainder.  This works because 2000 is a leap year, and
  311.      * 1900/2100 are out of the range.
  312.      */
  313.  
  314.     tmp = (tmp * 4) + 70;
  315.     isLeap = 0;
  316.     if (rem >= SECSPERYEAR) {              /* 1971, etc. */
  317.     tmp++;
  318.     rem -= SECSPERYEAR;
  319.     if (rem >= SECSPERYEAR) {          /* 1972, etc. */
  320.         tmp++;
  321.         rem -= SECSPERYEAR;
  322.         if (rem >= SECSPERYEAR + SECSPERDAY) { /* 1973, etc. */
  323.         tmp++;
  324.         rem -= SECSPERYEAR + SECSPERDAY;
  325.         } else {
  326.         isLeap = 1;
  327.         }
  328.     }
  329.     }
  330.     tm.tm_year = tmp;
  331.  
  332.     /*
  333.      * Compute the day of year and leave the seconds in the current day in
  334.      * the remainder.
  335.      */
  336.  
  337.     tm.tm_yday = rem / SECSPERDAY;
  338.     rem %= SECSPERDAY;
  339.     
  340.     /*
  341.      * Compute the time of day.
  342.      */
  343.  
  344.     tm.tm_hour = rem / 3600;
  345.     rem %= 3600;
  346.     tm.tm_min = rem / 60;
  347.     tm.tm_sec = rem % 60;
  348.  
  349.     /*
  350.      * Compute the month and day of month.
  351.      */
  352.  
  353.     days = (isLeap) ? leapDays : normalDays;
  354.     for (tmp = 1; days[tmp] < tm.tm_yday; tmp++) {
  355.     }
  356.     tm.tm_mon = --tmp;
  357.     tm.tm_mday = tm.tm_yday - days[tmp];
  358.  
  359.     /*
  360.      * Compute day of week.  Epoch started on a Thursday.
  361.      */
  362.  
  363.     tm.tm_wday = (*tp / SECSPERDAY) + 4;
  364.     if ((*tp % SECSPERDAY) < 0) {
  365.     tm.tm_wday--;
  366.     }
  367.     tm.tm_wday %= 7;
  368.     if (tm.tm_wday < 0) {
  369.     tm.tm_wday += 7;
  370.     }
  371.  
  372.     return &tm;
  373. }
  374.