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