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: localtim.c,v $ 00037 * Revision 1.4 2004/10/14 16:43:00 drsung 00038 * Fixed compiler warning "comparison between signed and unsigned" 00039 * 00040 * Revision 1.3 2003/12/19 22:26:37 drsung 00041 * Dox written. 00042 * 00043 * Revision 1.2 2003/11/26 11:14:32 haraldkipp 00044 * Portability issues 00045 * 00046 * Revision 1.1 2003/11/24 18:07:37 drsung 00047 * first release 00048 * 00049 * 00050 */ 00051 00052 00053 #include <time.h> 00054 #include "ctime.h" 00055 00056 #define __need_NULL 00057 #include <stddef.h> 00058 00059 #define LONG_MAX 2147483647L 00060 00076 int localtime_r(CONST time_t * timer, tm * ptm) 00077 { 00078 long ltime; 00079 if ((*timer > (time_t)(3 * _DAY_SEC)) && (*timer < (time_t)(LONG_MAX - 3 * _DAY_SEC))) { 00080 /* 00081 * The date does not fall within the first three, or last 00082 * three, representable days of the Epoch. Therefore, there 00083 * is no possibility of overflowing or underflowing the 00084 * time_t representation as we compensate for timezone and 00085 * Daylight Savings Time. 00086 */ 00087 00088 ltime = (long) *timer - _timezone; 00089 gmtime_r((time_t *) & ltime, ptm); 00090 00091 /* 00092 * Check and adjust for Daylight Saving Time. 00093 */ 00094 if (_daylight && _isindst(ptm)) { 00095 ltime -= _dstbias; 00096 gmtime_r((time_t *) & ltime, ptm); 00097 ptm->tm_isdst = 1; 00098 } 00099 } else { 00100 gmtime_r(timer, ptm); 00101 00102 /* 00103 * The date falls with the first three, or last three days 00104 * of the Epoch. It is possible the time_t representation 00105 * would overflow or underflow while compensating for 00106 * timezone and Daylight Savings Time. Therefore, make the 00107 * timezone and Daylight Savings Time adjustments directly 00108 * in the tm structure. The beginning of the Epoch is 00109 * 00:00:00, 01-01-70 (UCT) and the last representable second 00110 * in the Epoch is 03:14:07, 01-19-2038 (UCT). This will be 00111 * used in the calculations below. 00112 * 00113 * First, adjust for the timezone. 00114 */ 00115 if (_isindst(ptm)) 00116 ltime = (long) ptm->tm_sec - (_timezone + _dstbias); 00117 else 00118 ltime = (long) ptm->tm_sec - _timezone; 00119 ptm->tm_sec = (int) (ltime % 60); 00120 if (ptm->tm_sec < 0) { 00121 ptm->tm_sec += 60; 00122 ltime -= 60; 00123 } 00124 00125 ltime = (long) ptm->tm_min + ltime / 60; 00126 ptm->tm_min = (int) (ltime % 60); 00127 if (ptm->tm_min < 0) { 00128 ptm->tm_min += 60; 00129 ltime -= 60; 00130 } 00131 00132 ltime = (long) ptm->tm_hour + ltime / 60; 00133 ptm->tm_hour = (int) (ltime % 24); 00134 if (ptm->tm_hour < 0) { 00135 ptm->tm_hour += 24; 00136 ltime -= 24; 00137 } 00138 00139 ltime /= 24; 00140 00141 if (ltime > 0L) { 00142 /* 00143 * There is no possibility of overflowing the tm_mday 00144 * and tm_yday fields since the date can be no later 00145 * than January 19. 00146 */ 00147 ptm->tm_wday = (ptm->tm_wday + ltime) % 7; 00148 ptm->tm_mday += ltime; 00149 ptm->tm_yday += ltime; 00150 } else if (ltime < 0L) { 00151 /* 00152 * It is possible to underflow the tm_mday and tm_yday 00153 * fields. If this happens, then adjusted date must 00154 * lie in December 1969. 00155 */ 00156 ptm->tm_wday = (ptm->tm_wday + 7 + ltime) % 7; 00157 if ((ptm->tm_mday += ltime) <= 0) { 00158 ptm->tm_mday += 31; 00159 ptm->tm_yday = 364; 00160 ptm->tm_mon = 11; 00161 ptm->tm_year--; 00162 } else { 00163 ptm->tm_yday += ltime; 00164 } 00165 } 00166 00167 00168 } 00169 return 0; 00170 } 00171 00172 00193 /* 00194 Note: This function is *not* thread safe, because it uses a static variable 00195 to store the calculated values. To be safe, you must surround the call to localtime 00196 _and_ the usage of the returned pointer with NutEnterCritical() and NutExitCritical()! 00197 Provided for compatibility to std c lib. 00198 */ 00199 tm *localtime(CONST time_t * timer) 00200 { 00201 if (localtime_r(timer, &_tb)) 00202 return NULL; 00203 else 00204 return &_tb; 00205 } 00206