1c7b0ef0aSsam #include "../hdr/macros.h"
2ebdd0f25Seric 
3*7ff2b169Ssam SCCSID(@(#)ctime.c	4.3);
4ebdd0f25Seric 
5ebdd0f25Seric /*
6ebdd0f25Seric  * This routine converts time as follows.
7ebdd0f25Seric  * The epoch is 0000 Jan 1 1970 GMT.
8ebdd0f25Seric  * The argument time is in seconds since then.
9ebdd0f25Seric  * The localtime(t) entry returns a pointer to an array
10ebdd0f25Seric  * containing
11ebdd0f25Seric  *  seconds (0-59)
12ebdd0f25Seric  *  minutes (0-59)
13ebdd0f25Seric  *  hours (0-23)
14ebdd0f25Seric  *  day of month (1-31)
15ebdd0f25Seric  *  month (0-11)
16ebdd0f25Seric  *  year-1970
17ebdd0f25Seric  *  weekday (0-6, Sun is 0)
18ebdd0f25Seric  *  day of the year
19ebdd0f25Seric  *  daylight savings flag
20ebdd0f25Seric  *
21ebdd0f25Seric  * The routine calls the system to determine the local
22ebdd0f25Seric  * timezone and whether Daylight Saving Time is permitted locally.
23ebdd0f25Seric  * (DST is then determined by the current US standard rules)
24ebdd0f25Seric  * There is a table that accounts for the peculiarities
25ebdd0f25Seric  * undergone by daylight time in 1974-1975.
26ebdd0f25Seric  *
27ebdd0f25Seric  * The routine does not work
28ebdd0f25Seric  * in Saudi Arabia which runs on Solar time.
29ebdd0f25Seric  *
30ebdd0f25Seric  * asctime(tvec))
31ebdd0f25Seric  * where tvec is produced by localtime
32ebdd0f25Seric  * returns a ptr to a character string
33ebdd0f25Seric  * that has the ascii time in the form
34ebdd0f25Seric  *	Thu Jan 01 00:00:00 1970n0\\
35ebdd0f25Seric  *	01234567890123456789012345
36ebdd0f25Seric  *	0	  1	    2
37ebdd0f25Seric  *
38ebdd0f25Seric  * ctime(t) just calls localtime, then asctime.
39ebdd0f25Seric  */
40ebdd0f25Seric 
41*7ff2b169Ssam #ifdef notdef
42*7ff2b169Ssam #include <sys/types.h>			/* included by macros.h above */
43*7ff2b169Ssam #endif
44c7b0ef0aSsam #include <sys/time.h>
45ebdd0f25Seric #include <sys/timeb.h>
46ebdd0f25Seric 
47ebdd0f25Seric static	char	cbuf[26];
48ebdd0f25Seric int	dmsize[12] =
49ebdd0f25Seric {
50ebdd0f25Seric 	31,
51ebdd0f25Seric 	28,
52ebdd0f25Seric 	31,
53ebdd0f25Seric 	30,
54ebdd0f25Seric 	31,
55ebdd0f25Seric 	30,
56ebdd0f25Seric 	31,
57ebdd0f25Seric 	31,
58ebdd0f25Seric 	30,
59ebdd0f25Seric 	31,
60ebdd0f25Seric 	30,
61ebdd0f25Seric 	31
62ebdd0f25Seric };
63ebdd0f25Seric 
64ebdd0f25Seric /*
65ebdd0f25Seric  * The following table is used for 1974 and 1975 and
66ebdd0f25Seric  * gives the day number of the first day after the Sunday of the
67ebdd0f25Seric  * change.
68ebdd0f25Seric  */
69ebdd0f25Seric static struct {
70ebdd0f25Seric 	int	daylb;
71ebdd0f25Seric 	int	dayle;
72ebdd0f25Seric } daytab[] = {
73ebdd0f25Seric 	5,	333,	/* 1974: Jan 6 - last Sun. in Nov */
74ebdd0f25Seric 	58,	303,	/* 1975: Last Sun. in Feb - last Sun in Oct */
75ebdd0f25Seric };
76ebdd0f25Seric 
77ebdd0f25Seric struct tm	*gmtime();
78ebdd0f25Seric char		*ct_numb();
79ebdd0f25Seric struct tm	*localtime();
80ebdd0f25Seric char	*ctime();
81ebdd0f25Seric char	*ct_num();
82ebdd0f25Seric char	*asctime();
83ebdd0f25Seric 
84ebdd0f25Seric char *
ctime(t)85ebdd0f25Seric ctime(t)
86ebdd0f25Seric long *t;
87ebdd0f25Seric {
88ebdd0f25Seric 	return(asctime(localtime(t)));
89ebdd0f25Seric }
90ebdd0f25Seric 
91ebdd0f25Seric struct tm *
localtime(tim)92ebdd0f25Seric localtime(tim)
93ebdd0f25Seric long *tim;
94ebdd0f25Seric {
95ebdd0f25Seric 	register int dayno;
96ebdd0f25Seric 	register struct tm *ct;
97ebdd0f25Seric 	register daylbegin, daylend;
98ebdd0f25Seric 	long copyt;
99ebdd0f25Seric 	struct timeb systime;
100ebdd0f25Seric 
101ebdd0f25Seric 	ftime(&systime);
102ebdd0f25Seric 	copyt = *tim - (long)systime.timezone*60;
103ebdd0f25Seric 	ct = gmtime(&copyt);
104ebdd0f25Seric 	dayno = ct->tm_yday;
105ebdd0f25Seric 	daylbegin = 119;	/* last Sun in Apr */
106ebdd0f25Seric 	daylend = 303;		/* Last Sun in Oct */
107ebdd0f25Seric 	if (ct->tm_year==74 || ct->tm_year==75) {
108ebdd0f25Seric 		daylbegin = daytab[ct->tm_year-74].daylb;
109ebdd0f25Seric 		daylend = daytab[ct->tm_year-74].dayle;
110ebdd0f25Seric 	}
111ebdd0f25Seric 	daylbegin = sunday(ct, daylbegin);
112ebdd0f25Seric 	daylend = sunday(ct, daylend);
113ebdd0f25Seric 	if (systime.dstflag &&
114ebdd0f25Seric 	    (dayno>daylbegin || (dayno==daylbegin && ct->tm_hour>=2)) &&
115ebdd0f25Seric 	    (dayno<daylend || (dayno==daylend && ct->tm_hour<1))) {
116ebdd0f25Seric 		copyt += 1*60*60;
117ebdd0f25Seric 		ct = gmtime(&copyt);
118ebdd0f25Seric 		ct->tm_isdst++;
119ebdd0f25Seric 	}
120ebdd0f25Seric 	return(ct);
121ebdd0f25Seric }
122ebdd0f25Seric 
123ebdd0f25Seric /*
124ebdd0f25Seric  * The argument is a 0-origin day number.
125ebdd0f25Seric  * The value is the day number of the first
126ebdd0f25Seric  * Sunday on or after the day.
127ebdd0f25Seric  */
128ebdd0f25Seric static
sunday(t,d)129ebdd0f25Seric sunday(t, d)
130ebdd0f25Seric register struct tm *t;
131ebdd0f25Seric register int d;
132ebdd0f25Seric {
133ebdd0f25Seric 	if (d >= 58)
134ebdd0f25Seric 		d += dysize(t->tm_year) - 365;
135ebdd0f25Seric 	return(d - (d - t->tm_yday + t->tm_wday + 700) % 7);
136ebdd0f25Seric }
137ebdd0f25Seric 
138ebdd0f25Seric struct tm *
gmtime(tim)139ebdd0f25Seric gmtime(tim)
140ebdd0f25Seric long *tim;
141ebdd0f25Seric {
142ebdd0f25Seric 	register int d0, d1;
143ebdd0f25Seric 	long hms, day;
144ebdd0f25Seric 	register int *tp;
145ebdd0f25Seric 	static struct tm xtime;
146ebdd0f25Seric 
147ebdd0f25Seric 	/*
148ebdd0f25Seric 	 * break initial number into days
149ebdd0f25Seric 	 */
150ebdd0f25Seric 	hms = *tim % 86400;
151ebdd0f25Seric 	day = *tim / 86400;
152ebdd0f25Seric 	if (hms<0) {
153ebdd0f25Seric 		hms += 86400;
154ebdd0f25Seric 		day -= 1;
155ebdd0f25Seric 	}
156ebdd0f25Seric 	tp = (int *)&xtime;
157ebdd0f25Seric 
158ebdd0f25Seric 	/*
159ebdd0f25Seric 	 * generate hours:minutes:seconds
160ebdd0f25Seric 	 */
161ebdd0f25Seric 	*tp++ = hms%60;
162ebdd0f25Seric 	d1 = hms/60;
163ebdd0f25Seric 	*tp++ = d1%60;
164ebdd0f25Seric 	d1 /= 60;
165ebdd0f25Seric 	*tp++ = d1;
166ebdd0f25Seric 
167ebdd0f25Seric 	/*
168ebdd0f25Seric 	 * day is the day number.
169ebdd0f25Seric 	 * generate day of the week.
170ebdd0f25Seric 	 * The addend is 4 mod 7 (1/1/1970 was Thursday)
171ebdd0f25Seric 	 */
172ebdd0f25Seric 
173ebdd0f25Seric 	xtime.tm_wday = (day+7340036)%7;
174ebdd0f25Seric 
175ebdd0f25Seric 	/*
176ebdd0f25Seric 	 * year number
177ebdd0f25Seric 	 */
178ebdd0f25Seric 	if (day>=0) for(d1=70; day >= dysize(d1); d1++)
179ebdd0f25Seric 		day -= dysize(d1);
180ebdd0f25Seric 	else for (d1=70; day<0; d1--)
181ebdd0f25Seric 		day += dysize(d1-1);
182ebdd0f25Seric 	xtime.tm_year = d1;
183ebdd0f25Seric 	xtime.tm_yday = d0 = day;
184ebdd0f25Seric 
185ebdd0f25Seric 	/*
186ebdd0f25Seric 	 * generate month
187ebdd0f25Seric 	 */
188ebdd0f25Seric 
189ebdd0f25Seric 	if (dysize(d1)==366)
190ebdd0f25Seric 		dmsize[1] = 29;
191ebdd0f25Seric 	for(d1=0; d0 >= dmsize[d1]; d1++)
192ebdd0f25Seric 		d0 -= dmsize[d1];
193ebdd0f25Seric 	dmsize[1] = 28;
194ebdd0f25Seric 	*tp++ = d0+1;
195ebdd0f25Seric 	*tp++ = d1;
196ebdd0f25Seric 	xtime.tm_isdst = 0;
197ebdd0f25Seric 	return(&xtime);
198ebdd0f25Seric }
199ebdd0f25Seric 
200ebdd0f25Seric char *
asctime(t)201ebdd0f25Seric asctime(t)
202ebdd0f25Seric struct tm *t;
203ebdd0f25Seric {
204ebdd0f25Seric 	register char *cp, *ncp;
205ebdd0f25Seric 	register int *tp;
206ebdd0f25Seric 
207ebdd0f25Seric 	cp = cbuf;
208ebdd0f25Seric 	for (ncp = "Day Mon 00 00:00:00 1900\n"; *cp++ = *ncp++;);
209ebdd0f25Seric 	ncp = &"SunMonTueWedThuFriSat"[3*t->tm_wday];
210ebdd0f25Seric 	cp = cbuf;
211ebdd0f25Seric 	*cp++ = *ncp++;
212ebdd0f25Seric 	*cp++ = *ncp++;
213ebdd0f25Seric 	*cp++ = *ncp++;
214ebdd0f25Seric 	cp++;
215ebdd0f25Seric 	tp = &t->tm_mon;
216ebdd0f25Seric 	ncp = &"JanFebMarAprMayJunJulAugSepOctNovDec"[(*tp)*3];
217ebdd0f25Seric 	*cp++ = *ncp++;
218ebdd0f25Seric 	*cp++ = *ncp++;
219ebdd0f25Seric 	*cp++ = *ncp++;
220ebdd0f25Seric 	cp = ct_numb(cp, *--tp);
221ebdd0f25Seric 	cp = ct_numb(cp, *--tp+100);
222ebdd0f25Seric 	cp = ct_numb(cp, *--tp+100);
223ebdd0f25Seric 	cp = ct_numb(cp, *--tp+100);
224ebdd0f25Seric 	if (t->tm_year>=100) {
225ebdd0f25Seric 		cp[1] = '2';
226ebdd0f25Seric 		cp[2] = '0';
227ebdd0f25Seric 	}
228ebdd0f25Seric 	cp += 2;
229ebdd0f25Seric 	cp = ct_numb(cp, t->tm_year+100);
230ebdd0f25Seric 	return(cbuf);
231ebdd0f25Seric }
232ebdd0f25Seric 
dysize(y)233ebdd0f25Seric dysize(y)
234ebdd0f25Seric {
235ebdd0f25Seric 	if((y%4) == 0)
236ebdd0f25Seric 		return(366);
237ebdd0f25Seric 	return(365);
238ebdd0f25Seric }
239ebdd0f25Seric 
240ebdd0f25Seric static char *
ct_numb(cp,n)241ebdd0f25Seric ct_numb(cp, n)
242ebdd0f25Seric register char *cp;
243ebdd0f25Seric {
244ebdd0f25Seric 	cp++;
245ebdd0f25Seric 	if (n>=10)
246ebdd0f25Seric 		*cp++ = (n/10)%10 + '0';
247ebdd0f25Seric 	else
248ebdd0f25Seric 		*cp++ = ' ';
249ebdd0f25Seric 	*cp++ = n%10 + '0';
250ebdd0f25Seric 	return(cp);
251ebdd0f25Seric }
252