xref: /plan9-contrib/sys/src/cmd/disk/kfs/porttime.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
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 void		localtime(long tim, Tm *ct);
7 void		gmtime(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 void
44 localtime(long tim, Tm *ct)
45 {
46 	int daylbegin, daylend, dayno, i;
47 	long copyt;
48 
49 	copyt = tim - timezone.minuteswest*60L;
50 	gmtime(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 		gmtime(copyt, ct);
64 		ct->isdst++;
65 	}
66 }
67 
68 /*
69  * The argument is a 0-origin day number.
70  * The value is the day number of the last
71  * Sunday before or after the day.
72  */
73 static
74 sunday(Tm *t, int d)
75 {
76 	if(d >= 58)
77 		d += dysize(t->year) - 365;
78 	return d - (d - t->yday + t->wday + 700) % 7;
79 }
80 
81 void
82 gmtime(long tim, Tm *ct)
83 {
84 	int d0, d1;
85 	long hms, day;
86 
87 	/*
88 	 * break initial number into days
89 	 */
90 	hms = tim % 86400L;
91 	day = tim / 86400L;
92 	if(hms < 0) {
93 		hms += 86400L;
94 		day -= 1;
95 	}
96 
97 	/*
98 	 * generate hours:minutes:seconds
99 	 */
100 	ct->sec = hms % 60;
101 	d1 = hms / 60;
102 	ct->min = d1 % 60;
103 	d1 /= 60;
104 	ct->hour = d1;
105 
106 	/*
107 	 * day is the day number.
108 	 * generate day of the week.
109 	 * The addend is 4 mod 7 (1/1/1970 was Thursday)
110 	 */
111 
112 	ct->wday = (day + 7340036L) % 7;
113 
114 	/*
115 	 * year number
116 	 */
117 	if(day >= 0)
118 		for(d1 = 70; day >= dysize(d1); d1++)
119 			day -= dysize(d1);
120 	else
121 		for (d1 = 70; day < 0; d1--)
122 			day += dysize(d1-1);
123 	ct->year = d1;
124 	ct->yday = d0 = day;
125 
126 	/*
127 	 * generate month
128 	 */
129 
130 	if(dysize(d1) == 366)
131 		dmsize[1] = 29;
132 	for(d1 = 0; d0 >= dmsize[d1]; d1++)
133 		d0 -= dmsize[d1];
134 	dmsize[1] = 28;
135 	ct->mday = d0 + 1;
136 	ct->mon = d1;
137 	ct->isdst = 0;
138 }
139 
140 void
141 datestr(char *s, long t)
142 {
143 	Tm tm;
144 
145 	localtime(t, &tm);
146 	sprint(s, "%.4d%.2d%.2d", tm.year+1900, tm.mon+1, tm.mday);
147 }
148 
149 int
150 Tconv(Op *o)
151 {
152 	char s[30];
153 	char *cp;
154 	long t;
155 	Tm tm;
156 
157 	t = *(long*)o->argp;
158 	if(t == 0) {
159 		strcpy(s, "The Epoch");
160 		goto out;
161 	}
162 
163 	localtime(t, &tm);
164 	strcpy(s, "Day Mon 00 00:00:00 1900");
165 	cp = &"SunMonTueWedThuFriSat"[tm.wday*3];
166 	s[0] = cp[0];
167 	s[1] = cp[1];
168 	s[2] = cp[2];
169 	cp = &"JanFebMarAprMayJunJulAugSepOctNovDec"[tm.mon*3];
170 	s[4] = cp[0];
171 	s[5] = cp[1];
172 	s[6] = cp[2];
173 	ct_numb(s+8, tm.mday);
174 	ct_numb(s+11, tm.hour+100);
175 	ct_numb(s+14, tm.min+100);
176 	ct_numb(s+17, tm.sec+100);
177 	if(tm.year >= 100) {
178 		s[20] = '2';
179 		s[21] = '0';
180 	}
181 	ct_numb(s+22, tm.year+100);
182 
183 out:
184 	strconv(s, o, o->f1, o->f2);
185 	return sizeof(t);
186 }
187 
188 static
189 dysize(int y)
190 {
191 
192 	if((y%4) == 0)
193 		return 366;
194 	return 365;
195 }
196 
197 static
198 void
199 ct_numb(char *cp, int n)
200 {
201 
202 	if(n >= 10)
203 		cp[0] = (n/10)%10 + '0';
204 	else
205 		cp[0] = ' ';
206 	cp[1] = n%10 + '0';
207 }
208 
209 /*
210  * compute the next time after t
211  * that has hour hr and is not on
212  * day in bitpattern --
213  * for automatic dumps
214  */
215 long
216 nextime(long t, int hr, int day)
217 {
218 	Tm tm;
219 	int nhr;
220 
221 	if(hr < 0 || hr >= 24)
222 		hr = 5;
223 	if((day&0x7f) == 0x7f)
224 		day = 0;
225 
226 loop:
227 	localtime(t, &tm);
228 	t -= tm.sec;
229 	t -= tm.min*60;
230 	nhr = tm.hour;
231 	do {
232 		t += 60*60;
233 		nhr++;
234 	} while(nhr%24 != hr);
235 	localtime(t, &tm);
236 	if(tm.hour != hr) {
237 		t += 60*60;
238 		localtime(t, &tm);
239 		if(tm.hour != hr) {
240 			t -= 60*60;
241 			localtime(t, &tm);
242 		}
243 	}
244 	if(day & (1<<tm.wday)) {
245 		t += 12*60*60;
246 		goto loop;
247 	}
248 	return t;
249 }
250