time.c
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 23k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. /***
  2. *time.c - get current system time
  3. *
  4. *       Copyright (c) 1989-1996, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *       defines time() - gets the current system time and converts it to
  8. *                        internal (time_t) format time.
  9. *
  10. *******************************************************************************/
  11. #include <cruntime.h>
  12. #include <time.h>
  13. #include <internal.h>
  14. #include <windows.h>
  15. /*
  16.  * Cache holding the last time (GMT) for which the Daylight time status was
  17.  * determined by an API call.
  18.  */
  19. static SYSTEMTIME gmt_cache;
  20. /*
  21.  * Three values of dstflag_cache and dstflag (local variable in code
  22.  * below)
  23.  */
  24. #define DAYLIGHT_TIME   1
  25. #define STANDARD_TIME   0
  26. #define UNKNOWN_TIME    -1
  27. // From ctime.h
  28. #define _DAY_SEC           (24L * 60L * 60L)    /* secs in a day */
  29. #define _YEAR_SEC          (365L * _DAY_SEC)    /* secs in a year */
  30. #define _FOUR_YEAR_SEC     (1461L * _DAY_SEC)   /* secs in a 4 year interval */
  31. #define _DEC_SEC           315532800L           /* secs in 1970-1979 */
  32. #define _BASE_YEAR         70L                  /* 1970 is the base year */
  33. #define _BASE_DOW          4                    /* 01-01-70 was a Thursday */
  34. #define _LEAP_YEAR_ADJUST  17L                  /* Leap years 1900 - 1970 */
  35. #define _MAX_YEAR          138L                 /* 2038 is the max year */
  36. static int dstflag_cache;
  37. /*
  38.  * Number of milliseconds in one day
  39.  */
  40. #define DAY_MILLISEC    (24L * 60L * 60L * 1000L)
  41. /*
  42.  * The macro below is valid for years between 1901 and 2099, which easily
  43.  * includes all years representable by the current implementation of time_t.
  44.  */
  45. #define IS_LEAP_YEAR(year)  ( (year & 3) == 0 )
  46. /*
  47.  * Pointer to a saved copy of the TZ value obtained in the previous call
  48.  * to tzset() set (if any).
  49.  */
  50. static char * lastTZ = NULL;
  51. static int tzapiused;
  52. static TIME_ZONE_INFORMATION tzinfo;
  53. /*
  54.  * Structure used to represent DST transition date/times.
  55.  */
  56. typedef struct {
  57.         int  yr;        /* year of interest */
  58.         int  yd;        /* day of year */
  59.         long ms;        /* milli-seconds in the day */
  60.         } transitiondate;
  61. /*
  62.  * DST start and end structs.
  63.  */
  64. static transitiondate dststart = { -1, 0, 0L };
  65. static transitiondate dstend   = { -1, 0, 0L };
  66. // From timeset.c
  67. long _timezone = 8 * 3600L; /* Pacific Time Zone */
  68. int _daylight = 1;          /* Daylight Saving Time (DST) in timezone */
  69. long _dstbias = -3600L;     /* DST offset in seconds */
  70. /* note that NT Posix's TZNAME_MAX is only 10 */
  71. static char tzstd[64] = { "PST" };
  72. static char tzdst[64] = { "PDT" };
  73. char *_tzname[2] = { tzstd, tzdst };
  74. int _lpdays[] = {
  75.         -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
  76. };
  77. int _days[] = {
  78.         -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364
  79. };
  80. /*  Day names must be Three character abbreviations strung together */
  81. const char __dnames[] = {
  82.         "SunMonTueWedThuFriSat"
  83. };
  84. /*  Month names must be Three character abbreviations strung together */
  85. const char __mnames[] = {
  86.         "JanFebMarAprMayJunJulAugSepOctNovDec"
  87. };
  88. /***
  89. *static void cvtdate( trantype, datetype, year, month, week, dayofweek,
  90. *                     date, hour, min, second, millisec ) - convert
  91. *       transition date format
  92. *
  93. *Purpose:
  94. *       Convert the format of a transition date specification to a value of
  95. *       a transitiondate structure.
  96. *
  97. *Entry:
  98. *       int trantype    - 1, if it is the start of DST
  99. *                         0, if is the end of DST (in which case the date is
  100. *                            is a DST date)
  101. *       int datetype    - 1, if a day-in-month format is specified.
  102. *                         0, if an absolute date is specified.
  103. *       int year        - year for which the date is being converted (70 ==
  104. *                         1970)
  105. *       int month       - month (0 == January)
  106. *       int week        - week of month, if datetype == 1 (note that 5== last
  107. *                         week of month),
  108. *                         0, otherwise.
  109. *       int dayofweek   - day of week (0 == Sunday), if datetype == 1.
  110. *                         0, otherwise.
  111. *       int date        - date of month (1 - 31)
  112. *       int hour        - hours (0 - 23)
  113. *       int min         - minutes (0 - 59)
  114. *       int sec         - seconds (0 - 59)
  115. *       int msec        - milliseconds (0 - 999)
  116. *
  117. *Exit:
  118. *       dststart or dstend is filled in with the converted date.
  119. *
  120. *******************************************************************************/
  121. static void __cdecl cvtdate (
  122.         int trantype,
  123.         int datetype,
  124.         int year,
  125.         int month,
  126.         int week,
  127.         int dayofweek,
  128.         int date,
  129.         int hour,
  130.         int min,
  131.         int sec,
  132.         int msec
  133.         )
  134. {
  135.         int yearday;
  136.         int monthdow;
  137.         if ( datetype == 1 ) {
  138.             /*
  139.              * Transition day specified in day-in-month format.
  140.              */
  141.             /*
  142.              * Figure the year-day of the start of the month.
  143.              */
  144.             yearday = 1 + (IS_LEAP_YEAR(year) ? _lpdays[month - 1] :
  145.                       _days[month - 1]);
  146.             /*
  147.              * Figure the day of the week of the start of the month.
  148.              */
  149.             monthdow = (yearday + ((year - 70) * 365) + ((year - 1) >> 2) -
  150.                         _LEAP_YEAR_ADJUST + _BASE_DOW) % 7;
  151.             /*
  152.              * Figure the year-day of the transition date
  153.              */
  154.             if ( monthdow < dayofweek )
  155.                 yearday += (dayofweek - monthdow) + (week - 1) * 7;
  156.             else
  157.                 yearday += (dayofweek - monthdow) + week * 7;
  158.             /*
  159.              * May have to adjust the calculation above if week == 5 (meaning
  160.              * the last instance of the day in the month). Check if year falls
  161.              * beyond after month and adjust accordingly.
  162.              */
  163.             if ( (week == 5) &&
  164.                  (yearday > (IS_LEAP_YEAR(year) ? _lpdays[month] :
  165.                              _days[month])) )
  166.             {
  167.                 yearday -= 7;
  168.             }
  169.         }
  170.         else {
  171.             /*
  172.              * Transition day specified as an absolute day
  173.              */
  174.             yearday = IS_LEAP_YEAR(year) ? _lpdays[month - 1] :
  175.                       _days[month - 1];
  176.             yearday += date;
  177.         }
  178.         if ( trantype == 1 ) {
  179.             /*
  180.              * Converted date was for the start of DST
  181.              */
  182.             dststart.yd = yearday;
  183.             dststart.ms = (long)msec +
  184.                           (1000L * (sec + 60L * (min + 60L * hour)));
  185.             /*
  186.              * Set year field of dststart so that unnecessary calls to
  187.              * cvtdate() may be avoided.
  188.              */
  189.             dststart.yr = year;
  190.         }
  191.         else {
  192.             /*
  193.              * Converted date was for the end of DST
  194.              */
  195.             dstend.yd = yearday;
  196.             dstend.ms = (long)msec +
  197.                               (1000L * (sec + 60L * (min + 60L * hour)));
  198.             /*
  199.              * The converted date is still a DST date. Must convert to a
  200.              * standard (local) date while being careful the millisecond field
  201.              * does not overflow or underflow.
  202.              */
  203.             if ( (dstend.ms += (_dstbias * 1000L)) < 0 ) {
  204.                 dstend.ms += DAY_MILLISEC;
  205.                 dstend.ms--;
  206.             }
  207.             else if ( dstend.ms >= DAY_MILLISEC ) {
  208.                 dstend.ms -= DAY_MILLISEC;
  209.                 dstend.ms++;
  210.             }
  211.             /*
  212.              * Set year field of dstend so that unnecessary calls to cvtdate()
  213.              * may be avoided.
  214.              */
  215.             dstend.yr = year;
  216.         }
  217.         return;
  218. }
  219. /***
  220. *int _isindst(tb) - determine if broken-down time falls in DST
  221. *
  222. *Purpose:
  223. *       Determine if the given broken-down time falls within daylight saving
  224. *       time (DST). The DST rules are either obtained from Win32 (tzapiused !=
  225. *       TRUE) or assumed to be USA rules, post 1986.
  226. *
  227. *       If the DST rules are obtained from Win32's GetTimeZoneInformation API,
  228. *       the transition dates to/from DST can be specified in either of two
  229. *       formats. First, a day-in-month format, similar to the way USA rules
  230. *       are specified, can be used. The transition date is given as the n-th
  231. *       occurence of a specified day of the week in a specified month. Second,
  232. *       an absolute date can be specified. The two cases are distinguished by
  233. *       the value of wYear field in the SYSTEMTIME structure (0 denotes a
  234. *       day-in-month format).
  235. *
  236. *       USA rules for DST are that a time is in DST iff it is on or after
  237. *       02:00 on the first Sunday in April, and before 01:00 on the last
  238. *       Sunday in October.
  239. *
  240. *Entry:
  241. *       struct tm *tb - structure holding broken-down time value
  242. *
  243. *Exit:
  244. *       1, if time represented is in DST
  245. *       0, otherwise
  246. *
  247. *******************************************************************************/
  248. int __cdecl _isindst (
  249.         struct tm *tb
  250.         )
  251. #ifdef _MTTIME
  252. {
  253.         int retval;
  254.         _mlock( _TIME_LOCK );
  255.         retval = _isindst_lk( tb );
  256.         _munlock( _TIME_LOCK );
  257.         return retval;
  258. }
  259. static int __cdecl _isindst_lk (
  260.         struct tm *tb
  261.         )
  262. #endif  /* _MTTIME */
  263. {
  264.         long ms;
  265.         if ( _daylight == 0 )
  266.             return 0;
  267.         /*
  268.          * Compute (recompute) the transition dates for daylight saving time
  269.          * if necessary.The yr (year) fields of dststart and dstend is
  270.          * compared to the year of interest to determine necessity.
  271.          */
  272.         if ( (tb->tm_year != dststart.yr) || (tb->tm_year != dstend.yr) ) {
  273.             if ( tzapiused ) {
  274.                 /*
  275.                  * Convert the start of daylight saving time to dststart.
  276.                  */
  277.                 if ( tzinfo.DaylightDate.wYear == 0 )
  278.                     cvtdate( 1,
  279.                              1,             /* day-in-month format */
  280.                              tb->tm_year,
  281.                              tzinfo.DaylightDate.wMonth,
  282.                              tzinfo.DaylightDate.wDay,
  283.                              tzinfo.DaylightDate.wDayOfWeek,
  284.                              0,
  285.                              tzinfo.DaylightDate.wHour,
  286.                              tzinfo.DaylightDate.wMinute,
  287.                              tzinfo.DaylightDate.wSecond,
  288.                              tzinfo.DaylightDate.wMilliseconds );
  289.                 else
  290.                     cvtdate( 1,
  291.                              0,             /* absolute date */
  292.                              tb->tm_year,
  293.                              tzinfo.DaylightDate.wMonth,
  294.                              0,
  295.                              0,
  296.                              tzinfo.DaylightDate.wDay,
  297.                              tzinfo.DaylightDate.wHour,
  298.                              tzinfo.DaylightDate.wMinute,
  299.                              tzinfo.DaylightDate.wSecond,
  300.                              tzinfo.DaylightDate.wMilliseconds );
  301.                 /*
  302.                  * Convert start of standard time to dstend.
  303.                  */
  304.                 if ( tzinfo.StandardDate.wYear == 0 )
  305.                     cvtdate( 0,
  306.                              1,             /* day-in-month format */
  307.                              tb->tm_year,
  308.                              tzinfo.StandardDate.wMonth,
  309.                              tzinfo.StandardDate.wDay,
  310.                              tzinfo.StandardDate.wDayOfWeek,
  311.                              0,
  312.                              tzinfo.StandardDate.wHour,
  313.                              tzinfo.StandardDate.wMinute,
  314.                              tzinfo.StandardDate.wSecond,
  315.                              tzinfo.StandardDate.wMilliseconds );
  316.                 else
  317.                     cvtdate( 0,
  318.                              0,             /* absolute date */
  319.                              tb->tm_year,
  320.                              tzinfo.StandardDate.wMonth,
  321.                              0,
  322.                              0,
  323.                              tzinfo.StandardDate.wDay,
  324.                              tzinfo.StandardDate.wHour,
  325.                              tzinfo.StandardDate.wMinute,
  326.                              tzinfo.StandardDate.wSecond,
  327.                              tzinfo.StandardDate.wMilliseconds );
  328.             }
  329.             else {
  330.                 /*
  331.                  * GetTimeZoneInformation API was NOT used, or failed. USA
  332.                  * daylight saving time rules are assumed.
  333.                  */
  334.                 cvtdate( 1,
  335.                          1,
  336.                          tb->tm_year,
  337.                          4,                 /* April */
  338.                          1,                 /* first... */
  339.                          0,                 /* ...Sunday */
  340.                          0,
  341.                          2,                 /* 02:00 (2 AM) */
  342.                          0,
  343.                          0,
  344.                          0 );
  345.                 cvtdate( 0,
  346.                          1,
  347.                          tb->tm_year,
  348.                          10,                /* October */
  349.                          5,                 /* last... */
  350.                          0,                 /* ...Sunday */
  351.                          0,
  352.                          2,                 /* 02:00 (2 AM) */
  353.                          0,
  354.                          0,
  355.                          0 );
  356.             }
  357.         }
  358.         /*
  359.          * Handle simple cases first.
  360.          */
  361.         if ( dststart.yd < dstend.yd ) {
  362.             /*
  363.              * Northern hemisphere ordering
  364.              */
  365.             if ( (tb->tm_yday < dststart.yd) || (tb->tm_yday > dstend.yd) )
  366.                 return 0;
  367.             if ( (tb->tm_yday > dststart.yd) && (tb->tm_yday < dstend.yd) )
  368.                 return 1;
  369.         }
  370.         else {
  371.             /*
  372.              * Southern hemisphere ordering
  373.              */
  374.             if ( (tb->tm_yday < dstend.yd) || (tb->tm_yday > dststart.yd) )
  375.                 return 1;
  376.             if ( (tb->tm_yday > dstend.yd) && (tb->tm_yday < dststart.yd) )
  377.                 return 0;
  378.         }
  379.         ms = 1000L * (tb->tm_sec + 60L * tb->tm_min + 3600L * tb->tm_hour);
  380.         if ( tb->tm_yday == dststart.yd ) {
  381.             if ( ms >= dststart.ms )
  382.                 return 1;
  383.             else
  384.                 return 0;
  385.         }
  386.         else {
  387.             /*
  388.              * tb->tm_yday == dstend.yd
  389.              */
  390.             if ( ms < dstend.ms )
  391.                 return 1;
  392.             else
  393.                 return 0;
  394.         }
  395. }
  396. /***
  397. *void tzset() - sets timezone information and calc if in daylight time
  398. *
  399. *Purpose:
  400. *       Sets the timezone information from the TZ environment variable
  401. *       and then sets _timezone, _daylight, and _tzname. If we're in daylight
  402. *       time is automatically calculated.
  403. *
  404. *Entry:
  405. *       None, reads TZ environment variable.
  406. *
  407. *Exit:
  408. *       sets _daylight, _timezone, and _tzname global vars, no return value
  409. *
  410. *Exceptions:
  411. *
  412. *******************************************************************************/
  413. void __cdecl __tzset (void)
  414. {
  415.     if ( GetTimeZoneInformation( &tzinfo ) != 0xFFFFFFFF ) {
  416.         /*
  417.          * Note that the API was used.
  418.          */
  419.         tzapiused = 1;
  420.         /*
  421.          * Derive _timezone value from Bias and StandardBias fields.
  422.          */
  423.         _timezone = tzinfo.Bias * 60L;
  424.         if ( tzinfo.StandardDate.wMonth != 0 )
  425.             _timezone += (tzinfo.StandardBias * 60L);
  426.         /*
  427.          * Check to see if there is a daylight time bias. Since the
  428.          * StandardBias has been added into _timezone, it must be
  429.          * compensated for in the value computed for _dstbias.
  430.          */
  431.         if ( (tzinfo.DaylightDate.wMonth != 0) &&
  432.              (tzinfo.DaylightBias != 0) )
  433.         {
  434.             _daylight = 1;
  435.             _dstbias = (tzinfo.DaylightBias - tzinfo.StandardBias) *
  436.                        60L;
  437.         }
  438.         else {
  439.                 _daylight = 0;
  440.             /*
  441.              * Set daylight bias to 0 because GetTimeZoneInformation
  442.              * may return TIME_ZONE_ID_DAYLIGHT even though there is
  443.              * no DST (in NT 3.51, just turn off the automatic DST
  444.              * adjust in the control panel)!
  445.              */
  446.             _dstbias = 0;
  447.         }
  448.     }
  449. }
  450. /***
  451. *time_t __loctotime_t(yr, mo, dy, hr, mn, sc, dstflag) - converts OS local
  452. *       time to internal time format (i.e., a time_t value)
  453. *
  454. *Purpose:
  455. *       Converts a local time value, obtained in a broken down format from
  456. *       the host OS, to time_t format (i.e., the number elapsed seconds since
  457. *       01-01-70, 00:00:00, UTC).
  458. *
  459. *Entry:
  460. *       int yr, mo, dy -    date
  461. *       int hr, mn, sc -    time
  462. *       int dstflag    -    1 if Daylight Time, 0 if Standard Time, -1 if
  463. *                           not specified.
  464. *
  465. *Exit:
  466. *       Returns calendar time value.
  467. *
  468. *Exceptions:
  469. *
  470. *******************************************************************************/
  471. time_t __cdecl __loctotime_t (
  472.         int yr,         /* 0 based */
  473.         int mo,         /* 1 based */
  474.         int dy,         /* 1 based */
  475.         int hr,
  476.         int mn,
  477.         int sc,
  478.         int dstflag )
  479. {
  480.         int tmpdays;
  481.         long tmptim;
  482.         struct tm tb;
  483.         /*
  484.          * Do a quick range check on the year and convert it to a delta
  485.          * off of 1900.
  486.          */
  487.         if ( ((long)(yr -= 1900) < _BASE_YEAR) || ((long)yr > _MAX_YEAR) )
  488.                 return (time_t)(-1);
  489.         /*
  490.          * Compute the number of elapsed days in the current year. Note the
  491.          * test for a leap year would fail in the year 2100, if this was in
  492.          * range (which it isn't).
  493.          */
  494.         tmpdays = dy + _days[mo - 1];
  495.         if ( !(yr & 3) && (mo > 2) )
  496.                 tmpdays++;
  497.         /*
  498.          * Compute the number of elapsed seconds since the Epoch. Note the
  499.          * computation of elapsed leap years would break down after 2100
  500.          * if such values were in range (fortunately, they aren't).
  501.          */
  502.         tmptim = /* 365 days for each year */
  503.                  (((long)yr - _BASE_YEAR) * 365L
  504.                  /* one day for each elapsed leap year */
  505.                  + (long)((yr - 1) >> 2) - _LEAP_YEAR_ADJUST
  506.                  /* number of elapsed days in yr */
  507.                  + tmpdays)
  508.                  /* convert to hours and add in hr */
  509.                  * 24L + hr;
  510.         tmptim = /* convert to minutes and add in mn */
  511.                  (tmptim * 60L + mn)
  512.                  /* convert to seconds and add in sec */
  513.                  * 60L + sc;
  514.         /*
  515.          * Account for time zone.
  516.          */
  517.         __tzset();
  518.         tmptim += _timezone;
  519.         /*
  520.          * Fill in enough fields of tb for _isindst(), then call it to
  521.          * determine DST.
  522.          */
  523.         tb.tm_yday = tmpdays;
  524.         tb.tm_year = yr;
  525.         tb.tm_mon  = mo - 1;
  526.         tb.tm_hour = hr;
  527.         if ( (dstflag == 1) || ((dstflag == -1) && _daylight &&
  528.                                 _isindst(&tb)) )
  529.                 tmptim += _dstbias;
  530.         return(tmptim);
  531. }
  532. /***
  533. *time_t time(timeptr) - Get current system time and convert to time_t value.
  534. *
  535. *Purpose:
  536. *       Gets the current date and time and stores it in internal (time_t)
  537. *       format. The time is returned and stored via the pointer passed in
  538. *       timeptr. If timeptr == NULL, the time is only returned, not stored in
  539. *       *timeptr. The internal (time_t) format is the number of seconds since
  540. *       00:00:00, Jan 1 1970 (UTC).
  541. *
  542. *       Note: We cannot use GetSystemTime since its return is ambiguous. In
  543. *       Windows NT, in return UTC. In Win32S, probably also Win32C, it
  544. *       returns local time.
  545. *
  546. *Entry:
  547. *       time_t *timeptr - pointer to long to store time in.
  548. *
  549. *Exit:
  550. *       returns the current time.
  551. *
  552. *Exceptions:
  553. *
  554. *******************************************************************************/
  555. time_t __cdecl time (
  556.         time_t *timeptr
  557.         )
  558. {
  559.         time_t tim;
  560. #ifdef _WIN32
  561.         SYSTEMTIME loct, gmt;
  562.         TIME_ZONE_INFORMATION tzinfo;
  563.         DWORD tzstate;
  564.         int dstflag;
  565.         /*
  566.          * Get local time from Win32
  567.          */
  568.         GetLocalTime( &loct );
  569.         /*
  570.          * Determine whether or not the local time is a Daylight Saving
  571.          * Time. On Windows NT, the GetTimeZoneInformation API is *VERY*
  572.          * expensive. The scheme below is intended to avoid this API call in
  573.          * many important case by caching the GMT value and dstflag.In a
  574.          * subsequent call to time(), the cached value of dstflag is used
  575.          * unless the new GMT differs from the cached value at least in the
  576.          * minutes place.
  577.          */
  578.         GetSystemTime( &gmt );
  579.         if ( (gmt.wMinute == gmt_cache.wMinute) &&
  580.              (gmt.wHour == gmt_cache.wHour) &&
  581.              (gmt.wDay == gmt_cache.wDay) &&
  582.              (gmt.wMonth == gmt_cache.wMonth) &&
  583.              (gmt.wYear == gmt_cache.wYear) )
  584.         {
  585.             dstflag = dstflag_cache;
  586.         }
  587.         else
  588.         {
  589.             if ( (tzstate = GetTimeZoneInformation( &tzinfo )) != 0xFFFFFFFF )
  590.             {
  591.                 /*
  592.                  * Must be very careful in determining whether or not DST is
  593.                  * really in effect.
  594.                  */
  595.                 if ( (tzstate == TIME_ZONE_ID_DAYLIGHT) &&
  596.                      (tzinfo.DaylightDate.wMonth != 0) &&
  597.                      (tzinfo.DaylightBias != 0) )
  598.                     dstflag = DAYLIGHT_TIME;
  599.                 else
  600.                     /*
  601.                      * When in doubt, assume standard time
  602.                      */
  603.                     dstflag = STANDARD_TIME;
  604.             }
  605.             else
  606.                 dstflag = UNKNOWN_TIME;
  607.             dstflag_cache = dstflag;
  608.             gmt_cache = gmt;
  609.         }
  610.         /* convert using our private routine */
  611.         tim = __loctotime_t( (int)loct.wYear,
  612.                              (int)loct.wMonth,
  613.                              (int)loct.wDay,
  614.                              (int)loct.wHour,
  615.                              (int)loct.wMinute,
  616.                              (int)loct.wSecond,
  617.                              dstflag );
  618. #else  /* _WIN32 */
  619. #if defined (_M_MPPC) || defined (_M_M68K)
  620.         DateTimeRec dt;
  621.         GetTime(&dt);
  622.         /* convert using our private routine */
  623.         tim = _gmtotime_t((int)dt.year,
  624.                           (int)dt.month,
  625.                           (int)dt.day,
  626.                           (int)dt.hour,
  627.                           dt.minute,
  628.                           dt.second);
  629. #endif  /* defined (_M_MPPC) || defined (_M_M68K) */
  630. #endif  /* _WIN32 */
  631.         if (timeptr)
  632.                 *timeptr = tim;         /* store time if requested */
  633.         return tim;
  634. }