mktime.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. /*
  2. * Copyright (C) 2001-2003 by egnite Software GmbH. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the copyright holders nor the names of
  14. * contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  20. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  21. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  22. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  23. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  24. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  25. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  26. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  27. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. *
  30. * For additional information see http://www.ethernut.de/
  31. *
  32. * Portions of the following functions are derived from material which is
  33. * Copyright (c) 1985 by Microsoft Corporation. All rights are reserved.
  34. */
  35. /*
  36. * $Log$
  37. * Revision 1.4 2009/01/17 15:37:52 haraldkipp
  38. * Added some NUTASSERT macros to check function parameters.
  39. *
  40. * Revision 1.3 2008/08/11 06:59:40 haraldkipp
  41. * BSD types replaced by stdint types (feature request #1282721).
  42. *
  43. * Revision 1.2 2003/12/19 22:26:37 drsung
  44. * Dox written.
  45. *
  46. * Revision 1.1 2003/11/24 18:07:37 drsung
  47. * first release
  48. *
  49. *
  50. */
  51. #include <stdint.h>
  52. #include <time.h>
  53. #include "ctime.h"
  54. #include <sys/nutdebug.h>
  55. #define __need_NULL
  56. #include <stddef.h>
  57. /*
  58. * ChkAdd evaluates to TRUE if dest = src1 + src2 has overflowed
  59. */
  60. #define ChkAdd(dest, src1, src2) ( ((src1 >= 0L) && (src2 >= 0L) \
  61. && (dest < 0L)) || ((src1 < 0L) && (src2 < 0L) && (dest >= 0L)) )
  62. /*
  63. * ChkMul evaluates to TRUE if dest = src1 * src2 has overflowed
  64. */
  65. #define ChkMul(dest, src1, src2) ( src1 ? (dest/src1 != src2) : 0 )
  66. /*!
  67. * \addtogroup xgCrtTime
  68. * @{
  69. */
  70. static time_t _make_time_t(tm * tb, int ultflag)
  71. {
  72. long tmptm1, tmptm2, tmptm3;
  73. tm *tbtemp;
  74. NUTASSERT(tb != NULL);
  75. /*
  76. * First, make sure tm_year is reasonably close to being in range.
  77. */
  78. if (((tmptm1 = tb->tm_year) < _BASE_YEAR - 1) || (tmptm1 > _MAX_YEAR + 1))
  79. goto err_mktime;
  80. /*
  81. * Adjust month value so it is in the range 0 - 11. This is because
  82. * we don't know how many days are in months 12, 13, 14, etc.
  83. */
  84. if ((tb->tm_mon < 0) || (tb->tm_mon > 11)) {
  85. /*
  86. * no danger of overflow because the range check above.
  87. */
  88. tmptm1 += (tb->tm_mon / 12);
  89. if ((tb->tm_mon %= 12) < 0) {
  90. tb->tm_mon += 12;
  91. tmptm1--;
  92. }
  93. /*
  94. * Make sure year count is still in range.
  95. */
  96. if ((tmptm1 < _BASE_YEAR - 1) || (tmptm1 > _MAX_YEAR + 1))
  97. goto err_mktime;
  98. }
  99. /***** HERE: tmptm1 holds number of elapsed years *****/
  100. /*
  101. * Calculate days elapsed minus one, in the given year, to the given
  102. * month. Check for leap year and adjust if necessary.
  103. */
  104. tmptm2 = _days[tb->tm_mon];
  105. if (!(tmptm1 & 3) && (tb->tm_mon > 1))
  106. tmptm2++;
  107. /*
  108. * Calculate elapsed days since base date (midnight, 1/1/70, UTC)
  109. *
  110. *
  111. * 365 days for each elapsed year since 1970, plus one more day for
  112. * each elapsed leap year. no danger of overflow because of the range
  113. * check (above) on tmptm1.
  114. */
  115. tmptm3 = (tmptm1 - _BASE_YEAR) * 365L + ((tmptm1 - 1L) >> 2)
  116. - _LEAP_YEAR_ADJUST;
  117. /*
  118. * elapsed days to current month (still no possible overflow)
  119. */
  120. tmptm3 += tmptm2;
  121. /*
  122. * elapsed days to current date. overflow is now possible.
  123. */
  124. tmptm1 = tmptm3 + (tmptm2 = (long) (tb->tm_mday));
  125. if (ChkAdd(tmptm1, tmptm3, tmptm2))
  126. goto err_mktime;
  127. /***** HERE: tmptm1 holds number of elapsed days *****/
  128. /*
  129. * Calculate elapsed hours since base date
  130. */
  131. tmptm2 = tmptm1 * 24L;
  132. if (ChkMul(tmptm2, tmptm1, 24L))
  133. goto err_mktime;
  134. tmptm1 = tmptm2 + (tmptm3 = (long) tb->tm_hour);
  135. if (ChkAdd(tmptm1, tmptm2, tmptm3))
  136. goto err_mktime;
  137. /***** HERE: tmptm1 holds number of elapsed hours *****/
  138. /*
  139. * Calculate elapsed minutes since base date
  140. */
  141. tmptm2 = tmptm1 * 60L;
  142. if (ChkMul(tmptm2, tmptm1, 60L))
  143. goto err_mktime;
  144. tmptm1 = tmptm2 + (tmptm3 = (long) tb->tm_min);
  145. if (ChkAdd(tmptm1, tmptm2, tmptm3))
  146. goto err_mktime;
  147. /***** HERE: tmptm1 holds number of elapsed minutes *****/
  148. /*
  149. * Calculate elapsed seconds since base date
  150. */
  151. tmptm2 = tmptm1 * 60L;
  152. if (ChkMul(tmptm2, tmptm1, 60L))
  153. goto err_mktime;
  154. tmptm1 = tmptm2 + (tmptm3 = (long) tb->tm_sec);
  155. if (ChkAdd(tmptm1, tmptm2, tmptm3))
  156. goto err_mktime;
  157. /***** HERE: tmptm1 holds number of elapsed seconds *****/
  158. if (ultflag) {
  159. /*
  160. * Adjust for timezone. No need to check for overflow since
  161. * localtime() will check its arg value
  162. */
  163. tmptm1 += _timezone;
  164. /*
  165. * Convert this second count back into a time block structure.
  166. * If localtime returns NULL, return an error.
  167. */
  168. if ((tbtemp = localtime(&tmptm1)) == NULL)
  169. goto err_mktime;
  170. /*
  171. * Now must compensate for DST. The ANSI rules are to use the
  172. * passed-in tm_isdst flag if it is non-negative. Otherwise,
  173. * compute if DST applies. Recall that tbtemp has the time without
  174. * DST compensation, but has set tm_isdst correctly.
  175. */
  176. if ((tb->tm_isdst > 0) || ((tb->tm_isdst < 0) && (tbtemp->tm_isdst > 0))) {
  177. tmptm1 += _dstbias;
  178. tbtemp = localtime(&tmptm1); /* reconvert, can't get NULL */
  179. }
  180. } else {
  181. if ((tbtemp = gmtime(&tmptm1)) == NULL)
  182. goto err_mktime;
  183. }
  184. /***** HERE: tmptm1 holds number of elapsed seconds, adjusted *****/
  185. /***** for local time if requested *****/
  186. *tb = *tbtemp;
  187. return (time_t) tmptm1;
  188. err_mktime:
  189. /*
  190. * All errors come to here
  191. */
  192. return (time_t) (-1);
  193. }
  194. /*!
  195. * \brief Convert the local time to a calendar value.
  196. *
  197. * The \b mktime function converts the supplied time structure (possibly incomplete)
  198. * pointed to by \e timeptr into a fully defined structure with normalized values
  199. * and then converts it to a ::time_t calendar time value. The converted time has
  200. * the same encoding as the values returned by the ::time function. The original
  201. * values of the \c tm_wday and \c tm_yday components of the \e timeptr structure are
  202. * ignored, and the original values of the other components are not restricted
  203. * to their normal ranges.
  204. *
  205. * After an adjustment to Greenwich Mean Time (GMT), \b mktime handles dates from
  206. * midnight, January 1, 1970, to January 19, 3:14:07, 2038. This adjustment may
  207. * cause \b mktime to return -1 (cast to ::time_t) even though the date you specify
  208. * is within range. For example, if you are in Cairo, Egypt, which is two hours ahead
  209. * of GMT, two hours will first be subtracted from the date you specify in \e timeptr;
  210. * this may now put your date out of range.
  211. *
  212. * If successful, \b mktime sets the values of \c tm_wday and \c tm_yday as appropriate
  213. * and sets the other components to represent the specified calendar time, but with
  214. * their values forced to the normal ranges. The final value of tm_mday is not set until
  215. * tm_mon and tm_year are determined. When specifying a tm structure time, set
  216. * the \c tm_isdst field to:
  217. *
  218. * - Zero (0) to indicate that standard time is in effect.
  219. * - A value greater than 0 to indicate that daylight savings time is in effect.
  220. *
  221. * \c tm_isdst is a required field. If not set, its value is undefined and the return value
  222. * from \b mktime is unpredictable. If \e timeptr points to a ::tm structure returned by a
  223. * previous call to ::gmtime or ::localtime, the \c tm_isdst field contains the correct value.
  224. *
  225. * \note Note that ::gmtime and ::localtime use a single statically allocated buffer
  226. * for the conversion. If you supply this buffer to \b mktime, the previous contents are destroyed.
  227. *
  228. * \param timeptr Pointer to time structure.
  229. * \return \b mktime returns the specified calendar time encoded as a value of type
  230. * ::time_t. If \e timeptr references a date before midnight, January 1, 1970, or
  231. * if the calendar time cannot be represented, \b mktime returns –1 cast to type ::time_t.
  232. * When using \b mktime and if \e timeptr references a date after 3:14:07 January 19, 2038, UTC,
  233. * it will return –1 cast to type ::time_t.
  234. *
  235. */
  236. time_t mktime(tm * timeptr)
  237. {
  238. return (_make_time_t(timeptr, 1));
  239. }
  240. time_t _mkgmtime(tm * timeptr)
  241. {
  242. return (_make_time_t(timeptr, 0));
  243. }
  244. /*@}*/