|
|
1.1 root 1: /*
2: * This routine converts time as follows.
3: * The epoch is 0000 Jan 1 1970 GMT.
4: * The argument time is in seconds since then.
5: * The localtime(t) entry returns a pointer to an array
6: * containing
7: * seconds (0-59)
8: * minutes (0-59)
9: * hours (0-23)
10: * day of month (1-31)
11: * month (0-11)
12: * year-1970
13: * weekday (0-6, Sun is 0)
14: * day of the year
15: * daylight savings flag
16: *
17: * The routine calls the system to determine the local
18: * timezone and whether Daylight Saving Time is permitted locally.
19: * (DST is then determined by the current US standard rules)
20: * There is a table that accounts for the peculiarities
21: * undergone by daylight time in 1974-1975.
22: *
23: * The routine does not work
24: * in Saudi Arabia which runs on Solar time.
25: *
26: * asctime(tvec))
27: * where tvec is produced by localtime
28: * returns a ptr to a character string
29: * that has the ascii time in the form
30: * Thu Jan 01 00:00:00 1970n0\\
31: * 01234567890123456789012345
32: * 0 1 2
33: *
34: * ctime(t) just calls localtime, then asctime.
35: */
36:
37: #include <time.h>
38: #include <sys/types.h>
39: #include <sys/timeb.h>
40:
41: static char cbuf[26];
42: static int dmsize[12] =
43: {
44: 31,
45: 28,
46: 31,
47: 30,
48: 31,
49: 30,
50: 31,
51: 31,
52: 30,
53: 31,
54: 30,
55: 31
56: };
57:
58: #define NDAYTAB 10
59:
60: static int ndaytab;
61: static struct daytab {
62: unsigned char ybeg; /* year-1900 */
63: unsigned char yend;
64: unsigned char obeg; /* offset from sunday */
65: unsigned char oend;
66: short dbeg;
67: short dend;
68: } daytab[NDAYTAB];
69:
70: struct tm *gmtime();
71: char *ct_numb();
72: struct tm *localtime();
73: char *ctime();
74: char *ct_num();
75: char *asctime();
76:
77: char *
78: ctime(t)
79: long *t;
80: {
81: return(asctime(localtime(t)));
82: }
83:
84: struct tm *
85: localtime(tim)
86: long *tim;
87: {
88: register int dayno;
89: register struct tm *ct;
90: register daylbegin, daylend;
91: int boff, eoff;
92: register int i;
93: register int incr;
94: register int tmp;
95: long copyt;
96: struct timeb systime;
97:
98: ftime(&systime);
99: copyt = *tim - (long)systime.timezone*60;
100: ct = gmtime(©t);
101: if (systime.dstflag == 0)
102: return (ct);
103: dayno = ct->tm_yday;
104: daylbegin = 999; /* default: no dst */
105: daylend = 999;
106: incr = 1*60*60;
107: boff = eoff = 0;
108: rdaytab();
109: for (i = 0; i < ndaytab; i++)
110: if (daytab[i].ybeg <= ct->tm_year && ct->tm_year <= daytab[i].yend) {
111: daylbegin = daytab[i].dbeg;
112: daylend = daytab[i].dend;
113: boff = daytab[i].obeg;
114: eoff = daytab[i].oend;
115: break;
116: }
117: if (daylbegin > daylend) {
118: tmp = daylbegin;
119: daylbegin = daylend;
120: daylend = tmp;
121: copyt += incr;
122: incr = -incr;
123: }
124: daylbegin = sunday(ct, daylbegin)+boff;
125: daylend = sunday(ct, daylend)+eoff;
126: if ((dayno>daylbegin || (dayno==daylbegin && ct->tm_hour>=2)) &&
127: (dayno<daylend || (dayno==daylend && ct->tm_hour<1))) {
128: copyt += incr;
129: ct = gmtime(©t);
130: ct->tm_isdst++;
131: }
132: return(ct);
133: }
134:
135: /*
136: * The argument is a 0-origin day number.
137: * The value is the day number of the last
138: * Sunday before or after the day.
139: */
140: static
141: sunday(t, d)
142: register struct tm *t;
143: register int d;
144: {
145: if (d >= 58)
146: d += dysize(t->tm_year) - 365;
147: return(d - (d - t->tm_yday + t->tm_wday + 700) % 7);
148: }
149:
150: struct tm *
151: gmtime(tim)
152: long *tim;
153: {
154: register int d0, d1;
155: long hms, day;
156: register int *tp;
157: static struct tm xtime;
158:
159: /*
160: * break initial number into days
161: */
162: hms = *tim % 86400;
163: day = *tim / 86400;
164: if (hms<0) {
165: hms += 86400;
166: day -= 1;
167: }
168: tp = (int *)&xtime;
169:
170: /*
171: * generate hours:minutes:seconds
172: */
173: *tp++ = hms%60;
174: d1 = hms/60;
175: *tp++ = d1%60;
176: d1 /= 60;
177: *tp++ = d1;
178:
179: /*
180: * day is the day number.
181: * generate day of the week.
182: * The addend is 4 mod 7 (1/1/1970 was Thursday)
183: */
184:
185: xtime.tm_wday = (day+7340036)%7;
186:
187: /*
188: * year number
189: */
190: /* in 400 years there are 97*366+303*365=146097 days (40 bits and up)*/
191: if(day>=0) {
192: for(d1 = 70; day >= 146097; d1 += 400)
193: day -= 146097;
194: for(; day >= dysize(d1); d1++)
195: day -= dysize(d1);
196: }
197: else {
198: for(d1 = 70; day <= -146097; d1 -= 400)
199: day += 146097;
200: for(; day < 0; d1--)
201: day += dysize(d1-1); /* ! */
202: }
203: xtime.tm_year = d1;
204: xtime.tm_yday = d0 = day;
205:
206: /*
207: * generate month
208: */
209:
210: if (dysize(d1)==366)
211: dmsize[1] = 29;
212: for(d1=0; d0 >= dmsize[d1]; d1++)
213: d0 -= dmsize[d1];
214: dmsize[1] = 28;
215: *tp++ = d0+1;
216: *tp++ = d1;
217: xtime.tm_isdst = 0;
218: return(&xtime);
219: }
220:
221: char *
222: asctime(t)
223: struct tm *t;
224: {
225: register char *cp, *ncp;
226: register int *tp;
227:
228: cp = cbuf;
229: for (ncp = "Day Mon 00 00:00:00 1900\n"; *cp++ = *ncp++;);
230: ncp = &"SunMonTueWedThuFriSat"[3*t->tm_wday];
231: cp = cbuf;
232: *cp++ = *ncp++;
233: *cp++ = *ncp++;
234: *cp++ = *ncp++;
235: cp++;
236: tp = &t->tm_mon;
237: ncp = &"JanFebMarAprMayJunJulAugSepOctNovDec"[(*tp)*3];
238: *cp++ = *ncp++;
239: *cp++ = *ncp++;
240: *cp++ = *ncp++;
241: cp = ct_numb(cp, *--tp);
242: cp = ct_numb(cp, *--tp+100);
243: cp = ct_numb(cp, *--tp+100);
244: cp = ct_numb(cp, *--tp+100);
245: if (t->tm_year>=100) {
246: cp[1] = '2';
247: cp[2] = '0';
248: }
249: cp += 2;
250: cp = ct_numb(cp, t->tm_year+100);
251: return(cbuf);
252: }
253:
254: dysize(y)
255: {
256: if((y%4) == 0)
257: return(366);
258: return(365);
259: }
260:
261: static char *
262: ct_numb(cp, n)
263: register char *cp;
264: {
265: cp++;
266: if (n>=10)
267: *cp++ = (n/10)%10 + '0';
268: else
269: *cp++ = ' ';
270: *cp++ = n%10 + '0';
271: return(cp);
272: }
273:
274: #include <ctype.h>
275:
276: /*
277: * read the file of daylight savings time boundaries
278: * it looks like
279: * 1971 1983 32 0 317 1
280: * to mean that for years 1971-1983, dst starts the first sunday after
281: * day 32, and ends the first monday after day 317
282: */
283: #define BUFSZ 1024
284: #define DSTFILE "/lib/dst"
285:
286: static
287: rdaytab()
288: {
289: static int doneit;
290: int fd;
291: char buf[BUFSZ];
292: char *p;
293: register int i;
294: char *rdline();
295:
296: if (doneit++)
297: return;
298: if ((fd = open(DSTFILE, 0)) < 0)
299: return;
300: i = 0;
301: while ((p = rdline(fd, buf)) != 0)
302: if (dtparse(p, &daytab[i]))
303: if (++i >= NDAYTAB)
304: break;
305: ndaytab = i;
306: close(fd);
307: }
308:
309: dtparse(p, dp)
310: register char *p;
311: register struct daytab *dp;
312: {
313: short s;
314: char *gint();
315:
316: if ((p = gint(p, &s)) == 0)
317: return (0);
318: if (s < 1900)
319: dp->ybeg = 0;
320: else if (s > (1900+255))
321: dp->ybeg = 255;
322: else
323: dp->ybeg = s - 1900;
324: if ((p = gint(p, &s)) == 0)
325: return (0);
326: if (s < 1900)
327: dp->yend = 0;
328: else if (s > (1900+255))
329: dp->yend = 255;
330: else
331: dp->yend = s - 1900;
332: if ((p = gint(p, &dp->dbeg)) == 0)
333: return (0);
334: if ((p = gint(p, &s)) == 0)
335: return (0);
336: dp->obeg = s;
337: if ((p = gint(p, &dp->dend)) == 0)
338: return (0);
339: if ((p = gint(p, &s)) == 0)
340: return (0);
341: dp->oend = s;
342: return (1);
343: }
344:
345: static char *
346: gint(p, sp)
347: register char *p;
348: register short *sp;
349: {
350: register int i;
351:
352: while (isspace(*p))
353: p++;
354: if (!isdigit(*p))
355: return (0);
356: i = 0;
357: while (isdigit(*p))
358: i = (i*10) + *p++ - '0';
359: *sp = i;
360: return (p);
361: }
362:
363: static char *
364: rdline(fd, buf)
365: int fd;
366: char *buf;
367: {
368: register char *p, *q;
369: static char *lastp;
370: static char *endp;
371: int n;
372:
373: if (lastp == 0 || lastp >= endp) {
374: if ((n = read(fd, buf, BUFSZ)) <= 0)
375: return (0);
376: lastp = buf;
377: endp = &buf[n];
378: }
379: for (p = lastp; p < endp && *p != '\n'; p++)
380: ;
381: if (p < endp || lastp == buf) {
382: *p++ = 0;
383: q = lastp;
384: lastp = p;
385: return (q);
386: }
387: /*
388: * unfinished line at end of buffer. try again.
389: */
390: q = lastp;
391: p = buf;
392: while (q < endp)
393: *p++ = *q++;
394: if ((n = read(fd, p, BUFSZ - (p-buf))) <= 0)
395: return (0);
396: endp = &p[n];
397: for (; p < endp && *p != '\n'; p++)
398: ;
399: if (p >= endp)
400: --p; /* too bad */
401: *p++ = 0;
402: lastp = p;
403: return (buf);
404: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.