1*13743Ssam #include "../hdr/macros.h"
22158Seric 
3*13743Ssam SCCSID(@(#)ctime.c	4.2);
42158Seric 
52158Seric /*
62158Seric  * This routine converts time as follows.
72158Seric  * The epoch is 0000 Jan 1 1970 GMT.
82158Seric  * The argument time is in seconds since then.
92158Seric  * The localtime(t) entry returns a pointer to an array
102158Seric  * containing
112158Seric  *  seconds (0-59)
122158Seric  *  minutes (0-59)
132158Seric  *  hours (0-23)
142158Seric  *  day of month (1-31)
152158Seric  *  month (0-11)
162158Seric  *  year-1970
172158Seric  *  weekday (0-6, Sun is 0)
182158Seric  *  day of the year
192158Seric  *  daylight savings flag
202158Seric  *
212158Seric  * The routine calls the system to determine the local
222158Seric  * timezone and whether Daylight Saving Time is permitted locally.
232158Seric  * (DST is then determined by the current US standard rules)
242158Seric  * There is a table that accounts for the peculiarities
252158Seric  * undergone by daylight time in 1974-1975.
262158Seric  *
272158Seric  * The routine does not work
282158Seric  * in Saudi Arabia which runs on Solar time.
292158Seric  *
302158Seric  * asctime(tvec))
312158Seric  * where tvec is produced by localtime
322158Seric  * returns a ptr to a character string
332158Seric  * that has the ascii time in the form
342158Seric  *	Thu Jan 01 00:00:00 1970n0\\
352158Seric  *	01234567890123456789012345
362158Seric  *	0	  1	    2
372158Seric  *
382158Seric  * ctime(t) just calls localtime, then asctime.
392158Seric  */
402158Seric 
41*13743Ssam #include <sys/time.h>
422158Seric #include <sys/types.h>
432158Seric #include <sys/timeb.h>
442158Seric 
452158Seric static	char	cbuf[26];
462158Seric int	dmsize[12] =
472158Seric {
482158Seric 	31,
492158Seric 	28,
502158Seric 	31,
512158Seric 	30,
522158Seric 	31,
532158Seric 	30,
542158Seric 	31,
552158Seric 	31,
562158Seric 	30,
572158Seric 	31,
582158Seric 	30,
592158Seric 	31
602158Seric };
612158Seric 
622158Seric /*
632158Seric  * The following table is used for 1974 and 1975 and
642158Seric  * gives the day number of the first day after the Sunday of the
652158Seric  * change.
662158Seric  */
672158Seric static struct {
682158Seric 	int	daylb;
692158Seric 	int	dayle;
702158Seric } daytab[] = {
712158Seric 	5,	333,	/* 1974: Jan 6 - last Sun. in Nov */
722158Seric 	58,	303,	/* 1975: Last Sun. in Feb - last Sun in Oct */
732158Seric };
742158Seric 
752158Seric struct tm	*gmtime();
762158Seric char		*ct_numb();
772158Seric struct tm	*localtime();
782158Seric char	*ctime();
792158Seric char	*ct_num();
802158Seric char	*asctime();
812158Seric 
822158Seric char *
832158Seric ctime(t)
842158Seric long *t;
852158Seric {
862158Seric 	return(asctime(localtime(t)));
872158Seric }
882158Seric 
892158Seric struct tm *
902158Seric localtime(tim)
912158Seric long *tim;
922158Seric {
932158Seric 	register int dayno;
942158Seric 	register struct tm *ct;
952158Seric 	register daylbegin, daylend;
962158Seric 	long copyt;
972158Seric 	struct timeb systime;
982158Seric 
992158Seric 	ftime(&systime);
1002158Seric 	copyt = *tim - (long)systime.timezone*60;
1012158Seric 	ct = gmtime(&copyt);
1022158Seric 	dayno = ct->tm_yday;
1032158Seric 	daylbegin = 119;	/* last Sun in Apr */
1042158Seric 	daylend = 303;		/* Last Sun in Oct */
1052158Seric 	if (ct->tm_year==74 || ct->tm_year==75) {
1062158Seric 		daylbegin = daytab[ct->tm_year-74].daylb;
1072158Seric 		daylend = daytab[ct->tm_year-74].dayle;
1082158Seric 	}
1092158Seric 	daylbegin = sunday(ct, daylbegin);
1102158Seric 	daylend = sunday(ct, daylend);
1112158Seric 	if (systime.dstflag &&
1122158Seric 	    (dayno>daylbegin || (dayno==daylbegin && ct->tm_hour>=2)) &&
1132158Seric 	    (dayno<daylend || (dayno==daylend && ct->tm_hour<1))) {
1142158Seric 		copyt += 1*60*60;
1152158Seric 		ct = gmtime(&copyt);
1162158Seric 		ct->tm_isdst++;
1172158Seric 	}
1182158Seric 	return(ct);
1192158Seric }
1202158Seric 
1212158Seric /*
1222158Seric  * The argument is a 0-origin day number.
1232158Seric  * The value is the day number of the first
1242158Seric  * Sunday on or after the day.
1252158Seric  */
1262158Seric static
1272158Seric sunday(t, d)
1282158Seric register struct tm *t;
1292158Seric register int d;
1302158Seric {
1312158Seric 	if (d >= 58)
1322158Seric 		d += dysize(t->tm_year) - 365;
1332158Seric 	return(d - (d - t->tm_yday + t->tm_wday + 700) % 7);
1342158Seric }
1352158Seric 
1362158Seric struct tm *
1372158Seric gmtime(tim)
1382158Seric long *tim;
1392158Seric {
1402158Seric 	register int d0, d1;
1412158Seric 	long hms, day;
1422158Seric 	register int *tp;
1432158Seric 	static struct tm xtime;
1442158Seric 
1452158Seric 	/*
1462158Seric 	 * break initial number into days
1472158Seric 	 */
1482158Seric 	hms = *tim % 86400;
1492158Seric 	day = *tim / 86400;
1502158Seric 	if (hms<0) {
1512158Seric 		hms += 86400;
1522158Seric 		day -= 1;
1532158Seric 	}
1542158Seric 	tp = (int *)&xtime;
1552158Seric 
1562158Seric 	/*
1572158Seric 	 * generate hours:minutes:seconds
1582158Seric 	 */
1592158Seric 	*tp++ = hms%60;
1602158Seric 	d1 = hms/60;
1612158Seric 	*tp++ = d1%60;
1622158Seric 	d1 /= 60;
1632158Seric 	*tp++ = d1;
1642158Seric 
1652158Seric 	/*
1662158Seric 	 * day is the day number.
1672158Seric 	 * generate day of the week.
1682158Seric 	 * The addend is 4 mod 7 (1/1/1970 was Thursday)
1692158Seric 	 */
1702158Seric 
1712158Seric 	xtime.tm_wday = (day+7340036)%7;
1722158Seric 
1732158Seric 	/*
1742158Seric 	 * year number
1752158Seric 	 */
1762158Seric 	if (day>=0) for(d1=70; day >= dysize(d1); d1++)
1772158Seric 		day -= dysize(d1);
1782158Seric 	else for (d1=70; day<0; d1--)
1792158Seric 		day += dysize(d1-1);
1802158Seric 	xtime.tm_year = d1;
1812158Seric 	xtime.tm_yday = d0 = day;
1822158Seric 
1832158Seric 	/*
1842158Seric 	 * generate month
1852158Seric 	 */
1862158Seric 
1872158Seric 	if (dysize(d1)==366)
1882158Seric 		dmsize[1] = 29;
1892158Seric 	for(d1=0; d0 >= dmsize[d1]; d1++)
1902158Seric 		d0 -= dmsize[d1];
1912158Seric 	dmsize[1] = 28;
1922158Seric 	*tp++ = d0+1;
1932158Seric 	*tp++ = d1;
1942158Seric 	xtime.tm_isdst = 0;
1952158Seric 	return(&xtime);
1962158Seric }
1972158Seric 
1982158Seric char *
1992158Seric asctime(t)
2002158Seric struct tm *t;
2012158Seric {
2022158Seric 	register char *cp, *ncp;
2032158Seric 	register int *tp;
2042158Seric 
2052158Seric 	cp = cbuf;
2062158Seric 	for (ncp = "Day Mon 00 00:00:00 1900\n"; *cp++ = *ncp++;);
2072158Seric 	ncp = &"SunMonTueWedThuFriSat"[3*t->tm_wday];
2082158Seric 	cp = cbuf;
2092158Seric 	*cp++ = *ncp++;
2102158Seric 	*cp++ = *ncp++;
2112158Seric 	*cp++ = *ncp++;
2122158Seric 	cp++;
2132158Seric 	tp = &t->tm_mon;
2142158Seric 	ncp = &"JanFebMarAprMayJunJulAugSepOctNovDec"[(*tp)*3];
2152158Seric 	*cp++ = *ncp++;
2162158Seric 	*cp++ = *ncp++;
2172158Seric 	*cp++ = *ncp++;
2182158Seric 	cp = ct_numb(cp, *--tp);
2192158Seric 	cp = ct_numb(cp, *--tp+100);
2202158Seric 	cp = ct_numb(cp, *--tp+100);
2212158Seric 	cp = ct_numb(cp, *--tp+100);
2222158Seric 	if (t->tm_year>=100) {
2232158Seric 		cp[1] = '2';
2242158Seric 		cp[2] = '0';
2252158Seric 	}
2262158Seric 	cp += 2;
2272158Seric 	cp = ct_numb(cp, t->tm_year+100);
2282158Seric 	return(cbuf);
2292158Seric }
2302158Seric 
2312158Seric dysize(y)
2322158Seric {
2332158Seric 	if((y%4) == 0)
2342158Seric 		return(366);
2352158Seric 	return(365);
2362158Seric }
2372158Seric 
2382158Seric static char *
2392158Seric ct_numb(cp, n)
2402158Seric register char *cp;
2412158Seric {
2422158Seric 	cp++;
2432158Seric 	if (n>=10)
2442158Seric 		*cp++ = (n/10)%10 + '0';
2452158Seric 	else
2462158Seric 		*cp++ = ' ';
2472158Seric 	*cp++ = n%10 + '0';
2482158Seric 	return(cp);
2492158Seric }
250