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