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.

202 lines
6.6 KiB

  1. /***
  2. *gmtime.c - breaks down a time value into GMT date/time info
  3. *
  4. * Copyright (c) 1985-2001, 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. *Revision History:
  11. * 01-??-84 RLB Module created
  12. * 05-??-84 DCW Split off from rest off ctime routines.
  13. * 02-18-87 JCR For MS C, gmtime now returns NULL for out of range
  14. * time/date. (This is for ANSI compatibility.)
  15. * 04-10-87 JCR Changed long declaration to time_t and added const
  16. * 05-21-87 SKS Declare "struct tm tb" as NEAR data
  17. * 11-10-87 SKS Removed IBMC20 switch
  18. * 12-11-87 JCR Added "_LOAD_DS" to declaration
  19. * 05-24-88 PHG Merge DLL and regular versions
  20. * 06-06-89 JCR 386 mthread support
  21. * 11-06-89 KRS Add (unsigned) to handle years 2040-2099 correctly
  22. * 03-20-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
  23. * <cruntime.h>, removed #include <register.h> and
  24. * fixed the copyright. Also, cleaned up the formatting
  25. * a bit.
  26. * 10-04-90 GJF New-style function declarator.
  27. * 07-17-91 GJF Multi-thread support for Win32 [_WIN32_].
  28. * 02-17-93 GJF Changed for new _getptd().
  29. * 03-24-93 GJF Propagated changes from 16-bit tree.
  30. * 04-06-93 SKS Replace _CRTAPI* with __cdecl
  31. * 09-06-94 CFW Replace MTHREAD with _MT.
  32. * 01-10-95 CFW Debug CRT allocs.
  33. * 02-07-98 GJF Changes for Win64: replaced long with time_t.
  34. * 10-19-01 BWT Return NULL on malloc failure in MT case instead of
  35. * using static buffer.
  36. * 12-11-01 BWT return null if getptd fails instead of exiting program
  37. *
  38. *******************************************************************************/
  39. #include <cruntime.h>
  40. #include <time.h>
  41. #include <ctime.h>
  42. #include <stddef.h>
  43. #include <internal.h>
  44. #include <mtdll.h>
  45. #ifdef _MT
  46. #include <malloc.h>
  47. #include <stddef.h>
  48. #include <errno.h>
  49. #endif
  50. #include <dbgint.h>
  51. #if !defined(_MT)
  52. static struct tm tb = { 0 }; /* time block */
  53. #endif
  54. /***
  55. *struct tm *gmtime(timp) - convert *timp to a structure (UTC)
  56. *
  57. *Purpose:
  58. * Converts the calendar time value, in internal format (time_t), to
  59. * broken-down time (tm structure) with the corresponding UTC time.
  60. *
  61. *Entry:
  62. * const time_t *timp - pointer to time_t value to convert
  63. *
  64. *Exit:
  65. * returns pointer to filled-in tm structure.
  66. * returns NULL if *timp < 0L
  67. *
  68. *Exceptions:
  69. *
  70. *******************************************************************************/
  71. struct tm * __cdecl gmtime (
  72. const time_t *timp
  73. )
  74. {
  75. time_t caltim = *timp; /* calendar time to convert */
  76. int islpyr = 0; /* is-current-year-a-leap-year flag */
  77. REG1 int tmptim;
  78. REG3 int *mdays; /* pointer to days or lpdays */
  79. #ifdef _MT
  80. REG2 struct tm *ptb; /* will point to gmtime buffer */
  81. _ptiddata ptd = _getptd_noexit();
  82. if (!ptd) {
  83. errno = ENOMEM;
  84. return (NULL);
  85. }
  86. #else
  87. REG2 struct tm *ptb = &tb;
  88. #endif
  89. if ( caltim < 0 )
  90. return(NULL);
  91. #ifdef _MT
  92. /* Use per thread buffer area (malloc space, if necessary) */
  93. if ( (ptd->_gmtimebuf != NULL) || ((ptd->_gmtimebuf =
  94. _malloc_crt(sizeof(struct tm))) != NULL) )
  95. ptb = ptd->_gmtimebuf;
  96. else
  97. {
  98. errno = ENOMEM;
  99. return (NULL); /* malloc error: use static buffer */
  100. }
  101. #endif
  102. /*
  103. * Determine years since 1970. First, identify the four-year interval
  104. * since this makes handling leap-years easy (note that 2000 IS a
  105. * leap year and 2100 is out-of-range).
  106. */
  107. tmptim = (int)(caltim / _FOUR_YEAR_SEC);
  108. caltim -= ((time_t)tmptim * _FOUR_YEAR_SEC);
  109. /*
  110. * Determine which year of the interval
  111. */
  112. tmptim = (tmptim * 4) + 70; /* 1970, 1974, 1978,...,etc. */
  113. if ( caltim >= _YEAR_SEC ) {
  114. tmptim++; /* 1971, 1975, 1979,...,etc. */
  115. caltim -= _YEAR_SEC;
  116. if ( caltim >= _YEAR_SEC ) {
  117. tmptim++; /* 1972, 1976, 1980,...,etc. */
  118. caltim -= _YEAR_SEC;
  119. /*
  120. * Note, it takes 366 days-worth of seconds to get past a leap
  121. * year.
  122. */
  123. if ( caltim >= (_YEAR_SEC + _DAY_SEC) ) {
  124. tmptim++; /* 1973, 1977, 1981,...,etc. */
  125. caltim -= (_YEAR_SEC + _DAY_SEC);
  126. }
  127. else {
  128. /*
  129. * In a leap year after all, set the flag.
  130. */
  131. islpyr++;
  132. }
  133. }
  134. }
  135. /*
  136. * tmptim now holds the value for tm_year. caltim now holds the
  137. * number of elapsed seconds since the beginning of that year.
  138. */
  139. ptb->tm_year = tmptim;
  140. /*
  141. * Determine days since January 1 (0 - 365). This is the tm_yday value.
  142. * Leave caltim with number of elapsed seconds in that day.
  143. */
  144. ptb->tm_yday = (int)(caltim / _DAY_SEC);
  145. caltim -= (time_t)(ptb->tm_yday) * _DAY_SEC;
  146. /*
  147. * Determine months since January (0 - 11) and day of month (1 - 31)
  148. */
  149. if ( islpyr )
  150. mdays = _lpdays;
  151. else
  152. mdays = _days;
  153. for ( tmptim = 1 ; mdays[tmptim] < ptb->tm_yday ; tmptim++ ) ;
  154. ptb->tm_mon = --tmptim;
  155. ptb->tm_mday = ptb->tm_yday - mdays[tmptim];
  156. /*
  157. * Determine days since Sunday (0 - 6)
  158. */
  159. ptb->tm_wday = ((int)(*timp / _DAY_SEC) + _BASE_DOW) % 7;
  160. /*
  161. * Determine hours since midnight (0 - 23), minutes after the hour
  162. * (0 - 59), and seconds after the minute (0 - 59).
  163. */
  164. ptb->tm_hour = (int)(caltim / 3600);
  165. caltim -= (time_t)ptb->tm_hour * 3600L;
  166. ptb->tm_min = (int)(caltim / 60);
  167. ptb->tm_sec = (int)(caltim - (ptb->tm_min) * 60);
  168. ptb->tm_isdst = 0;
  169. return( (struct tm *)ptb );
  170. }