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