|
|
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.