|
|
1.1 ! root 1: /* ! 2: * Convert time to ascii representation ! 3: * ! 4: * Pseudo system-5, employs TIMEZONE environment for gmt offset, ! 5: * timezone abbreviations, and daylight savings time information. ! 6: * TIMEZONE=SSS:mmm:DDD:n.d.m:n.d.m:h:m ! 7: * SSS - Standard timezone abbreviation up to 31 characters long ! 8: * mmm - minutes west of GMT ! 9: * DDD - Daylight timezone abbreviation also 31 characters ! 10: * n.d.m - n'th occurrence of d'th day of week in m'th month of ! 11: * start and end of daylight savings time. Negative n indicates ! 12: * counting backwards from end of month. Zero n indicates absolute date, ! 13: * d'th day of m'th month. Days and months from 1 to n. ! 14: * h - Hour of change from standard to daylight. ! 15: * m - Minutes of adjustment at change. ! 16: * Example - Central standard in current US conventions: ! 17: * TIMEZONE=CST:3600:CDT:-1.1.4:-1.1.10:2:60 ! 18: * Only the first two fields are required. ! 19: * If no daylight timezone is specified, then no daylight conversion is done. ! 20: * If no dates for daylight are given, they default to 83-05-10 US standard. ! 21: * If no hour of daylight time change is specified, it defaults to 2AM. ! 22: * If no minutes of adjustment is specified, it defaults to 60. ! 23: * These defaults can be changed by overwriting tzdstdef[]. ! 24: */ ! 25: ! 26: ! 27: #include <time.h> ! 28: #include <sys/timeb.h> ! 29: ! 30: ! 31: #define FEB 1 ! 32: #define NWDAY 7 /* Number of weekdays */ ! 33: #define NMON 12 /* Number of months */ ! 34: #define todigit(c) ((c)+'0') ! 35: ! 36: long timezone = 0L; ! 37: char tzname[2][32] = { "GMT", "" }; ! 38: char tzdstdef[] = "1.1.4:-1.1.10:2:60......"; ! 39: static struct dsttimes { ! 40: char dst_month, dst_day, dst_occur; ! 41: } dsttimes[2] = { ! 42: { 1, 0, 3 }, /* First sunday in april */ ! 43: { -1, 0, 9 } /* Last sunday in october */ ! 44: }; ! 45: static char dsthour = 2; ! 46: static char timestr[] = "AAA AAA DD DD:DD:DD DDDD\n"; ! 47: static char daynames[3*NWDAY+1] = "SunMonTueWedThuFriSat"; ! 48: static char months[3*NMON+1] = "JanFebMarAprMayJunJulAugSepOctNovDec"; ! 49: static char dpm[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; ! 50: static int dstadjust = 60*60; /* In seconds */ ! 51: static struct tm tm; ! 52: ! 53: /* Set the timezone parameters, once is enough */ ! 54: void ! 55: settz() ! 56: { ! 57: extern char *getenv(); ! 58: register char *cp1, *cp2; ! 59: static int settz = 0; ! 60: ! 61: if (settz++ > 0) ! 62: return; ! 63: if ((cp1 = getenv("TIMEZONE")) == ((char *)0)) ! 64: return; ! 65: timezone = 0; ! 66: ! 67: /* Read primary timezone name and nul terminate */ ! 68: cp2 = tzname[0]; ! 69: while (*cp1 && *cp1 != ':' && cp2 < &tzname[0][31]) ! 70: *cp2++ = *cp1++; ! 71: *cp2++ = 0; ! 72: while (*cp1 && *cp1++ != ':'); ! 73: ! 74: /* Read timezone offset and convert to seconds */ ! 75: timezone = (long)atoi(cp1) * 60L; ! 76: while (*cp1 && *cp1++ != ':'); ! 77: ! 78: /* Read daylight timezone name and nul terminate */ ! 79: cp2 = tzname[1]; ! 80: while (*cp1 && *cp1 != ':' && cp2 < &tzname[1][31]) ! 81: *cp2++ = *cp1++; ! 82: *cp2++ = 0; ! 83: while (*cp1 && *cp1++ != ':'); ! 84: ! 85: /* Exit if no daylight time */ ! 86: if (tzname[1][0] == 0) ! 87: return; ! 88: ! 89: /* Set default dst parameters */ ! 90: setdst(tzdstdef); ! 91: ! 92: /* Set supplied dst parameters */ ! 93: setdst(cp1); ! 94: } ! 95: ! 96: /* Parse and set dst parameters */ ! 97: static ! 98: setdst(cp1) register char *cp1; ! 99: { ! 100: /* Get optional start of daylight time */ ! 101: if (*cp1) { ! 102: dsttimes[0].dst_occur = atoi(cp1); ! 103: while (*cp1 && *cp1++ != '.'); ! 104: dsttimes[0].dst_day = atoi(cp1)-1; ! 105: while (*cp1 && *cp1++ != '.'); ! 106: dsttimes[0].dst_month = atoi(cp1)-1; ! 107: while (*cp1 && *cp1++ != ':'); ! 108: } ! 109: ! 110: /* Get optional end of daylight time */ ! 111: if (*cp1) { ! 112: dsttimes[1].dst_occur = atoi(cp1); ! 113: while (*cp1 && *cp1++ != '.'); ! 114: dsttimes[1].dst_day = atoi(cp1)-1; ! 115: while (*cp1 && *cp1++ != '.'); ! 116: dsttimes[1].dst_month = atoi(cp1)-1; ! 117: while (*cp1 && *cp1++ != ':'); ! 118: } ! 119: ! 120: /* Get optional hour of daylight time advance */ ! 121: if (*cp1) { ! 122: dsthour = atoi(cp1); ! 123: while (*cp1 && *cp1++ != ':'); ! 124: } ! 125: ! 126: /* Get optional minutes of adjustment */ ! 127: if (*cp1) ! 128: dstadjust = atoi(cp1) * 60; ! 129: } ! 130: ! 131: /* ! 132: * Most common interface, returns a static string ! 133: * which is a printable version of the time and date. ! 134: */ ! 135: char * ! 136: ctime(tp) ! 137: long *tp; ! 138: { ! 139: return (asctime(localtime(tp))); ! 140: } ! 141: ! 142: /* ! 143: * Do what gmtime does for the local timezone. ! 144: * And correct for daylight time. ! 145: */ ! 146: struct tm * ! 147: localtime(tp) ! 148: long *tp; ! 149: { ! 150: long ltime; ! 151: ! 152: settz(); ! 153: ltime = *tp - timezone; ! 154: gmtime(<ime); ! 155: /* ! 156: * If necessary, adjust for daylight saving time. ! 157: */ ! 158: if (isdaylight()) { ! 159: ltime = *tp - timezone + dstadjust; ! 160: gmtime(<ime); ! 161: tm.tm_isdst = (dstadjust != 0); ! 162: } else ! 163: tm.tm_isdst = 0; ! 164: return (&tm); ! 165: } ! 166: ! 167: /* ! 168: * Returns a printable version of the time ! 169: * which has been broken down as in the tm structure. ! 170: */ ! 171: char * ! 172: asctime(tmp) ! 173: struct tm *tmp; ! 174: { ! 175: register char *cp, *xp; ! 176: register unsigned i; ! 177: ! 178: cp = timestr; ! 179: /* ! 180: * Day of week ! 181: */ ! 182: if ((i = tmp->tm_wday) >= NWDAY) ! 183: i = 0; ! 184: xp = &daynames[i*3]; ! 185: *cp++ = *xp++; ! 186: *cp++ = *xp++; ! 187: *cp++ = *xp++; ! 188: *cp++ = ' '; ! 189: /* ! 190: * Month ! 191: */ ! 192: if ((i = tmp->tm_mon) >= NMON) ! 193: i = 0; ! 194: xp = &months[i*3]; ! 195: *cp++ = *xp++; ! 196: *cp++ = *xp++; ! 197: *cp++ = *xp++; ! 198: *cp++ = ' '; ! 199: /* ! 200: * Day of month ! 201: */ ! 202: if ((i = tmp->tm_mday) >= 10) ! 203: *cp++ = todigit(i/10); ! 204: else ! 205: *cp++ = ' '; ! 206: *cp++ = todigit(i%10); ! 207: *cp++ = ' '; ! 208: /* ! 209: * Hours:mins:seconds ! 210: */ ! 211: *cp++ = todigit((i = tmp->tm_hour)/10); ! 212: *cp++ = todigit(i%10); ! 213: *cp++ = ':'; ! 214: *cp++ = todigit((i = tmp->tm_min)/10); ! 215: *cp++ = todigit(i%10); ! 216: *cp++ = ':'; ! 217: *cp++ = todigit((i = tmp->tm_sec)/10); ! 218: *cp++ = todigit(i%10); ! 219: *cp++ = ' '; ! 220: /* ! 221: * Year ! 222: */ ! 223: i = tmp->tm_year + 1900; ! 224: *cp++ = todigit(i/1000); ! 225: i = i%1000; ! 226: *cp++ = todigit(i/100); ! 227: i = i%100; ! 228: *cp++ = todigit(i/10); ! 229: *cp++ = todigit(i%10); ! 230: *cp++ = '\n'; ! 231: *cp++ = '\0'; ! 232: return (timestr); ! 233: } ! 234: ! 235: /* ! 236: * Do conversions for Greenwich Mean Time to ! 237: * the tm structure. ! 238: */ ! 239: struct tm * ! 240: gmtime(tp) ! 241: long *tp; ! 242: { ! 243: long xtime; ! 244: unsigned days; ! 245: long secs; ! 246: int year; ! 247: int ydays; ! 248: int wday; ! 249: register char *mp; ! 250: ! 251: if ((xtime = *tp) < 0) ! 252: xtime = 0; ! 253: days = xtime/(60L*60L*24L); ! 254: secs = xtime%(60L*60L*24L); ! 255: tm.tm_hour = secs/(60L*60L); ! 256: secs = secs%(60L*60L); ! 257: tm.tm_min = secs/60; ! 258: tm.tm_sec = secs%60; ! 259: /* ! 260: * Start at Thursday (wday=4) Jan 1, 1970 (the Epoch) ! 261: * and calculate from there. ! 262: */ ! 263: wday = (4+days)%NWDAY; ! 264: year = 1970; ! 265: for (;;) { ! 266: ydays = isleap(year) ? 366 : 365; ! 267: if (days < ydays) ! 268: break; ! 269: year++; ! 270: days -= ydays; ! 271: } ! 272: tm.tm_year = year-1900; ! 273: tm.tm_yday = days; ! 274: tm.tm_wday = wday; ! 275: /* ! 276: * Setup february's #days now. ! 277: */ ! 278: if (isleap(year)) ! 279: dpm[FEB] = 29; ! 280: else ! 281: dpm[FEB] = 28; ! 282: for (mp = &dpm[0]; mp < &dpm[NMON] && days >= *mp; mp++) ! 283: days -= *mp; ! 284: tm.tm_mon = mp-dpm; ! 285: tm.tm_mday = days+1; ! 286: return (&tm); ! 287: } ! 288: ! 289: /* ! 290: * Return 1 on leap years; 0 otherwise. ! 291: */ ! 292: static ! 293: isleap(yr) ! 294: register yr; ! 295: { ! 296: if (yr%4000 == 0) ! 297: return (0); ! 298: if (yr%400==0 || (yr%100!=0 && yr%4==0)) ! 299: return (1); ! 300: return (0); ! 301: } ! 302: ! 303: /* ! 304: * Check for daylight savings time. ! 305: */ ! 306: static ! 307: isdaylight() ! 308: { ! 309: register int xday; ! 310: ! 311: if (tzname[1][0] == 0) /* No name, no daylight time */ ! 312: return (0); ! 313: if (tm.tm_mon < dsttimes[0].dst_month) ! 314: return (0); ! 315: else if (tm.tm_mon == dsttimes[0].dst_month) { ! 316: xday = nthday(&dsttimes[0]); ! 317: if (tm.tm_mday != xday) ! 318: return (tm.tm_mday > xday); ! 319: return (tm.tm_hour >= dsthour); ! 320: } else if (tm.tm_mon < dsttimes[1].dst_month) ! 321: return (1); ! 322: else if (tm.tm_mon == dsttimes[1].dst_month) { ! 323: xday = nthday(&dsttimes[1]); ! 324: if (tm.tm_mday != xday) ! 325: return (tm.tm_mday < xday); ! 326: return (tm.tm_hour < dsthour-1); ! 327: } ! 328: return (0); ! 329: } ! 330: ! 331: static ! 332: nthday(dp) ! 333: register struct dsttimes *dp; ! 334: { ! 335: register int nthday; ! 336: register int nth; ! 337: ! 338: if ((nth = dp->dst_occur) == 0) ! 339: return dp->dst_day; ! 340: nthday = tm.tm_mday - tm.tm_wday + dp->dst_day; ! 341: if (nth > 0) { ! 342: while (nthday > 0) ! 343: nthday -= 7; ! 344: do ! 345: nthday += 7; ! 346: while (--nth > 0); ! 347: } else { ! 348: while (nthday < dpm[tm.tm_mon]) ! 349: nthday += 7; ! 350: do ! 351: nthday -= 7; ! 352: while (++nth < 0); ! 353: } ! 354: return (nthday); ! 355: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.