00001 /* 00002 * Copyright (C) 2001-2003 by egnite Software GmbH. All rights reserved. 00003 * 00004 * Redistribution and use in source and binary forms, with or without 00005 * modification, are permitted provided that the following conditions 00006 * are met: 00007 * 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the copyright holders nor the names of 00014 * contributors may be used to endorse or promote products derived 00015 * from this software without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS 00018 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00019 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00020 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE 00021 * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00022 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00023 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 00024 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 00025 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00026 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 00027 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00028 * SUCH DAMAGE. 00029 * 00030 * For additional information see http://www.ethernut.de/ 00031 * 00032 * Portions of the following functions are derived from material which is 00033 * Copyright (c) 1985 by Microsoft Corporation. All rights are reserved. 00034 */ 00035 /* 00036 * $Log: tzset.c,v $ 00037 * Revision 1.2 2003/12/19 22:26:38 drsung 00038 * Dox written. 00039 * 00040 * Revision 1.1 2003/11/24 18:07:37 drsung 00041 * first release 00042 * 00043 * 00044 */ 00045 00046 #include <time.h> 00047 #include "ctime.h" 00048 00049 typedef struct { 00050 int yr; /* year of interest */ 00051 int yd; /* day of year */ 00052 long ms; /* milli-seconds in the day */ 00053 } transitiondate; 00054 00055 /* 00056 * DST start and end structs. 00057 */ 00058 static transitiondate dststart = { -1, 0, 0L }; 00059 static transitiondate dstend = { -1, 0, 0L }; 00060 u_char _daylight = 1; /* daylight saving default enabled */ 00061 long _dstbias = -1 * 60L * 60L; /* bias for daylight saving in seconds */ 00062 long _timezone = 5L * 60L * 60L; /* default time zone is EST = -05:00:00 */ 00063 00064 /* 00065 * The macro below is valid for years between 1901 and 2099, which easily 00066 * includes all years representable by the current implementation of time_t. 00067 */ 00068 #define IS_LEAP_YEAR(year) ( (year & 3) == 0 ) 00069 #define DAY_MILLISEC (24L * 60L * 60L * 1000L) 00070 00071 00072 static void cvtdate(int trantype, 00073 int datetype, int year, int month, int week, int dayofweek, int date, int hour, int min, int sec, int msec) 00074 { 00075 int yearday; 00076 int monthdow; 00077 00078 if (datetype == 1) { 00079 00080 /* 00081 * Transition day specified in day-in-month format. 00082 */ 00083 00084 /* 00085 * Figure the year-day of the start of the month. 00086 */ 00087 yearday = 1 + (IS_LEAP_YEAR(year) ? _lpdays[month - 1] : _days[month - 1]); 00088 00089 /* 00090 * Figure the day of the week of the start of the month. 00091 */ 00092 monthdow = (yearday + ((year - 70) * 365) + ((year - 1) >> 2) - _LEAP_YEAR_ADJUST + _BASE_DOW) % 7; 00093 00094 /* 00095 * Figure the year-day of the transition date 00096 */ 00097 if (monthdow <= dayofweek) 00098 yearday += (dayofweek - monthdow) + (week - 1) * 7; 00099 else 00100 yearday += (dayofweek - monthdow) + week * 7; 00101 00102 /* 00103 * May have to adjust the calculation above if week == 5 (meaning 00104 * the last instance of the day in the month). Check if year falls 00105 * beyond after month and adjust accordingly. 00106 */ 00107 if ((week == 5) && (yearday > (IS_LEAP_YEAR(year) ? _lpdays[month] : _days[month]))) { 00108 yearday -= 7; 00109 } 00110 } else { 00111 /* 00112 * Transition day specified as an absolute day 00113 */ 00114 yearday = IS_LEAP_YEAR(year) ? _lpdays[month - 1] : _days[month - 1]; 00115 00116 yearday += date; 00117 } 00118 00119 if (trantype == 1) { 00120 /* 00121 * Converted date was for the start of DST 00122 */ 00123 dststart.yd = yearday; 00124 dststart.ms = (long) msec + (1000L * (sec + 60L * (min + 60L * hour))); 00125 /* 00126 * Set year field of dststart so that unnecessary calls to 00127 * cvtdate() may be avoided. 00128 */ 00129 dststart.yr = year; 00130 } else { 00131 /* 00132 * Converted date was for the end of DST 00133 */ 00134 dstend.yd = yearday; 00135 dstend.ms = (long) msec + (1000L * (sec + 60L * (min + 60L * hour))); 00136 /* 00137 * The converted date is still a DST date. Must convert to a 00138 * standard (local) date while being careful the millisecond field 00139 * does not overflow or underflow. 00140 */ 00141 if ((dstend.ms += (_dstbias * 1000L)) < 0) { 00142 dstend.ms += DAY_MILLISEC; 00143 dstend.yd--; 00144 } else if (dstend.ms >= DAY_MILLISEC) { 00145 dstend.ms -= DAY_MILLISEC; 00146 dstend.yd++; 00147 } 00148 00149 /* 00150 * Set year field of dstend so that unnecessary calls to cvtdate() 00151 * may be avoided. 00152 */ 00153 dstend.yr = year; 00154 } 00155 00156 return; 00157 } 00158 00159 00160 int _isindst(tm * tb) 00161 { 00162 long ms; 00163 if (_daylight == 0) 00164 return 0; 00165 00166 /* 00167 * Compute (recompute) the transition dates for daylight saving time 00168 * if necessary.The yr (year) fields of dststart and dstend is 00169 * compared to the year of interest to determine necessity. 00170 */ 00171 if ((tb->tm_year != dststart.yr) || (tb->tm_year != dstend.yr)) { 00172 00173 cvtdate(1, 1, tb->tm_year, 3, /* March */ 00174 5, /* last... */ 00175 0, /* ...Sunday */ 00176 0, 2, /* 02:00 (2 AM) */ 00177 0, 0, 0); 00178 00179 cvtdate(0, 1, tb->tm_year, 10, /* October */ 00180 5, /* last... */ 00181 0, /* ...Sunday */ 00182 0, 2, /* 02:00 (2 AM) */ 00183 0, 0, 0); 00184 } 00185 00186 /* 00187 * Handle simple cases first. 00188 */ 00189 if (dststart.yd < dstend.yd) { 00190 /* 00191 * Northern hemisphere ordering 00192 */ 00193 if ((tb->tm_yday < dststart.yd) || (tb->tm_yday > dstend.yd)) 00194 return 0; 00195 if ((tb->tm_yday > dststart.yd) && (tb->tm_yday < dstend.yd)) 00196 return 1; 00197 } else { 00198 /* 00199 * Southern hemisphere ordering 00200 */ 00201 if ((tb->tm_yday < dstend.yd) || (tb->tm_yday > dststart.yd)) 00202 return 1; 00203 if ((tb->tm_yday > dstend.yd) && (tb->tm_yday < dststart.yd)) 00204 return 0; 00205 } 00206 00207 ms = 1000L * (tb->tm_sec + 60L * tb->tm_min + 3600L * tb->tm_hour); 00208 00209 if (tb->tm_yday == dststart.yd) { 00210 if (ms >= dststart.ms) 00211 return 1; 00212 else 00213 return 0; 00214 } else { 00215 if (ms < dstend.ms) 00216 return 1; 00217 else 00218 return 0; 00219 } 00220 00221 }