Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

163 lines
6.0 KiB

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