00001 /* mkgmtime.c - make time corresponding to a GMT timeval struct 00002 $Id: mkgmtime.c,v 1.10 2003/10/22 18:50:12 rjs3 Exp $ 00003 00004 * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions 00008 * are met: 00009 * 00010 * 1. Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * 00013 * 2. Redistributions in binary form must reproduce the above copyright 00014 * notice, this list of conditions and the following disclaimer in 00015 * the documentation and/or other materials provided with the 00016 * distribution. 00017 * 00018 * 3. The name "Carnegie Mellon University" must not be used to 00019 * endorse or promote products derived from this software without 00020 * prior written permission. For permission or any other legal 00021 * details, please contact 00022 * Office of Technology Transfer 00023 * Carnegie Mellon University 00024 * 5000 Forbes Avenue 00025 * Pittsburgh, PA 15213-3890 00026 * (412) 268-4387, fax: (412) 268-7395 00027 * tech-transfer@andrew.cmu.edu 00028 * 00029 * 4. Redistributions of any form whatsoever must retain the following 00030 * acknowledgment: 00031 * "This product includes software developed by Computing Services 00032 * at Carnegie Mellon University (http://www.cmu.edu/computing/)." 00033 * 00034 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO 00035 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 00036 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE 00037 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 00038 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 00039 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 00040 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 00041 * 00042 * 00043 */ 00044 /* 00045 * Copyright (c) 1987, 1989, 1993 00046 * The Regents of the University of California. All rights reserved. 00047 * 00048 * This code is derived from software contributed to Berkeley by 00049 * Arthur David Olson of the National Cancer Institute. 00050 * 00051 * Redistribution and use in source and binary forms, with or without 00052 * modification, are permitted provided that the following conditions 00053 * are met: 00054 * 1. Redistributions of source code must retain the above copyright 00055 * notice, this list of conditions and the following disclaimer. 00056 * 2. Redistributions in binary form must reproduce the above copyright 00057 * notice, this list of conditions and the following disclaimer in the 00058 * documentation and/or other materials provided with the distribution. 00059 * 3. All advertising materials mentioning features or use of this software 00060 * must display the following acknowledgement: 00061 * This product includes software developed by the University of 00062 * California, Berkeley and its contributors. 00063 * 4. Neither the name of the University nor the names of its contributors 00064 * may be used to endorse or promote products derived from this software 00065 * without specific prior written permission. 00066 * 00067 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 00068 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00069 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00070 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 00071 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00072 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00073 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00074 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00075 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00076 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00077 * SUCH DAMAGE. 00078 */ 00079 00080 /* 00081 ** Adapted from code provided by Robert Elz, who writes: 00082 ** The "best" way to do mktime I think is based on an idea of Bob 00083 ** Kridle's (so its said...) from a long time ago. (mtxinu!kridle now). 00084 ** It does a binary search of the time_t space. Since time_t's are 00085 ** just 32 bits, its a max of 32 iterations (even at 64 bits it 00086 ** would still be very reasonable). 00087 */ 00088 00089 #include "ublox_gps/mkgmtime.h" 00090 #ifndef WRONG 00091 #define WRONG (-1) 00092 #endif /* !defined WRONG */ 00093 00094 static int tmcomp(register const struct tm * const atmp, 00095 register const struct tm * const btmp) 00096 { 00097 register int result; 00098 00099 if ((result = (atmp->tm_year - btmp->tm_year)) == 0 && 00100 (result = (atmp->tm_mon - btmp->tm_mon)) == 0 && 00101 (result = (atmp->tm_mday - btmp->tm_mday)) == 0 && 00102 (result = (atmp->tm_hour - btmp->tm_hour)) == 0 && 00103 (result = (atmp->tm_min - btmp->tm_min)) == 0) 00104 result = atmp->tm_sec - btmp->tm_sec; 00105 return result; 00106 } 00107 00108 time_t mkgmtime(struct tm * const tmp) { 00109 register int dir; 00110 register int bits; 00111 register int saved_seconds; 00112 time_t t; 00113 struct tm yourtm, *mytm; 00114 00115 yourtm = *tmp; 00116 saved_seconds = yourtm.tm_sec; 00117 yourtm.tm_sec = 0; 00118 /* 00119 ** Calculate the number of magnitude bits in a time_t 00120 ** (this works regardless of whether time_t is 00121 ** signed or unsigned, though lint complains if unsigned). 00122 */ 00123 for (bits = 0, t = 1; t > 0; ++bits, t <<= 1) 00124 ; 00125 /* 00126 ** If time_t is signed, then 0 is the median value, 00127 ** if time_t is unsigned, then 1 << bits is median. 00128 */ 00129 t = (t < 0) ? 0 : ((time_t) 1 << bits); 00130 00131 /* Some gmtime() implementations are broken and will return 00132 * NULL for time_ts larger than 40 bits even on 64-bit platforms 00133 * so we'll just cap it at 40 bits */ 00134 if(bits > 40) bits = 40; 00135 00136 for ( ; ; ) { 00137 mytm = gmtime(&t); 00138 00139 if(!mytm) return WRONG; 00140 00141 dir = tmcomp(mytm, &yourtm); 00142 if (dir != 0) { 00143 if (bits-- < 0) 00144 return WRONG; 00145 if (bits < 0) 00146 --t; 00147 else if (dir > 0) 00148 t -= (time_t) 1 << bits; 00149 else t += (time_t) 1 << bits; 00150 continue; 00151 } 00152 break; 00153 } 00154 t += saved_seconds; 00155 return t; 00156 }