xref: /plan9/sys/src/cmd/disk/kfs/porttime.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
13e12c5d1SDavid du Colombier #include	"all.h"
23e12c5d1SDavid du Colombier 
33e12c5d1SDavid du Colombier static	int	sunday(Tm *t, int d);
43e12c5d1SDavid du Colombier static	int	dysize(int);
53e12c5d1SDavid du Colombier static	void	ct_numb(char*, int);
67dd7cddfSDavid du Colombier static	void	klocaltime(long tim, Tm *ct);
77dd7cddfSDavid du Colombier static	void	kgmtime(long tim, Tm *ct);
83e12c5d1SDavid du Colombier 
93e12c5d1SDavid du Colombier static	char	dmsize[12] =
103e12c5d1SDavid du Colombier {
113e12c5d1SDavid du Colombier 	31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
123e12c5d1SDavid du Colombier };
133e12c5d1SDavid du Colombier 
143e12c5d1SDavid du Colombier /*
153e12c5d1SDavid du Colombier  * The following table is used for 1974 and 1975 and
163e12c5d1SDavid du Colombier  * gives the day number of the first day after the Sunday of the
173e12c5d1SDavid du Colombier  * change.
183e12c5d1SDavid du Colombier  */
193e12c5d1SDavid du Colombier static	struct
203e12c5d1SDavid du Colombier {
213e12c5d1SDavid du Colombier 	short	yrfrom;
223e12c5d1SDavid du Colombier 	short	yrto;
233e12c5d1SDavid du Colombier 	short	daylb;
243e12c5d1SDavid du Colombier 	short	dayle;
253e12c5d1SDavid du Colombier } daytab[] =
263e12c5d1SDavid du Colombier {
273e12c5d1SDavid du Colombier 	87,	999,	97,	303,
283e12c5d1SDavid du Colombier 	76,	86,	119,	303,
293e12c5d1SDavid du Colombier 	75,	75,	58,	303,
303e12c5d1SDavid du Colombier 	74,	74,	5,	333,
313e12c5d1SDavid du Colombier 	0,	73,	119,	303,
323e12c5d1SDavid du Colombier };
333e12c5d1SDavid du Colombier 
343e12c5d1SDavid du Colombier static struct
353e12c5d1SDavid du Colombier {
363e12c5d1SDavid du Colombier 	short	minuteswest;	/* minutes west of Greenwich */
373e12c5d1SDavid du Colombier 	short	dsttime;	/* dst correction */
383e12c5d1SDavid du Colombier } timezone =
393e12c5d1SDavid du Colombier {
403e12c5d1SDavid du Colombier 	5*60, 1
413e12c5d1SDavid du Colombier };
423e12c5d1SDavid du Colombier 
437dd7cddfSDavid du Colombier static void
klocaltime(long tim,Tm * ct)447dd7cddfSDavid du Colombier klocaltime(long tim, Tm *ct)
453e12c5d1SDavid du Colombier {
463e12c5d1SDavid du Colombier 	int daylbegin, daylend, dayno, i;
473e12c5d1SDavid du Colombier 	long copyt;
483e12c5d1SDavid du Colombier 
493e12c5d1SDavid du Colombier 	copyt = tim - timezone.minuteswest*60L;
507dd7cddfSDavid du Colombier 	kgmtime(copyt, ct);
513e12c5d1SDavid du Colombier 	dayno = ct->yday;
523e12c5d1SDavid du Colombier 	for(i=0;; i++)
533e12c5d1SDavid du Colombier 		if(ct->year >= daytab[i].yrfrom &&
543e12c5d1SDavid du Colombier 		   ct->year <= daytab[i].yrto) {
553e12c5d1SDavid du Colombier 			daylbegin = sunday(ct, daytab[i].daylb);
563e12c5d1SDavid du Colombier 			daylend = sunday(ct, daytab[i].dayle);
573e12c5d1SDavid du Colombier 			break;
583e12c5d1SDavid du Colombier 		}
593e12c5d1SDavid du Colombier 	if(timezone.dsttime &&
603e12c5d1SDavid du Colombier 	    (dayno>daylbegin || (dayno==daylbegin && ct->hour>=2)) &&
613e12c5d1SDavid du Colombier 	    (dayno<daylend || (dayno==daylend && ct->hour<1))) {
623e12c5d1SDavid du Colombier 		copyt += 60L*60L;
637dd7cddfSDavid du Colombier 		kgmtime(copyt, ct);
643e12c5d1SDavid du Colombier 	}
653e12c5d1SDavid du Colombier }
663e12c5d1SDavid du Colombier 
673e12c5d1SDavid du Colombier /*
683e12c5d1SDavid du Colombier  * The argument is a 0-origin day number.
693e12c5d1SDavid du Colombier  * The value is the day number of the last
703e12c5d1SDavid du Colombier  * Sunday before or after the day.
713e12c5d1SDavid du Colombier  */
723e12c5d1SDavid du Colombier static
sunday(Tm * t,int d)733e12c5d1SDavid du Colombier sunday(Tm *t, int d)
743e12c5d1SDavid du Colombier {
753e12c5d1SDavid du Colombier 	if(d >= 58)
763e12c5d1SDavid du Colombier 		d += dysize(t->year) - 365;
773e12c5d1SDavid du Colombier 	return d - (d - t->yday + t->wday + 700) % 7;
783e12c5d1SDavid du Colombier }
793e12c5d1SDavid du Colombier 
807dd7cddfSDavid du Colombier static void
kgmtime(long tim,Tm * ct)817dd7cddfSDavid du Colombier kgmtime(long tim, Tm *ct)
823e12c5d1SDavid du Colombier {
833e12c5d1SDavid du Colombier 	int d0, d1;
843e12c5d1SDavid du Colombier 	long hms, day;
853e12c5d1SDavid du Colombier 
863e12c5d1SDavid du Colombier 	/*
873e12c5d1SDavid du Colombier 	 * break initial number into days
883e12c5d1SDavid du Colombier 	 */
893e12c5d1SDavid du Colombier 	hms = tim % 86400L;
903e12c5d1SDavid du Colombier 	day = tim / 86400L;
913e12c5d1SDavid du Colombier 	if(hms < 0) {
923e12c5d1SDavid du Colombier 		hms += 86400L;
933e12c5d1SDavid du Colombier 		day -= 1;
943e12c5d1SDavid du Colombier 	}
953e12c5d1SDavid du Colombier 
963e12c5d1SDavid du Colombier 	/*
973e12c5d1SDavid du Colombier 	 * generate hours:minutes:seconds
983e12c5d1SDavid du Colombier 	 */
993e12c5d1SDavid du Colombier 	ct->sec = hms % 60;
1003e12c5d1SDavid du Colombier 	d1 = hms / 60;
1013e12c5d1SDavid du Colombier 	ct->min = d1 % 60;
1023e12c5d1SDavid du Colombier 	d1 /= 60;
1033e12c5d1SDavid du Colombier 	ct->hour = d1;
1043e12c5d1SDavid du Colombier 
1053e12c5d1SDavid du Colombier 	/*
1063e12c5d1SDavid du Colombier 	 * day is the day number.
1073e12c5d1SDavid du Colombier 	 * generate day of the week.
1083e12c5d1SDavid du Colombier 	 * The addend is 4 mod 7 (1/1/1970 was Thursday)
1093e12c5d1SDavid du Colombier 	 */
1103e12c5d1SDavid du Colombier 
1113e12c5d1SDavid du Colombier 	ct->wday = (day + 7340036L) % 7;
1123e12c5d1SDavid du Colombier 
1133e12c5d1SDavid du Colombier 	/*
1143e12c5d1SDavid du Colombier 	 * year number
1153e12c5d1SDavid du Colombier 	 */
1163e12c5d1SDavid du Colombier 	if(day >= 0)
1173e12c5d1SDavid du Colombier 		for(d1 = 70; day >= dysize(d1); d1++)
1183e12c5d1SDavid du Colombier 			day -= dysize(d1);
1193e12c5d1SDavid du Colombier 	else
1203e12c5d1SDavid du Colombier 		for (d1 = 70; day < 0; d1--)
1213e12c5d1SDavid du Colombier 			day += dysize(d1-1);
1223e12c5d1SDavid du Colombier 	ct->year = d1;
1233e12c5d1SDavid du Colombier 	ct->yday = d0 = day;
1243e12c5d1SDavid du Colombier 
1253e12c5d1SDavid du Colombier 	/*
1263e12c5d1SDavid du Colombier 	 * generate month
1273e12c5d1SDavid du Colombier 	 */
1283e12c5d1SDavid du Colombier 
1293e12c5d1SDavid du Colombier 	if(dysize(d1) == 366)
1303e12c5d1SDavid du Colombier 		dmsize[1] = 29;
1313e12c5d1SDavid du Colombier 	for(d1 = 0; d0 >= dmsize[d1]; d1++)
1323e12c5d1SDavid du Colombier 		d0 -= dmsize[d1];
1333e12c5d1SDavid du Colombier 	dmsize[1] = 28;
1343e12c5d1SDavid du Colombier 	ct->mday = d0 + 1;
1353e12c5d1SDavid du Colombier 	ct->mon = d1;
1363e12c5d1SDavid du Colombier }
1373e12c5d1SDavid du Colombier 
1383e12c5d1SDavid du Colombier void
datestr(char * s,long t)1393e12c5d1SDavid du Colombier datestr(char *s, long t)
1403e12c5d1SDavid du Colombier {
1413e12c5d1SDavid du Colombier 	Tm tm;
1423e12c5d1SDavid du Colombier 
1437dd7cddfSDavid du Colombier 	klocaltime(t, &tm);
1443e12c5d1SDavid du Colombier 	sprint(s, "%.4d%.2d%.2d", tm.year+1900, tm.mon+1, tm.mday);
1453e12c5d1SDavid du Colombier }
1463e12c5d1SDavid du Colombier 
1473e12c5d1SDavid du Colombier int
Tfmt(Fmt * f1)148*9a747e4fSDavid du Colombier Tfmt(Fmt *f1)
1493e12c5d1SDavid du Colombier {
1503e12c5d1SDavid du Colombier 	char s[30];
1513e12c5d1SDavid du Colombier 	char *cp;
1523e12c5d1SDavid du Colombier 	long t;
1533e12c5d1SDavid du Colombier 	Tm tm;
1543e12c5d1SDavid du Colombier 
155*9a747e4fSDavid du Colombier 	t = va_arg(f1->args, long);
156*9a747e4fSDavid du Colombier 	if(t == 0)
157*9a747e4fSDavid du Colombier 		return fmtstrcpy(f1, "The Epoch");
1583e12c5d1SDavid du Colombier 
1597dd7cddfSDavid du Colombier 	klocaltime(t, &tm);
1603e12c5d1SDavid du Colombier 	strcpy(s, "Day Mon 00 00:00:00 1900");
1613e12c5d1SDavid du Colombier 	cp = &"SunMonTueWedThuFriSat"[tm.wday*3];
1623e12c5d1SDavid du Colombier 	s[0] = cp[0];
1633e12c5d1SDavid du Colombier 	s[1] = cp[1];
1643e12c5d1SDavid du Colombier 	s[2] = cp[2];
1653e12c5d1SDavid du Colombier 	cp = &"JanFebMarAprMayJunJulAugSepOctNovDec"[tm.mon*3];
1663e12c5d1SDavid du Colombier 	s[4] = cp[0];
1673e12c5d1SDavid du Colombier 	s[5] = cp[1];
1683e12c5d1SDavid du Colombier 	s[6] = cp[2];
1693e12c5d1SDavid du Colombier 	ct_numb(s+8, tm.mday);
1703e12c5d1SDavid du Colombier 	ct_numb(s+11, tm.hour+100);
1713e12c5d1SDavid du Colombier 	ct_numb(s+14, tm.min+100);
1723e12c5d1SDavid du Colombier 	ct_numb(s+17, tm.sec+100);
1733e12c5d1SDavid du Colombier 	if(tm.year >= 100) {
1743e12c5d1SDavid du Colombier 		s[20] = '2';
1753e12c5d1SDavid du Colombier 		s[21] = '0';
1763e12c5d1SDavid du Colombier 	}
1773e12c5d1SDavid du Colombier 	ct_numb(s+22, tm.year+100);
1783e12c5d1SDavid du Colombier 
179*9a747e4fSDavid du Colombier 	return fmtstrcpy(f1, s);
1803e12c5d1SDavid du Colombier }
1813e12c5d1SDavid du Colombier 
1823e12c5d1SDavid du Colombier static
dysize(int y)1833e12c5d1SDavid du Colombier dysize(int y)
1843e12c5d1SDavid du Colombier {
1853e12c5d1SDavid du Colombier 
1863e12c5d1SDavid du Colombier 	if((y%4) == 0)
1873e12c5d1SDavid du Colombier 		return 366;
1883e12c5d1SDavid du Colombier 	return 365;
1893e12c5d1SDavid du Colombier }
1903e12c5d1SDavid du Colombier 
1913e12c5d1SDavid du Colombier static
1923e12c5d1SDavid du Colombier void
ct_numb(char * cp,int n)1933e12c5d1SDavid du Colombier ct_numb(char *cp, int n)
1943e12c5d1SDavid du Colombier {
1953e12c5d1SDavid du Colombier 
1963e12c5d1SDavid du Colombier 	if(n >= 10)
1973e12c5d1SDavid du Colombier 		cp[0] = (n/10)%10 + '0';
1983e12c5d1SDavid du Colombier 	else
1993e12c5d1SDavid du Colombier 		cp[0] = ' ';
2003e12c5d1SDavid du Colombier 	cp[1] = n%10 + '0';
2013e12c5d1SDavid du Colombier }
2023e12c5d1SDavid du Colombier 
2033e12c5d1SDavid du Colombier /*
2043e12c5d1SDavid du Colombier  * compute the next time after t
2053e12c5d1SDavid du Colombier  * that has hour hr and is not on
2063e12c5d1SDavid du Colombier  * day in bitpattern --
2073e12c5d1SDavid du Colombier  * for automatic dumps
2083e12c5d1SDavid du Colombier  */
2093e12c5d1SDavid du Colombier long
nextime(long t,int hr,int day)2103e12c5d1SDavid du Colombier nextime(long t, int hr, int day)
2113e12c5d1SDavid du Colombier {
2123e12c5d1SDavid du Colombier 	Tm tm;
2133e12c5d1SDavid du Colombier 	int nhr;
2143e12c5d1SDavid du Colombier 
2153e12c5d1SDavid du Colombier 	if(hr < 0 || hr >= 24)
2163e12c5d1SDavid du Colombier 		hr = 5;
2173e12c5d1SDavid du Colombier 	if((day&0x7f) == 0x7f)
2183e12c5d1SDavid du Colombier 		day = 0;
2193e12c5d1SDavid du Colombier 
2203e12c5d1SDavid du Colombier loop:
2217dd7cddfSDavid du Colombier 	klocaltime(t, &tm);
2223e12c5d1SDavid du Colombier 	t -= tm.sec;
2233e12c5d1SDavid du Colombier 	t -= tm.min*60;
2243e12c5d1SDavid du Colombier 	nhr = tm.hour;
2253e12c5d1SDavid du Colombier 	do {
2263e12c5d1SDavid du Colombier 		t += 60*60;
2273e12c5d1SDavid du Colombier 		nhr++;
2283e12c5d1SDavid du Colombier 	} while(nhr%24 != hr);
2297dd7cddfSDavid du Colombier 	klocaltime(t, &tm);
2303e12c5d1SDavid du Colombier 	if(tm.hour != hr) {
2313e12c5d1SDavid du Colombier 		t += 60*60;
2327dd7cddfSDavid du Colombier 		klocaltime(t, &tm);
2333e12c5d1SDavid du Colombier 		if(tm.hour != hr) {
2343e12c5d1SDavid du Colombier 			t -= 60*60;
2357dd7cddfSDavid du Colombier 			klocaltime(t, &tm);
2363e12c5d1SDavid du Colombier 		}
2373e12c5d1SDavid du Colombier 	}
2383e12c5d1SDavid du Colombier 	if(day & (1<<tm.wday)) {
2393e12c5d1SDavid du Colombier 		t += 12*60*60;
2403e12c5d1SDavid du Colombier 		goto loop;
2413e12c5d1SDavid du Colombier 	}
2423e12c5d1SDavid du Colombier 	return t;
2433e12c5d1SDavid du Colombier }
244