Source code of Windows XP (NT5)
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.

157 lines
5.6 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. /*
  78. * Check and adjust for Daylight Saving Time.
  79. */
  80. if ( _daylight && _isindst( ptm ) ) {
  81. ltime -= _dstbias;
  82. ptm = _gmtime64( &ltime );
  83. ptm->tm_isdst = 1;
  84. }
  85. }
  86. else {
  87. ptm = _gmtime64( ptime );
  88. /*
  89. * The date falls with the first three days of the Epoch.
  90. * It is possible the time_t representation would underflow
  91. * while compensating for timezone and Daylight Savings Time
  92. * Therefore, make the timezone and Daylight Savings Time
  93. * adjustments directly in the tm structure. The beginning of
  94. * the Epoch is 00:00:00, 01-01-70 (UTC).
  95. *
  96. * First, adjust for the timezone.
  97. */
  98. if ( _isindst(ptm) ) {
  99. ltime = (__time64_t)ptm->tm_sec - (_timezone + _dstbias);
  100. ptm->tm_isdst;
  101. }
  102. else
  103. ltime = (__time64_t)ptm->tm_sec - _timezone;
  104. ptm->tm_sec = (int)(ltime % 60);
  105. if ( ptm->tm_sec < 0 ) {
  106. ptm->tm_sec += 60;
  107. ltime -= 60;
  108. }
  109. ltime = (__time64_t)ptm->tm_min + ltime/60;
  110. ptm->tm_min = (int)(ltime % 60);
  111. if ( ptm->tm_min < 0 ) {
  112. ptm->tm_min += 60;
  113. ltime -= 60;
  114. }
  115. ltime = (__time64_t)ptm->tm_hour + ltime/60;
  116. ptm->tm_hour = (int)(ltime % 24);
  117. if ( ptm->tm_hour < 0 ) {
  118. ptm->tm_hour += 24;
  119. ltime -=24;
  120. }
  121. ltime /= 24;
  122. if ( ltime < 0 ) {
  123. /*
  124. * It is possible to underflow the tm_mday and tm_yday
  125. * fields. If this happens, then adjusted date must
  126. * lie in December 1969.
  127. */
  128. ptm->tm_wday = (ptm->tm_wday + 7 + (int)ltime) % 7;
  129. if ( (ptm->tm_mday += (int)ltime) <= 0 ) {
  130. ptm->tm_mday += 31;
  131. ptm->tm_yday = 364;
  132. ptm->tm_mon = 11;
  133. ptm->tm_year--;
  134. }
  135. else {
  136. ptm->tm_yday += (int)ltime;
  137. }
  138. }
  139. }
  140. return(ptm);
  141. }