1: # 2: /* 3: * MAKETIME derive 32-bit time value from TM structure. 4: * 5: * Usage: 6: * long t,maketime(); 7: * struct tm *tp; Pointer to TM structure from <time.h> 8: * NOTE: this must be extended version!!! 9: * t = maketime(tp); 10: * 11: * Returns: 12: * 0 if failure; parameter out of range or nonsensical. 13: * else long time-value. 14: * Notes: 15: * This code is quasi-public; it may be used freely in like software. 16: * It is not to be sold, nor used in licensed software without 17: * permission of the author. 18: * For everyone's benefit, please report bugs and improvements! 19: * Copyright 1981 by Ken Harrenstien, SRI International. 20: * (ARPANET: KLH @ SRI) 21: */ 22: #ifndef lint 23: static char rcsid[]= "$Id: maketime.c,v 1.6 87/12/18 17:05:58 narten Exp $"; 24: #endif 25: /* $Log: maketime.c,v $ 26: * Revision 1.6 87/12/18 17:05:58 narten 27: * include rcsparam.h 28: * 29: * Revision 1.5 87/12/18 11:35:51 narten 30: * maketime.c: fixed USG code - you have tgo call "tzset" in order to have 31: * "timezone" set. ("localtime" calls it, but it's probably better not to 32: * count on "localtime" having been called.) 33: * 34: * Revision 1.4 87/10/18 10:26:57 narten 35: * Updating version numbers. Changes relative to 1.0 are actually 36: * relative to 1.2 37: * 38: * Revision 1.3 87/09/24 13:58:45 narten 39: * Sources now pass through lint (if you ignore printf/sprintf/fprintf 40: * warnings) 41: * 42: * Revision 1.2 87/03/27 14:21:48 jenkins 43: * Port to suns 44: * 45: * Revision 1.1 84/01/23 14:50:04 kcs 46: * Initial revision 47: * 48: * Revision 1.2 83/12/05 10:12:56 wft 49: * added cond. compilation for USG Unix; long timezone; 50: * 51: * Revision 1.1 82/05/06 11:38:00 wft 52: * Initial revision 53: * 54: */ 55: 56: 57: #include "rcsbase.h" 58: #include "time.h" 59: 60: int daytb[] = { /* # days in year thus far, indexed by month (0-12!!) */ 61: 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 62: }; 63: 64: struct tm *localtime(); 65: long time(); 66: 67: long maketime(atm) 68: struct tm *atm; 69: { register struct tm *tp; 70: register int i; 71: int year, yday, mon, day, hour, min, sec, zone, dst, leap; 72: long tres, curtim; 73: 74: VOID time(&curtim); 75: tp = localtime(&curtim); /* Get breakdowns of current time */ 76: year = tp->tm_year; /* Use to set up defaults */ 77: mon = tp->tm_mon; 78: day = tp->tm_mday; 79: 80: 81: #ifdef DEBUG 82: printf("first YMD: %d %d %d, T=%ld\n",year,mon,day,tres); 83: #endif DEBUG 84: tp = atm; 85: 86: /* First must find date, using specified year, month, day. 87: * If one of these is unspecified, it defaults either to the 88: * current date (if no more global spec was given) or to the 89: * zero-value for that spec (i.e. a more global spec was seen). 90: * Start with year... note 32 bits can only handle 135 years. 91: */ 92: if(tp->tm_year != TMNULL) 93: { if((year = tp->tm_year) >= 1900) /* Allow full yr # */ 94: year -= 1900; /* by making kosher */ 95: mon = 0; /* Since year was given, default */ 96: day = 1; /* for remaining specs is zero */ 97: } 98: if(year < 70 || 70+134 < year ) /* Check range */ 99: return(0); /* ERR: year out of range */ 100: leap = year&03 ? 0 : 1; /* See if leap year */ 101: year -= 70; /* UNIX time starts at 1970 */ 102: 103: /* 104: * Find day of year. 105: * YDAY is used only if it exists and either the month or day-of-month 106: * is missing. 107: */ 108: if (tp->tm_yday != TMNULL 109: && (tp->tm_mon == TMNULL || tp->tm_mday == TMNULL)) 110: yday = tp->tm_yday; 111: else 112: { if(tp->tm_mon != TMNULL) 113: { mon = tp->tm_mon; /* Month was specified */ 114: day = 1; /* so set remaining default */ 115: } 116: if(mon < 0 || 11 < mon) return(0); /* ERR: bad month */ 117: if(tp->tm_mday != TMNULL) day = tp->tm_mday; 118: if(day < 1 119: || (((daytb[mon+1]-daytb[mon]) < day) 120: && (day!=29 || mon!=1 || !leap) )) 121: return(0); /* ERR: bad day */ 122: yday = daytb[mon] /* Add # of days in months so far */ 123: + ((leap /* Leap year, and past Feb? If */ 124: && mon>1)? 1:0) /* so, add leap day for this year */ 125: + day-1; /* And finally add # days this mon */ 126: 127: if (tp->tm_yday != TMNULL /* Confirm that YDAY correct */ 128: && tp->tm_yday != yday) return(0); /* ERR: conflict */ 129: } 130: if(yday < 0 || (leap?366:365) <= yday) 131: return(0); /* ERR: bad YDAY or maketime bug */ 132: 133: tres = year*365 /* Get # days of years so far */ 134: + ((year+1)>>2) /* plus # of leap days since 1970 */ 135: + yday; /* and finally add # days this year */ 136: 137: if((i = tp->tm_wday) != TMNULL) /* Check WDAY if present */ 138: if(i < 0 || 6 < i /* Ensure within range */ 139: || i != (tres+4)%7) /* Matches? Jan 1,1970 was Thu = 4 */ 140: return(0); /* ERR: bad WDAY */ 141: 142: #ifdef DEBUG 143: printf("YMD: %d %d %d, T=%ld\n",year,mon,day,tres); 144: #endif DEBUG 145: /* 146: * Now determine time. If not given, default to zeros 147: * (since time is always the least global spec) 148: */ 149: tres *= 86400L; /* Get # seconds (24*60*60) */ 150: hour = min = sec = 0; 151: if(tp->tm_hour != TMNULL) hour = tp->tm_hour; 152: if(tp->tm_min != TMNULL) min = tp->tm_min; 153: if(tp->tm_sec != TMNULL) sec = tp->tm_sec; 154: if( min < 0 || 60 <= min 155: || sec < 0 || 60 <= sec) return(0); /* ERR: MS out of range */ 156: if(hour < 0 || 24 <= hour) 157: if(hour != 24 || (min+sec) !=0) /* Allow 24:00 */ 158: return(0); /* ERR: H out of range */ 159: 160: /* confirm AM/PM if there */ 161: switch(tp->tm_ampm) 162: { case 0: case TMNULL: /* Ignore these values */ 163: break; 164: case 1: /* AM */ 165: case 2: /* PM */ 166: if(hour > 12) return(0); /* ERR: hrs 13-23 bad */ 167: if(hour ==12) hour = 0; /* Modulo 12 */ 168: if(tp->tm_ampm == 2) /* If PM, then */ 169: hour += 12; /* get 24-hour time */ 170: break; 171: default: return(0); /* ERR: illegal TM_AMPM value */ 172: } 173: 174: tres += sec + 60L*(min + 60L*hour); /* Add in # secs of time */ 175: 176: #ifdef DEBUG 177: printf("HMS: %d %d %d T=%ld\n",hour,min,sec,tres); 178: #endif DEBUG 179: /* 180: * We now have the GMT date/time and must make final 181: * adjustment for the specified time zone. If none is specified, 182: * the local time-zone is assumed. 183: */ 184: if((zone = tp->tm_zon) == TMNULL /* If unspecified */ 185: || (zone == 1)) /* or local-zone requested */ 186: zone = localzone(); /* then set to local zone */ 187: if(zone < 0 || 24*60 <= zone) 188: return(0); /* ERR: zone out of range */ 189: 190: /* See if must apply Daylight Saving Time shift. 191: * Note that if DST is specified, validity is not checked. 192: */ 193: if((dst = tp->tm_isdst) == TMNULL) /* Must we figure it out? */ 194: { curtim = tres +localzone()*60L; /* Yuck. Get equiv local */ 195: dst = localtime(&curtim)->tm_isdst; /* time, and ask. */ 196: } 197: tres += zone*60L -(dst?3600:0); /* Add in # seconds of zone adj */ 198: 199: return(tres); 200: } 201: 202: 203: /* LOCALZONE return local timezone in # mins west of GMT 204: * 205: */ 206: 207: #ifdef V6 208: extern long timezone; 209: #else 210: #ifdef USG 211: extern long timezone; 212: #else /* V7 */ 213: #include <sys/types.h> 214: #include <sys/timeb.h> 215: #endif USG 216: #endif V6 217: 218: int _lclzon = -1; 219: localzone() 220: { 221: #ifdef V6 222: return(_lclzon >= 0 ? _lclzon : (_lclzon = timezone/60L)); 223: #else 224: #ifdef USG 225: tzset(); 226: return(_lclzon >= 0 ? _lclzon : (_lclzon = timezone/60L)); 227: #else /* V7 */ 228: struct timeb tb; 229: 230: if(_lclzon < 0) 231: { ftime(&tb); 232: _lclzon = tb.timezone; 233: } 234: return(_lclzon); 235: 236: #endif USG 237: #endif V6 238: }