|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1980 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #if defined(LIBC_SCCS) && !defined(lint) ! 8: static char sccsid[] = "@(#)ctime.c 5.5 (Berkeley) 3/9/86"; ! 9: #endif LIBC_SCCS and not lint ! 10: ! 11: /* ! 12: * This routine converts time as follows. ! 13: * The epoch is 0000 Jan 1 1970 GMT. ! 14: * The argument time is in seconds since then. ! 15: * The localtime(t) entry returns a pointer to an array ! 16: * containing ! 17: * seconds (0-59) ! 18: * minutes (0-59) ! 19: * hours (0-23) ! 20: * day of month (1-31) ! 21: * month (0-11) ! 22: * year-1970 ! 23: * weekday (0-6, Sun is 0) ! 24: * day of the year ! 25: * daylight savings flag ! 26: * ! 27: * The routine calls the system to determine the local ! 28: * timezone and whether Daylight Saving Time is permitted locally. ! 29: * (DST is then determined by the current local rules) ! 30: * ! 31: * The routine does not work ! 32: * in Saudi Arabia which runs on Solar time. ! 33: * ! 34: * asctime(tvec)) ! 35: * where tvec is produced by localtime ! 36: * returns a ptr to a character string ! 37: * that has the ascii time in the form ! 38: * Thu Jan 01 00:00:00 1970\n\0 ! 39: * 0123456789012345678901234 5 ! 40: * 0 1 2 ! 41: * ! 42: * ctime(t) just calls localtime, then asctime. ! 43: */ ! 44: ! 45: #include <sys/time.h> ! 46: #include <sys/types.h> ! 47: #include <sys/timeb.h> ! 48: ! 49: static char cbuf[26]; ! 50: static int dmsize[12] = ! 51: { ! 52: 31, ! 53: 28, ! 54: 31, ! 55: 30, ! 56: 31, ! 57: 30, ! 58: 31, ! 59: 31, ! 60: 30, ! 61: 31, ! 62: 30, ! 63: 31 ! 64: }; ! 65: ! 66: /* ! 67: * The following table is used for 1974 and 1975 and ! 68: * gives the day number of the first day after the Sunday of the ! 69: * change. ! 70: */ ! 71: struct dstab { ! 72: int dayyr; ! 73: int daylb; ! 74: int dayle; ! 75: }; ! 76: ! 77: static struct dstab usdaytab[] = { ! 78: 1974, 5, 333, /* 1974: Jan 6 - last Sun. in Nov */ ! 79: 1975, 58, 303, /* 1975: Last Sun. in Feb - last Sun in Oct */ ! 80: 0, 119, 303, /* all other years: end Apr - end Oct */ ! 81: }; ! 82: static struct dstab ausdaytab[] = { ! 83: 1970, 400, 0, /* 1970: no daylight saving at all */ ! 84: 1971, 303, 0, /* 1971: daylight saving from Oct 31 */ ! 85: 1972, 303, 58, /* 1972: Jan 1 -> Feb 27 & Oct 31 -> dec 31 */ ! 86: 0, 303, 65, /* others: -> Mar 7, Oct 31 -> */ ! 87: }; ! 88: ! 89: /* ! 90: * The European tables ... based on hearsay ! 91: * Believed correct for: ! 92: * WE: Great Britain, Portugal? ! 93: * ME: Belgium, Luxembourg, Netherlands, Denmark, Norway, ! 94: * Austria, Poland, Czechoslovakia, Sweden, Switzerland, ! 95: * DDR, DBR, France, Spain, Hungary, Italy, Jugoslavia ! 96: * Finland (EE timezone, but ME dst rules) ! 97: * Eastern European dst is unknown, we'll make it ME until someone speaks up. ! 98: * EE: Bulgaria, Greece, Rumania, Turkey, Western Russia ! 99: * ! 100: * Ireland is unpredictable. (Years when Easter Sunday just happens ...) ! 101: * Years before 1983 are suspect. ! 102: */ ! 103: static struct dstab wedaytab[] = { ! 104: 1983, 89, 296, /* 1983: end March - end Oct */ ! 105: 0, 89, 303, /* others: end March - end Oct */ ! 106: }; ! 107: ! 108: static struct dstab medaytab[] = { ! 109: 1983, 89, 296, /* 1983: end March - end Oct */ ! 110: 0, 89, 272, /* others: end March - end Sep */ ! 111: }; ! 112: ! 113: /* ! 114: * Canada, same as the US, except no early 70's fluctuations. ! 115: * Can this really be right ?? ! 116: */ ! 117: static struct dstab candaytab[] = { ! 118: 0, 119, 303, /* all years: end Apr - end Oct */ ! 119: }; ! 120: ! 121: static struct dayrules { ! 122: int dst_type; /* number obtained from system */ ! 123: int dst_hrs; /* hours to add when dst on */ ! 124: struct dstab * dst_rules; /* one of the above */ ! 125: enum {STH,NTH} dst_hemi; /* southern, northern hemisphere */ ! 126: } dayrules [] = { ! 127: DST_USA, 1, usdaytab, NTH, ! 128: DST_AUST, 1, ausdaytab, STH, ! 129: DST_WET, 1, wedaytab, NTH, ! 130: DST_MET, 1, medaytab, NTH, ! 131: DST_EET, 1, medaytab, NTH, /* XXX */ ! 132: DST_CAN, 1, candaytab, NTH, ! 133: -1, ! 134: }; ! 135: ! 136: struct tm *gmtime(); ! 137: char *ct_numb(); ! 138: struct tm *localtime(); ! 139: char *ctime(); ! 140: char *ct_num(); ! 141: char *asctime(); ! 142: ! 143: char * ! 144: ctime(t) ! 145: time_t *t; ! 146: { ! 147: return(asctime(localtime(t))); ! 148: } ! 149: ! 150: struct tm * ! 151: localtime(tim) ! 152: time_t *tim; ! 153: { ! 154: register int dayno; ! 155: register struct tm *ct; ! 156: register dalybeg, daylend; ! 157: register struct dayrules *dr; ! 158: register struct dstab *ds; ! 159: int year; ! 160: time_t copyt; ! 161: struct timeval curtime; ! 162: static struct timezone zone; ! 163: static int init = 0; ! 164: ! 165: if (!init) { ! 166: gettimeofday(&curtime, &zone); ! 167: init++; ! 168: } ! 169: copyt = *tim - (time_t)zone.tz_minuteswest*60; ! 170: ct = gmtime(©t); ! 171: dayno = ct->tm_yday; ! 172: for (dr = dayrules; dr->dst_type >= 0; dr++) ! 173: if (dr->dst_type == zone.tz_dsttime) ! 174: break; ! 175: if (dr->dst_type >= 0) { ! 176: year = ct->tm_year + 1900; ! 177: for (ds = dr->dst_rules; ds->dayyr; ds++) ! 178: if (ds->dayyr == year) ! 179: break; ! 180: dalybeg = ds->daylb; /* first Sun after dst starts */ ! 181: daylend = ds->dayle; /* first Sun after dst ends */ ! 182: dalybeg = sunday(ct, dalybeg); ! 183: daylend = sunday(ct, daylend); ! 184: switch (dr->dst_hemi) { ! 185: case NTH: ! 186: if (!( ! 187: (dayno>dalybeg || (dayno==dalybeg && ct->tm_hour>=2)) && ! 188: (dayno<daylend || (dayno==daylend && ct->tm_hour<1)) ! 189: )) ! 190: return(ct); ! 191: break; ! 192: case STH: ! 193: if (!( ! 194: (dayno>dalybeg || (dayno==dalybeg && ct->tm_hour>=2)) || ! 195: (dayno<daylend || (dayno==daylend && ct->tm_hour<2)) ! 196: )) ! 197: return(ct); ! 198: break; ! 199: default: ! 200: return(ct); ! 201: } ! 202: copyt += dr->dst_hrs*60*60; ! 203: ct = gmtime(©t); ! 204: ct->tm_isdst++; ! 205: } ! 206: return(ct); ! 207: } ! 208: ! 209: /* ! 210: * The argument is a 0-origin day number. ! 211: * The value is the day number of the last ! 212: * Sunday on or before the day. ! 213: */ ! 214: static ! 215: sunday(t, d) ! 216: register struct tm *t; ! 217: register int d; ! 218: { ! 219: if (d >= 58) ! 220: d += dysize(t->tm_year) - 365; ! 221: return(d - (d - t->tm_yday + t->tm_wday + 700) % 7); ! 222: } ! 223: ! 224: struct tm * ! 225: gmtime(tim) ! 226: time_t *tim; ! 227: { ! 228: register int d0, d1; ! 229: long hms, day; ! 230: register int *tp; ! 231: static struct tm xtime; ! 232: ! 233: /* ! 234: * break initial number into days ! 235: */ ! 236: hms = *tim % 86400; ! 237: day = *tim / 86400; ! 238: if (hms<0) { ! 239: hms += 86400; ! 240: day -= 1; ! 241: } ! 242: tp = (int *)&xtime; ! 243: ! 244: /* ! 245: * generate hours:minutes:seconds ! 246: */ ! 247: *tp++ = hms%60; ! 248: d1 = hms/60; ! 249: *tp++ = d1%60; ! 250: d1 /= 60; ! 251: *tp++ = d1; ! 252: ! 253: /* ! 254: * day is the day number. ! 255: * generate day of the week. ! 256: * The addend is 4 mod 7 (1/1/1970 was Thursday) ! 257: */ ! 258: ! 259: xtime.tm_wday = (day+7340036)%7; ! 260: ! 261: /* ! 262: * year number ! 263: */ ! 264: if (day>=0) for(d1=70; day >= dysize(d1); d1++) ! 265: day -= dysize(d1); ! 266: else for (d1=70; day<0; d1--) ! 267: day += dysize(d1-1); ! 268: xtime.tm_year = d1; ! 269: xtime.tm_yday = d0 = day; ! 270: ! 271: /* ! 272: * generate month ! 273: */ ! 274: ! 275: if (dysize(d1)==366) ! 276: dmsize[1] = 29; ! 277: for(d1=0; d0 >= dmsize[d1]; d1++) ! 278: d0 -= dmsize[d1]; ! 279: dmsize[1] = 28; ! 280: *tp++ = d0+1; ! 281: *tp++ = d1; ! 282: xtime.tm_isdst = 0; ! 283: return(&xtime); ! 284: } ! 285: ! 286: char * ! 287: asctime(t) ! 288: struct tm *t; ! 289: { ! 290: register char *cp, *ncp; ! 291: register int *tp; ! 292: ! 293: cp = cbuf; ! 294: for (ncp = "Day Mon 00 00:00:00 1900\n"; *cp++ = *ncp++;); ! 295: ncp = &"SunMonTueWedThuFriSat"[3*t->tm_wday]; ! 296: cp = cbuf; ! 297: *cp++ = *ncp++; ! 298: *cp++ = *ncp++; ! 299: *cp++ = *ncp++; ! 300: cp++; ! 301: tp = &t->tm_mon; ! 302: ncp = &"JanFebMarAprMayJunJulAugSepOctNovDec"[(*tp)*3]; ! 303: *cp++ = *ncp++; ! 304: *cp++ = *ncp++; ! 305: *cp++ = *ncp++; ! 306: cp = ct_numb(cp, *--tp); ! 307: cp = ct_numb(cp, *--tp+100); ! 308: cp = ct_numb(cp, *--tp+100); ! 309: cp = ct_numb(cp, *--tp+100); ! 310: if (t->tm_year>=100) { ! 311: cp[1] = '2'; ! 312: cp[2] = '0' + (t->tm_year-100) / 100; ! 313: } ! 314: cp += 2; ! 315: cp = ct_numb(cp, t->tm_year+100); ! 316: return(cbuf); ! 317: } ! 318: ! 319: dysize(y) ! 320: { ! 321: if((y%4) == 0) ! 322: return(366); ! 323: return(365); ! 324: } ! 325: ! 326: static char * ! 327: ct_numb(cp, n) ! 328: register char *cp; ! 329: { ! 330: cp++; ! 331: if (n>=10) ! 332: *cp++ = (n/10)%10 + '0'; ! 333: else ! 334: *cp++ = ' '; ! 335: *cp++ = n%10 + '0'; ! 336: return(cp); ! 337: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.