xref: /plan9/sys/src/cmd/disk/kfs/porttime.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
1 #include	"all.h"
2 
3 static	int	sunday(Tm *t, int d);
4 static	int	dysize(int);
5 static	void	ct_numb(char*, int);
6 static	void	klocaltime(long tim, Tm *ct);
7 static	void	kgmtime(long tim, Tm *ct);
8 
9 static	char	dmsize[12] =
10 {
11 	31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
12 };
13 
14 /*
15  * The following table is used for 1974 and 1975 and
16  * gives the day number of the first day after the Sunday of the
17  * change.
18  */
19 static	struct
20 {
21 	short	yrfrom;
22 	short	yrto;
23 	short	daylb;
24 	short	dayle;
25 } daytab[] =
26 {
27 	87,	999,	97,	303,
28 	76,	86,	119,	303,
29 	75,	75,	58,	303,
30 	74,	74,	5,	333,
31 	0,	73,	119,	303,
32 };
33 
34 static struct
35 {
36 	short	minuteswest;	/* minutes west of Greenwich */
37 	short	dsttime;	/* dst correction */
38 } timezone =
39 {
40 	5*60, 1
41 };
42 
43 static void
klocaltime(long tim,Tm * ct)44 klocaltime(long tim, Tm *ct)
45 {
46 	int daylbegin, daylend, dayno, i;
47 	long copyt;
48 
49 	copyt = tim - timezone.minuteswest*60L;
50 	kgmtime(copyt, ct);
51 	dayno = ct->yday;
52 	for(i=0;; i++)
53 		if(ct->year >= daytab[i].yrfrom &&
54 		   ct->year <= daytab[i].yrto) {
55 			daylbegin = sunday(ct, daytab[i].daylb);
56 			daylend = sunday(ct, daytab[i].dayle);
57 			break;
58 		}
59 	if(timezone.dsttime &&
60 	    (dayno>daylbegin || (dayno==daylbegin && ct->hour>=2)) &&
61 	    (dayno<daylend || (dayno==daylend && ct->hour<1))) {
62 		copyt += 60L*60L;
63 		kgmtime(copyt, ct);
64 	}
65 }
66 
67 /*
68  * The argument is a 0-origin day number.
69  * The value is the day number of the last
70  * Sunday before or after the day.
71  */
72 static
sunday(Tm * t,int d)73 sunday(Tm *t, int d)
74 {
75 	if(d >= 58)
76 		d += dysize(t->year) - 365;
77 	return d - (d - t->yday + t->wday + 700) % 7;
78 }
79 
80 static void
kgmtime(long tim,Tm * ct)81 kgmtime(long tim, Tm *ct)
82 {
83 	int d0, d1;
84 	long hms, day;
85 
86 	/*
87 	 * break initial number into days
88 	 */
89 	hms = tim % 86400L;
90 	day = tim / 86400L;
91 	if(hms < 0) {
92 		hms += 86400L;
93 		day -= 1;
94 	}
95 
96 	/*
97 	 * generate hours:minutes:seconds
98 	 */
99 	ct->sec = hms % 60;
100 	d1 = hms / 60;
101 	ct->min = d1 % 60;
102 	d1 /= 60;
103 	ct->hour = d1;
104 
105 	/*
106 	 * day is the day number.
107 	 * generate day of the week.
108 	 * The addend is 4 mod 7 (1/1/1970 was Thursday)
109 	 */
110 
111 	ct->wday = (day + 7340036L) % 7;
112 
113 	/*
114 	 * year number
115 	 */
116 	if(day >= 0)
117 		for(d1 = 70; day >= dysize(d1); d1++)
118 			day -= dysize(d1);
119 	else
120 		for (d1 = 70; day < 0; d1--)
121 			day += dysize(d1-1);
122 	ct->year = d1;
123 	ct->yday = d0 = day;
124 
125 	/*
126 	 * generate month
127 	 */
128 
129 	if(dysize(d1) == 366)
130 		dmsize[1] = 29;
131 	for(d1 = 0; d0 >= dmsize[d1]; d1++)
132 		d0 -= dmsize[d1];
133 	dmsize[1] = 28;
134 	ct->mday = d0 + 1;
135 	ct->mon = d1;
136 }
137 
138 void
datestr(char * s,long t)139 datestr(char *s, long t)
140 {
141 	Tm tm;
142 
143 	klocaltime(t, &tm);
144 	sprint(s, "%.4d%.2d%.2d", tm.year+1900, tm.mon+1, tm.mday);
145 }
146 
147 int
Tfmt(Fmt * f1)148 Tfmt(Fmt *f1)
149 {
150 	char s[30];
151 	char *cp;
152 	long t;
153 	Tm tm;
154 
155 	t = va_arg(f1->args, long);
156 	if(t == 0)
157 		return fmtstrcpy(f1, "The Epoch");
158 
159 	klocaltime(t, &tm);
160 	strcpy(s, "Day Mon 00 00:00:00 1900");
161 	cp = &"SunMonTueWedThuFriSat"[tm.wday*3];
162 	s[0] = cp[0];
163 	s[1] = cp[1];
164 	s[2] = cp[2];
165 	cp = &"JanFebMarAprMayJunJulAugSepOctNovDec"[tm.mon*3];
166 	s[4] = cp[0];
167 	s[5] = cp[1];
168 	s[6] = cp[2];
169 	ct_numb(s+8, tm.mday);
170 	ct_numb(s+11, tm.hour+100);
171 	ct_numb(s+14, tm.min+100);
172 	ct_numb(s+17, tm.sec+100);
173 	if(tm.year >= 100) {
174 		s[20] = '2';
175 		s[21] = '0';
176 	}
177 	ct_numb(s+22, tm.year+100);
178 
179 	return fmtstrcpy(f1, s);
180 }
181 
182 static
dysize(int y)183 dysize(int y)
184 {
185 
186 	if((y%4) == 0)
187 		return 366;
188 	return 365;
189 }
190 
191 static
192 void
ct_numb(char * cp,int n)193 ct_numb(char *cp, int n)
194 {
195 
196 	if(n >= 10)
197 		cp[0] = (n/10)%10 + '0';
198 	else
199 		cp[0] = ' ';
200 	cp[1] = n%10 + '0';
201 }
202 
203 /*
204  * compute the next time after t
205  * that has hour hr and is not on
206  * day in bitpattern --
207  * for automatic dumps
208  */
209 long
nextime(long t,int hr,int day)210 nextime(long t, int hr, int day)
211 {
212 	Tm tm;
213 	int nhr;
214 
215 	if(hr < 0 || hr >= 24)
216 		hr = 5;
217 	if((day&0x7f) == 0x7f)
218 		day = 0;
219 
220 loop:
221 	klocaltime(t, &tm);
222 	t -= tm.sec;
223 	t -= tm.min*60;
224 	nhr = tm.hour;
225 	do {
226 		t += 60*60;
227 		nhr++;
228 	} while(nhr%24 != hr);
229 	klocaltime(t, &tm);
230 	if(tm.hour != hr) {
231 		t += 60*60;
232 		klocaltime(t, &tm);
233 		if(tm.hour != hr) {
234 			t -= 60*60;
235 			klocaltime(t, &tm);
236 		}
237 	}
238 	if(day & (1<<tm.wday)) {
239 		t += 12*60*60;
240 		goto loop;
241 	}
242 	return t;
243 }
244