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