home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / crt / src / gmtime.c < prev    next >
C/C++ Source or Header  |  1998-06-17  |  5KB  |  166 lines

  1. /***
  2. *gmtime.c - breaks down a time value into GMT date/time info
  3. *
  4. *       Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *       defines gmtime() - breaks the clock value down into GMT time/date
  8. *       information; return pointer to structure with the data.
  9. *
  10. *******************************************************************************/
  11.  
  12. #include <cruntime.h>
  13. #include <time.h>
  14. #include <ctime.h>
  15. #include <stddef.h>
  16. #include <internal.h>
  17. #include <mtdll.h>
  18. #ifdef _MT
  19. #include <malloc.h>
  20. #include <stddef.h>
  21. #endif  /* _MT */
  22. #include <dbgint.h>
  23.  
  24. static struct tm tb = { 0 };    /* time block */
  25.  
  26. /***
  27. *struct tm *gmtime(timp) - convert *timp to a structure (UTC)
  28. *
  29. *Purpose:
  30. *       Converts the calendar time value, in internal format (time_t), to
  31. *       broken-down time (tm structure) with the corresponding UTC time.
  32. *
  33. *Entry:
  34. *       const time_t *timp - pointer to time_t value to convert
  35. *
  36. *Exit:
  37. *       returns pointer to filled-in tm structure.
  38. *       returns NULL if *timp < 0L
  39. *
  40. *Exceptions:
  41. *
  42. *******************************************************************************/
  43.  
  44. struct tm * __cdecl gmtime (
  45.         const time_t *timp
  46.         )
  47. {
  48.  
  49.         long caltim = *timp;            /* calendar time to convert */
  50.         int islpyr = 0;                 /* is-current-year-a-leap-year flag */
  51.         REG1 int tmptim;
  52.         REG3 int *mdays;                /* pointer to days or lpdays */
  53.  
  54. #ifdef _MT
  55.  
  56.         REG2 struct tm *ptb;            /* will point to gmtime buffer */
  57.         _ptiddata ptd = _getptd();
  58.  
  59. #else  /* _MT */
  60.         REG2 struct tm *ptb = &tb;
  61. #endif  /* _MT */
  62.  
  63.         if ( caltim < 0L )
  64.                 return(NULL);
  65.  
  66. #ifdef _MT
  67.  
  68.         /* Use per thread buffer area (malloc space, if necessary) */
  69.  
  70.         if ( (ptd->_gmtimebuf != NULL) || ((ptd->_gmtimebuf =
  71.             _malloc_crt(sizeof(struct tm))) != NULL) )
  72.                 ptb = ptd->_gmtimebuf;
  73.         else
  74.                 ptb = &tb;      /* malloc error: use static buffer */
  75.  
  76. #endif  /* _MT */
  77.  
  78.         /*
  79.          * Determine years since 1970. First, identify the four-year interval
  80.          * since this makes handling leap-years easy (note that 2000 IS a
  81.          * leap year and 2100 is out-of-range).
  82.          */
  83.         tmptim = (int)(caltim / _FOUR_YEAR_SEC);
  84.         caltim -= ((long)tmptim * _FOUR_YEAR_SEC);
  85.  
  86.         /*
  87.          * Determine which year of the interval
  88.          */
  89.         tmptim = (tmptim * 4) + 70;         /* 1970, 1974, 1978,...,etc. */
  90.  
  91.         if ( caltim >= _YEAR_SEC ) {
  92.  
  93.             tmptim++;                       /* 1971, 1975, 1979,...,etc. */
  94.             caltim -= _YEAR_SEC;
  95.  
  96.             if ( caltim >= _YEAR_SEC ) {
  97.  
  98.                 tmptim++;                   /* 1972, 1976, 1980,...,etc. */
  99.                 caltim -= _YEAR_SEC;
  100.  
  101.                 /*
  102.                  * Note, it takes 366 days-worth of seconds to get past a leap
  103.                  * year.
  104.                  */
  105.                 if ( caltim >= (_YEAR_SEC + _DAY_SEC) ) {
  106.  
  107.                         tmptim++;           /* 1973, 1977, 1981,...,etc. */
  108.                         caltim -= (_YEAR_SEC + _DAY_SEC);
  109.                 }
  110.                 else {
  111.                         /*
  112.                          * In a leap year after all, set the flag.
  113.                          */
  114.                         islpyr++;
  115.                 }
  116.             }
  117.         }
  118.  
  119.         /*
  120.          * tmptim now holds the value for tm_year. caltim now holds the
  121.          * number of elapsed seconds since the beginning of that year.
  122.          */
  123.         ptb->tm_year = tmptim;
  124.  
  125.         /*
  126.          * Determine days since January 1 (0 - 365). This is the tm_yday value.
  127.          * Leave caltim with number of elapsed seconds in that day.
  128.          */
  129.         ptb->tm_yday = (int)(caltim / _DAY_SEC);
  130.         caltim -= (long)(ptb->tm_yday) * _DAY_SEC;
  131.  
  132.         /*
  133.          * Determine months since January (0 - 11) and day of month (1 - 31)
  134.          */
  135.         if ( islpyr )
  136.             mdays = _lpdays;
  137.         else
  138.             mdays = _days;
  139.  
  140.  
  141.         for ( tmptim = 1 ; mdays[tmptim] < ptb->tm_yday ; tmptim++ ) ;
  142.  
  143.         ptb->tm_mon = --tmptim;
  144.  
  145.         ptb->tm_mday = ptb->tm_yday - mdays[tmptim];
  146.  
  147.         /*
  148.          * Determine days since Sunday (0 - 6)
  149.          */
  150.         ptb->tm_wday = ((int)(*timp / _DAY_SEC) + _BASE_DOW) % 7;
  151.  
  152.         /*
  153.          *  Determine hours since midnight (0 - 23), minutes after the hour
  154.          *  (0 - 59), and seconds after the minute (0 - 59).
  155.          */
  156.         ptb->tm_hour = (int)(caltim / 3600);
  157.         caltim -= (long)ptb->tm_hour * 3600L;
  158.  
  159.         ptb->tm_min = (int)(caltim / 60);
  160.         ptb->tm_sec = (int)(caltim - (ptb->tm_min) * 60);
  161.  
  162.         ptb->tm_isdst = 0;
  163.         return( (struct tm *)ptb );
  164.  
  165. }
  166.