1: /* 2: * mktime - convert local time into calendar time 3: */ 4: /* $Header: mktime.c,v 1.5 91/04/22 13:20:54 ceriel Exp $ */ 5: 6: /* Michael A. Temari <temari@ix.netcom.com> 03/01/96 */ 7: /* - fixed bug is structure fixup code */ 8: 9: #include <time.h> 10: #include <limits.h> 11: #include "loc_time.h" 12: 13: /* The code assumes that unsigned long can be converted to time_t. 14: * A time_t should not be wider than unsigned long, since this would mean 15: * that the check for overflow at the end could fail. 16: */ 17: time_t 18: mktime(register struct tm *timep) 19: { 20: register long day, year; 21: register int tm_year; 22: int yday, month; 23: register unsigned long seconds; 24: int overflow; 25: unsigned dst; 26: 27: timep->tm_min += timep->tm_sec / 60; 28: timep->tm_sec %= 60; 29: if (timep->tm_sec < 0) { 30: timep->tm_sec += 60; 31: timep->tm_min--; 32: } 33: timep->tm_hour += timep->tm_min / 60; 34: timep->tm_min = timep->tm_min % 60; 35: if (timep->tm_min < 0) { 36: timep->tm_min += 60; 37: timep->tm_hour--; 38: } 39: day = timep->tm_hour / 24; 40: timep->tm_hour= timep->tm_hour % 24; 41: if (timep->tm_hour < 0) { 42: timep->tm_hour += 24; 43: day--; 44: } 45: timep->tm_year += timep->tm_mon / 12; 46: timep->tm_mon %= 12; 47: if (timep->tm_mon < 0) { 48: timep->tm_mon += 12; 49: timep->tm_year--; 50: } 51: day += (timep->tm_mday - 1); 52: while (day < 0) { 53: if(--timep->tm_mon < 0) { 54: timep->tm_year--; 55: timep->tm_mon = 11; 56: } 57: day += _ytab[LEAPYEAR(YEAR0 + timep->tm_year)][timep->tm_mon]; 58: } 59: while (day >= _ytab[LEAPYEAR(YEAR0 + timep->tm_year)][timep->tm_mon]) { 60: day -= _ytab[LEAPYEAR(YEAR0 + timep->tm_year)][timep->tm_mon]; 61: if (++(timep->tm_mon) == 12) { 62: timep->tm_mon = 0; 63: timep->tm_year++; 64: } 65: } 66: timep->tm_mday = day + 1; 67: _tzset(); /* set timezone and dst info */ 68: year = EPOCH_YR; 69: if (timep->tm_year < year - YEAR0) return (time_t)-1; 70: seconds = 0; 71: day = 0; /* means days since day 0 now */ 72: overflow = 0; 73: 74: /* Assume that when day becomes negative, there will certainly 75: * be overflow on seconds. 76: * The check for overflow needs not to be done for leapyears 77: * divisible by 400. 78: * The code only works when year (1970) is not a leapyear. 79: */ 80: #if EPOCH_YR != 1970 81: #error EPOCH_YR != 1970 82: #endif 83: tm_year = timep->tm_year + YEAR0; 84: 85: if (LONG_MAX / 365 < tm_year - year) overflow++; 86: day = (tm_year - year) * 365; 87: if (LONG_MAX - day < (tm_year - year) / 4 + 1) overflow++; 88: day += (tm_year - year) / 4 89: + ((tm_year % 4) && tm_year % 4 < year % 4); 90: day -= (tm_year - year) / 100 91: + ((tm_year % 100) && tm_year % 100 < year % 100); 92: day += (tm_year - year) / 400 93: + ((tm_year % 400) && tm_year % 400 < year % 400); 94: 95: yday = month = 0; 96: while (month < timep->tm_mon) { 97: yday += _ytab[LEAPYEAR(tm_year)][month]; 98: month++; 99: } 100: yday += (timep->tm_mday - 1); 101: if (day + yday < 0) overflow++; 102: day += yday; 103: 104: timep->tm_yday = yday; 105: timep->tm_wday = (day + 4) % 7; /* day 0 was thursday (4) */ 106: 107: seconds = ((timep->tm_hour * 60L) + timep->tm_min) * 60L + timep->tm_sec; 108: 109: if ((TIME_MAX - seconds) / SECS_DAY < day) overflow++; 110: seconds += day * SECS_DAY; 111: 112: /* Now adjust according to timezone and daylight saving time */ 113: 114: if (((_timezone > 0) && (TIME_MAX - _timezone < seconds)) 115: || ((_timezone < 0) && (seconds < -_timezone))) 116: overflow++; 117: seconds += _timezone; 118: 119: if (timep->tm_isdst < 0) 120: dst = _dstget(timep); 121: else if (timep->tm_isdst) 122: dst = _dst_off; 123: else dst = 0; 124: 125: if (dst > seconds) overflow++; /* dst is always non-negative */ 126: seconds -= dst; 127: 128: if (overflow) return (time_t)-1; 129: 130: if ((time_t)seconds != seconds) return (time_t)-1; 131: return (time_t)seconds; 132: }