|
|
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: int dysize();
77: static char *gint();
78: static dtparse();
79:
80: char *
81: ctime(t)
82: long *t;
83: {
84: return(asctime(localtime(t)));
85: }
86:
87: struct tm *
88: localtime(tim)
89: long *tim;
90: {
91: register int dayno;
92: register struct tm *ct;
93: register daylbegin, daylend;
94: int boff, eoff;
95: register int i;
96: register int incr;
97: register int tmp;
98: long copyt;
99: struct timeb systime;
100:
101: ftime(&systime);
102: copyt = *tim - (long)systime.timezone*60;
103: ct = gmtime(©t);
104: if (systime.dstflag == 0)
105: return (ct);
106: dayno = ct->tm_yday;
107: daylbegin = 999; /* default: no dst */
108: daylend = 999;
109: incr = 1*60*60;
110: boff = eoff = 0;
111: rdaytab();
112: for (i = 0; i < ndaytab; i++)
113: if (daytab[i].ybeg <= ct->tm_year && ct->tm_year <= daytab[i].yend) {
114: daylbegin = daytab[i].dbeg;
115: daylend = daytab[i].dend;
116: boff = daytab[i].obeg;
117: eoff = daytab[i].oend;
118: break;
119: }
120: if (daylbegin > daylend) {
121: tmp = daylbegin;
122: daylbegin = daylend;
123: daylend = tmp;
124: copyt += incr;
125: incr = -incr;
126: }
127: daylbegin = sunday(ct, daylbegin)+boff;
128: daylend = sunday(ct, daylend)+eoff;
129: if ((dayno>daylbegin || (dayno==daylbegin && ct->tm_hour>=2)) &&
130: (dayno<daylend || (dayno==daylend && ct->tm_hour<1))) {
131: copyt += incr;
132: ct = gmtime(©t);
133: ct->tm_isdst++;
134: }
135: return(ct);
136: }
137:
138: /*
139: * The argument is a 0-origin day number.
140: * The value is the day number of the last
141: * Sunday before or after the day.
142: */
143: static
144: sunday(t, d)
145: register struct tm *t;
146: register int d;
147: {
148: if (d >= 58)
149: d += dysize(t->tm_year) - 365;
150: return(d - (d - t->tm_yday + t->tm_wday + 700) % 7);
151: }
152:
153: struct tm *
154: gmtime(tim)
155: long *tim;
156: {
157: register int d0, d1;
158: long hms, day;
159: register int *tp;
160: static struct tm xtime;
161:
162: /*
163: * break initial number into days
164: */
165: hms = *tim % 86400;
166: day = *tim / 86400;
167: if (hms<0) {
168: hms += 86400;
169: day -= 1;
170: }
171: tp = (int *)&xtime;
172:
173: /*
174: * generate hours:minutes:seconds
175: */
176: *tp++ = hms%60;
177: d1 = hms/60;
178: *tp++ = d1%60;
179: d1 /= 60;
180: *tp++ = d1;
181:
182: /*
183: * day is the day number.
184: * generate day of the week.
185: * The addend is 4 mod 7 (1/1/1970 was Thursday)
186: */
187:
188: xtime.tm_wday = (day+7340036)%7;
189:
190: /*
191: * year number
192: */
193: /* in 400 years there are 97*366+303*365=146097 days (40 bits and up)*/
194: if(day>=0) {
195: for(d1 = 70; day >= 146097; d1 += 400)
196: day -= 146097;
197: for(; day >= dysize(d1); d1++)
198: day -= dysize(d1);
199: }
200: else {
201: for(d1 = 70; day <= -146097; d1 -= 400)
202: day += 146097;
203: for(; day < 0; d1--)
204: day += dysize(d1-1); /* ! */
205: }
206: xtime.tm_year = d1;
207: xtime.tm_yday = d0 = day;
208:
209: /*
210: * generate month
211: */
212:
213: if (dysize(d1)==366)
214: dmsize[1] = 29;
215: for(d1=0; d0 >= dmsize[d1]; d1++)
216: d0 -= dmsize[d1];
217: dmsize[1] = 28;
218: *tp++ = d0+1;
219: *tp++ = d1;
220: xtime.tm_isdst = 0;
221: return(&xtime);
222: }
223:
224: char *
225: asctime(t)
226: struct tm *t;
227: {
228: register char *cp, *ncp;
229: register int *tp;
230:
231: cp = cbuf;
232: for (ncp = "Day Mon 00 00:00:00 1900\n"; *cp++ = *ncp++;);
233: ncp = &"SunMonTueWedThuFriSat"[3*t->tm_wday];
234: cp = cbuf;
235: *cp++ = *ncp++;
236: *cp++ = *ncp++;
237: *cp++ = *ncp++;
238: cp++;
239: tp = &t->tm_mon;
240: ncp = &"JanFebMarAprMayJunJulAugSepOctNovDec"[(*tp)*3];
241: *cp++ = *ncp++;
242: *cp++ = *ncp++;
243: *cp++ = *ncp++;
244: cp = ct_numb(cp, *--tp);
245: cp = ct_numb(cp, *--tp+100);
246: cp = ct_numb(cp, *--tp+100);
247: cp = ct_numb(cp, *--tp+100);
248: if (t->tm_year>=100) {
249: cp[1] = '2';
250: cp[2] = '0';
251: }
252: cp += 2;
253: cp = ct_numb(cp, t->tm_year+100);
254: return(cbuf);
255: }
256:
257: dysize(y)
258: {
259: if((y%4) == 0)
260: return(366);
261: return(365);
262: }
263:
264: static char *
265: ct_numb(cp, n)
266: register char *cp;
267: {
268: cp++;
269: if (n>=10)
270: *cp++ = (n/10)%10 + '0';
271: else
272: *cp++ = ' ';
273: *cp++ = n%10 + '0';
274: return(cp);
275: }
276:
277: #include <ctype.h>
278:
279: /*
280: * read the file of daylight savings time boundaries
281: * it looks like
282: * 1971 1983 32 0 317 1
283: * to mean that for years 1971-1983, dst starts the first sunday after
284: * day 32, and ends the first monday after day 317
285: */
286: #define BUFSZ 1024
287: #define DSTFILE "/lib/dst"
288:
289: static
290: rdaytab()
291: {
292: static int doneit;
293: int fd;
294: char buf[BUFSZ];
295: char *p;
296: register int i;
297: char *rdline();
298:
299: if (doneit++)
300: return;
301: if ((fd = open(DSTFILE, 0)) < 0)
302: return;
303: i = 0;
304: while ((p = rdline(fd, buf)) != 0)
305: if (dtparse(p, &daytab[i]))
306: if (++i >= NDAYTAB)
307: break;
308: ndaytab = i;
309: close(fd);
310: }
311:
312: static
313: dtparse(p, dp)
314: register char *p;
315: register struct daytab *dp;
316: {
317: short s;
318:
319: if ((p = gint(p, &s)) == 0)
320: return (0);
321: if (s < 1900)
322: dp->ybeg = 0;
323: else if (s > (1900+255))
324: dp->ybeg = 255;
325: else
326: dp->ybeg = s - 1900;
327: if ((p = gint(p, &s)) == 0)
328: return (0);
329: if (s < 1900)
330: dp->yend = 0;
331: else if (s > (1900+255))
332: dp->yend = 255;
333: else
334: dp->yend = s - 1900;
335: if ((p = gint(p, &dp->dbeg)) == 0)
336: return (0);
337: if ((p = gint(p, &s)) == 0)
338: return (0);
339: dp->obeg = s;
340: if ((p = gint(p, &dp->dend)) == 0)
341: return (0);
342: if ((p = gint(p, &s)) == 0)
343: return (0);
344: dp->oend = s;
345: return (1);
346: }
347:
348: static char *
349: gint(p, sp)
350: register char *p;
351: register short *sp;
352: {
353: register int i;
354:
355: while (isspace(*p))
356: p++;
357: if (!isdigit(*p))
358: return (0);
359: i = 0;
360: while (isdigit(*p))
361: i = (i*10) + *p++ - '0';
362: *sp = i;
363: return (p);
364: }
365:
366: static char *
367: rdline(fd, buf)
368: int fd;
369: char *buf;
370: {
371: register char *p, *q;
372: static char *lastp;
373: static char *endp;
374: int n;
375:
376: if (lastp == 0 || lastp >= endp) {
377: if ((n = read(fd, buf, BUFSZ)) <= 0)
378: return (0);
379: lastp = buf;
380: endp = &buf[n];
381: }
382: for (p = lastp; p < endp && *p != '\n'; p++)
383: ;
384: if (p < endp || lastp == buf) {
385: *p++ = 0;
386: q = lastp;
387: lastp = p;
388: return (q);
389: }
390: /*
391: * unfinished line at end of buffer. try again.
392: */
393: q = lastp;
394: p = buf;
395: while (q < endp)
396: *p++ = *q++;
397: if ((n = read(fd, p, BUFSZ - (p-buf))) <= 0)
398: return (0);
399: endp = &p[n];
400: for (; p < endp && *p != '\n'; p++)
401: ;
402: if (p >= endp)
403: --p; /* too bad */
404: *p++ = 0;
405: lastp = p;
406: return (buf);
407: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.