tzset.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  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.3 2008/08/11 06:59:41 haraldkipp
  38. * BSD types replaced by stdint types (feature request #1282721).
  39. *
  40. * Revision 1.2 2003/12/19 22:26:38 drsung
  41. * Dox written.
  42. *
  43. * Revision 1.1 2003/11/24 18:07:37 drsung
  44. * first release
  45. *
  46. *
  47. */
  48. #include <stdint.h>
  49. #include <time.h>
  50. #include "ctime.h"
  51. typedef struct {
  52. int yr; /* year of interest */
  53. int yd; /* day of year */
  54. long ms; /* milli-seconds in the day */
  55. } transitiondate;
  56. /*
  57. * DST start and end structs.
  58. */
  59. static transitiondate dststart = { -1, 0, 0L };
  60. static transitiondate dstend = { -1, 0, 0L };
  61. int _daylight = 1; /* daylight saving default enabled */
  62. long _dstbias = -1 * 60L * 60L; /* bias for daylight saving in seconds */
  63. long _timezone = 5L * 60L * 60L; /* default time zone is EST = -05:00:00 */
  64. /*
  65. * The macro below is valid for years between 1901 and 2099, which easily
  66. * includes all years representable by the current implementation of time_t.
  67. */
  68. #define IS_LEAP_YEAR(year) ( (year & 3) == 0 )
  69. #define DAY_MILLISEC (24L * 60L * 60L * 1000L)
  70. static void cvtdate(int trantype,
  71. int datetype, int year, int month, int week, int dayofweek, int date, int hour, int min, int sec, int msec)
  72. {
  73. int yearday;
  74. int monthdow;
  75. if (datetype == 1) {
  76. /*
  77. * Transition day specified in day-in-month format.
  78. */
  79. /*
  80. * Figure the year-day of the start of the month.
  81. */
  82. yearday = 1 + (IS_LEAP_YEAR(year) ? _lpdays[month - 1] : _days[month - 1]);
  83. /*
  84. * Figure the day of the week of the start of the month.
  85. */
  86. monthdow = (yearday + ((year - 70) * 365) + ((year - 1) >> 2) - _LEAP_YEAR_ADJUST + _BASE_DOW) % 7;
  87. /*
  88. * Figure the year-day of the transition date
  89. */
  90. if (monthdow <= dayofweek)
  91. yearday += (dayofweek - monthdow) + (week - 1) * 7;
  92. else
  93. yearday += (dayofweek - monthdow) + week * 7;
  94. /*
  95. * May have to adjust the calculation above if week == 5 (meaning
  96. * the last instance of the day in the month). Check if year falls
  97. * beyond after month and adjust accordingly.
  98. */
  99. if ((week == 5) && (yearday > (IS_LEAP_YEAR(year) ? _lpdays[month] : _days[month]))) {
  100. yearday -= 7;
  101. }
  102. } else {
  103. /*
  104. * Transition day specified as an absolute day
  105. */
  106. yearday = IS_LEAP_YEAR(year) ? _lpdays[month - 1] : _days[month - 1];
  107. yearday += date;
  108. }
  109. if (trantype == 1) {
  110. /*
  111. * Converted date was for the start of DST
  112. */
  113. dststart.yd = yearday;
  114. dststart.ms = (long) msec + (1000L * (sec + 60L * (min + 60L * hour)));
  115. /*
  116. * Set year field of dststart so that unnecessary calls to
  117. * cvtdate() may be avoided.
  118. */
  119. dststart.yr = year;
  120. } else {
  121. /*
  122. * Converted date was for the end of DST
  123. */
  124. dstend.yd = yearday;
  125. dstend.ms = (long) msec + (1000L * (sec + 60L * (min + 60L * hour)));
  126. /*
  127. * The converted date is still a DST date. Must convert to a
  128. * standard (local) date while being careful the millisecond field
  129. * does not overflow or underflow.
  130. */
  131. if ((dstend.ms += (_dstbias * 1000L)) < 0) {
  132. dstend.ms += DAY_MILLISEC;
  133. dstend.yd--;
  134. } else if (dstend.ms >= DAY_MILLISEC) {
  135. dstend.ms -= DAY_MILLISEC;
  136. dstend.yd++;
  137. }
  138. /*
  139. * Set year field of dstend so that unnecessary calls to cvtdate()
  140. * may be avoided.
  141. */
  142. dstend.yr = year;
  143. }
  144. return;
  145. }
  146. int _isindst(tm * tb)
  147. {
  148. long ms;
  149. if (_daylight == 0)
  150. return 0;
  151. /*
  152. * Compute (recompute) the transition dates for daylight saving time
  153. * if necessary.The yr (year) fields of dststart and dstend is
  154. * compared to the year of interest to determine necessity.
  155. */
  156. if ((tb->tm_year != dststart.yr) || (tb->tm_year != dstend.yr)) {
  157. cvtdate(1, 1, tb->tm_year, 3, /* March */
  158. 5, /* last... */
  159. 0, /* ...Sunday */
  160. 0, 2, /* 02:00 (2 AM) */
  161. 0, 0, 0);
  162. cvtdate(0, 1, tb->tm_year, 10, /* October */
  163. 5, /* last... */
  164. 0, /* ...Sunday */
  165. 0, 2, /* 02:00 (2 AM) */
  166. 0, 0, 0);
  167. }
  168. /*
  169. * Handle simple cases first.
  170. */
  171. if (dststart.yd < dstend.yd) {
  172. /*
  173. * Northern hemisphere ordering
  174. */
  175. if ((tb->tm_yday < dststart.yd) || (tb->tm_yday > dstend.yd))
  176. return 0;
  177. if ((tb->tm_yday > dststart.yd) && (tb->tm_yday < dstend.yd))
  178. return 1;
  179. } else {
  180. /*
  181. * Southern hemisphere ordering
  182. */
  183. if ((tb->tm_yday < dstend.yd) || (tb->tm_yday > dststart.yd))
  184. return 1;
  185. if ((tb->tm_yday > dstend.yd) && (tb->tm_yday < dststart.yd))
  186. return 0;
  187. }
  188. ms = 1000L * (tb->tm_sec + 60L * tb->tm_min + 3600L * tb->tm_hour);
  189. if (tb->tm_yday == dststart.yd) {
  190. if (ms >= dststart.ms)
  191. return 1;
  192. else
  193. return 0;
  194. } else {
  195. if (ms < dstend.ms)
  196. return 1;
  197. else
  198. return 0;
  199. }
  200. }