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