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

  1. /***
  2. *localtim.c - Convert time_t value to time structure
  3. *
  4. *       Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *       Converts time stored as a time_t value to a structure of type
  8. *       struct tm expressed as local time.
  9. *
  10. *******************************************************************************/
  11.  
  12. #include <cruntime.h>
  13. #include <limits.h>
  14. #include <time.h>
  15. #include <stddef.h>
  16. #include <ctime.h>
  17. #include <internal.h>
  18.  
  19. /***
  20. *struct tm *localtime(ptime) - convert time_t value to tm structure
  21. *
  22. *Purpose:
  23. *       Convert a value in internal (time_t) format to a tm struct
  24. *       containing the corresponding local time.
  25. *
  26. * NOTES:
  27. *       (1) gmtime must be called before _isindst to ensure that the tb time
  28. *           structure is initialized.
  29. *       (2) gmtime and localtime use a single statically allocated buffer.
  30. *           Each call to one of these routines destroys the contents of the
  31. *           previous call.
  32. *       (3) It is assumed that time_t is a 32-bit long integer representing
  33. *           the number of seconds since 00:00:00, 01-01-70 (UTC) (i.e., the
  34. *           Posix/Unix Epoch. Only non-negative values are supported.
  35. *       (4) It is assumed that the maximum adjustment for local time is
  36. *           less than three days (include Daylight Savings Time adjustment).
  37. *           This only a concern in Posix where the specification of the TZ
  38. *           environment restricts the combined offset for time zone and
  39. *           Daylight Savings Time to 2 * (24:59:59), just under 50 hours.
  40. *
  41. *Entry:
  42. *       time_t *ptime - pointer to a long time value
  43. *
  44. *Exit:
  45. *       If *ptime is non-negative, returns a pointer to the tm structure.
  46. *       Otherwise, returns NULL.
  47. *
  48. *Exceptions:
  49. *       See items (3) and (4) in the NOTES above. If these assumptions are
  50. *       violated, behavior is undefined.
  51. *
  52. *******************************************************************************/
  53.  
  54. struct tm * __cdecl localtime (
  55.         const time_t *ptime
  56.         )
  57. {
  58.         REG1 struct tm *ptm;
  59.         long ltime;
  60.  
  61.         /*
  62.          * Check for illegal time_t value
  63.          */
  64.         if ( (long)*ptime < 0L )
  65.                 return( NULL );
  66.  
  67. #ifdef _WIN32
  68.         __tzset();
  69. #else  /* _WIN32 */
  70. #if defined (_M_MPPC) || defined (_M_M68K)
  71.         _tzset();
  72. #endif  /* defined (_M_MPPC) || defined (_M_M68K) */
  73. #endif  /* _WIN32 */
  74.  
  75.         if ( (*ptime > 3 * _DAY_SEC) && (*ptime < LONG_MAX - 3 * _DAY_SEC) ) {
  76.                 /*
  77.                  * The date does not fall within the first three, or last
  78.                  * three, representable days of the Epoch. Therefore, there
  79.                  * is no possibility of overflowing or underflowing the
  80.                  * time_t representation as we compensate for timezone and
  81.                  * Daylight Savings Time.
  82.                  */
  83.  
  84.                 ltime = (long)*ptime - _timezone;
  85.                 ptm = gmtime( (time_t *)<ime );
  86.  
  87.                 /*
  88.                  * Check and adjust for Daylight Saving Time.
  89.                  */
  90.                 if ( _daylight && _isindst( ptm ) ) {
  91.                         ltime -= _dstbias;
  92.                         ptm = gmtime( (time_t *)<ime );
  93.                         ptm->tm_isdst = 1;
  94.                 }
  95.         }
  96.         else {
  97.                 ptm = gmtime( ptime );
  98.  
  99.                 /*
  100.                  * The date falls with the first three, or last three days
  101.                  * of the Epoch. It is possible the time_t representation
  102.                  * would overflow or underflow while compensating for
  103.                  * timezone and Daylight Savings Time. Therefore, make the
  104.                  * timezone and Daylight Savings Time adjustments directly
  105.                  * in the tm structure. The beginning of the Epoch is
  106.                  * 00:00:00, 01-01-70 (UTC) and the last representable second
  107.                  * in the Epoch is 03:14:07, 01-19-2038 (UTC). This will be
  108.                  * used in the calculations below.
  109.                  *
  110.                  * First, adjust for the timezone.
  111.                  */
  112.                 if ( _isindst(ptm) )
  113.                         ltime = (long)ptm->tm_sec - (_timezone + _dstbias);
  114.                 else
  115.                         ltime = (long)ptm->tm_sec - _timezone;
  116.                 ptm->tm_sec = (int)(ltime % 60);
  117.                 if ( ptm->tm_sec < 0 ) {
  118.                         ptm->tm_sec += 60;
  119.                         ltime -= 60;
  120.                 }
  121.  
  122.                 ltime = (long)ptm->tm_min + ltime/60;
  123.                 ptm->tm_min = (int)(ltime % 60);
  124.                 if ( ptm->tm_min < 0 ) {
  125.                         ptm->tm_min += 60;
  126.                         ltime -= 60;
  127.                 }
  128.  
  129.                 ltime = (long)ptm->tm_hour + ltime/60;
  130.                 ptm->tm_hour = (int)(ltime % 24);
  131.                 if ( ptm->tm_hour < 0 ) {
  132.                         ptm->tm_hour += 24;
  133.                         ltime -=24;
  134.                 }
  135.  
  136.                 ltime /= 24;
  137.  
  138.                 if ( ltime > 0L ) {
  139.                         /*
  140.                          * There is no possibility of overflowing the tm_mday
  141.                          * and tm_yday fields since the date can be no later
  142.                          * than January 19.
  143.                          */
  144.                         ptm->tm_wday = (ptm->tm_wday + ltime) % 7;
  145.                         ptm->tm_mday += ltime;
  146.                         ptm->tm_yday += ltime;
  147.                 }
  148.                 else if ( ltime < 0L ) {
  149.                         /*
  150.                          * It is possible to underflow the tm_mday and tm_yday
  151.                          * fields. If this happens, then adjusted date must
  152.                          * lie in December 1969.
  153.                          */
  154.                         ptm->tm_wday = (ptm->tm_wday + 7 + ltime) % 7;
  155.                         if ( (ptm->tm_mday += ltime) <= 0 ) {
  156.                                 ptm->tm_mday += 31;
  157.                                 ptm->tm_yday = 364;
  158.                                 ptm->tm_mon = 11;
  159.                                 ptm->tm_year--;
  160.                         }
  161.                         else {
  162.                                 ptm->tm_yday += ltime;
  163.                         }
  164.                 }
  165.  
  166.  
  167.         }
  168.  
  169.  
  170.         return(ptm);
  171. }
  172.