1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2009 AT&T Intellectual Property * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Intellectual Property * 8 * * 9 * A copy of the License is available at * 10 * http://www.opensource.org/licenses/cpl1.0.txt * 11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12 * * 13 * Information and Software Systems Research * 14 * AT&T Research * 15 * Florham Park NJ * 16 * * 17 * Glenn Fowler <gsf@research.att.com> * 18 * David Korn <dgk@research.att.com> * 19 * Phong Vo <kpv@research.att.com> * 20 * * 21 ***********************************************************************/ 22 #pragma prototyped 23 /* 24 * Glenn Fowler 25 * AT&T Research 26 * 27 * Time_t conversion support 28 */ 29 30 #include <tmx.h> 31 32 #include "FEATURE/tmlib" 33 34 /* 35 * convert Tm_t to Time_t 36 * 37 * if west==TM_LOCALZONE then the local timezone is used 38 * otherwise west is the number of minutes west 39 * of GMT with DST taken into account 40 * 41 * this routine works with a copy of Tm_t to avoid clashes 42 * with other tm*() that may return static Tm_t* 43 */ 44 45 Time_t 46 tmxtime(register Tm_t* tm, int west) 47 { 48 register Time_t t; 49 register Tm_leap_t* lp; 50 register int32_t y; 51 int n; 52 int sec; 53 time_t now; 54 struct tm* tl; 55 Tm_t* to; 56 Tm_t ts; 57 58 ts = *tm; 59 to = tm; 60 tm = &ts; 61 tmset(tm_info.zone); 62 tmfix(tm); 63 y = tm->tm_year; 64 if (y < 69 || y > (TMX_MAXYEAR - 1900)) 65 return TMX_NOTIME; 66 y--; 67 t = y * 365 + y / 4 - y / 100 + (y + (1900 - 1600)) / 400 - (1970 - 1901) * 365 - (1970 - 1901) / 4; 68 if ((n = tm->tm_mon) > 11) 69 n = 11; 70 y += 1901; 71 if (n > 1 && tmisleapyear(y)) 72 t++; 73 t += tm_data.sum[n] + tm->tm_mday - 1; 74 t *= 24; 75 t += tm->tm_hour; 76 t *= 60; 77 t += tm->tm_min; 78 t *= 60; 79 t += sec = tm->tm_sec; 80 if (west != TM_UTCZONE && !(tm_info.flags & TM_UTC)) 81 { 82 /* 83 * time zone adjustments 84 */ 85 86 if (west == TM_LOCALZONE) 87 { 88 t += tm_info.zone->west * 60; 89 if (!tm_info.zone->daylight) 90 tm->tm_isdst = 0; 91 else 92 { 93 y = tm->tm_year; 94 tm->tm_year = tmequiv(tm) - 1900; 95 now = tmxsec(tmxtime(tm, tm_info.zone->west)); 96 tm->tm_year = y; 97 if (!(tl = tmlocaltime(&now))) 98 return TMX_NOTIME; 99 if (tm->tm_isdst = tl->tm_isdst) 100 t += tm_info.zone->dst * 60; 101 } 102 } 103 else 104 { 105 t += west * 60; 106 if (!tm_info.zone->daylight) 107 tm->tm_isdst = 0; 108 else if (tm->tm_isdst < 0) 109 { 110 y = tm->tm_year; 111 tm->tm_year = tmequiv(tm) - 1900; 112 tm->tm_isdst = 0; 113 now = tmxsec(tmxtime(tm, tm_info.zone->west)); 114 tm->tm_year = y; 115 if (!(tl = tmlocaltime(&now))) 116 return TMX_NOTIME; 117 tm->tm_isdst = tl->tm_isdst; 118 } 119 } 120 } 121 else if (tm->tm_isdst) 122 tm->tm_isdst = 0; 123 *to = *tm; 124 if (tm_info.flags & TM_LEAP) 125 { 126 /* 127 * leap second adjustments 128 */ 129 130 for (lp = &tm_data.leap[0]; t < lp->time - (lp+1)->total; lp++); 131 t += lp->total; 132 n = lp->total - (lp+1)->total; 133 if (t <= (lp->time + n) && (n > 0 && sec > 59 || n < 0 && sec > (59 + n) && sec <= 59)) 134 t -= n; 135 } 136 return tmxsns(t, tm->tm_nsec); 137 } 138