1 #include "astro.h"
2
3
4 char* month[] =
5 {
6 "January",
7 "February",
8 "March",
9 "April",
10 "May",
11 "June",
12 "July",
13 "August",
14 "September",
15 "October",
16 "November",
17 "December",
18 };
19
20 double
dsrc(double d,Tim * t,int i)21 dsrc(double d, Tim *t, int i)
22 {
23 double y;
24
25 do {
26 t->ifa[i] += 1.;
27 y = convdate(t);
28 } while(d >= y);
29 do {
30 t->ifa[i] -= 1.;
31 y = convdate(t);
32 } while(d < y);
33 return d - y;
34 }
35
36 void
dtsetup(double d,Tim * t)37 dtsetup(double d, Tim *t)
38 {
39 double v;
40
41 t->ifa[0] = floor(1900 + d/365.24220);
42 t->ifa[1] = 1;
43 t->ifa[2] = 1;
44 t->ifa[3] = 0;
45 t->ifa[4] = 0;
46 t->ifa[1] = floor(1 + dsrc(d, t, 0)/30);
47 t->ifa[2] = floor(1 + dsrc(d, t, 1));
48 dsrc(d, t, 2);
49
50 v = (d - convdate(t)) * 24;
51 t->ifa[3] = floor(v);
52 t->ifa[4] = (v - t->ifa[3]) * 60;
53 convdate(t); /* to set timezone */
54 }
55
56 void
pdate(double d)57 pdate(double d)
58 {
59 int i;
60 Tim t;
61
62 dtsetup(d, &t);
63 if(flags['s']) {
64 i = t.ifa[1];
65 print("%s ", month[i-1]);
66 i = t.ifa[2];
67 numb(i);
68 print("...");
69 return;
70 }
71
72 /* year month day */
73 print("%4d %2d %2d",
74 (int)t.ifa[0],
75 (int)t.ifa[1],
76 (int)t.ifa[2]);
77 }
78
79 void
ptime(double d)80 ptime(double d)
81 {
82 int h, m, s;
83 char *mer;
84 Tim t;
85
86 if(flags['s']) {
87 /* hour minute */
88 dtsetup(d + .5/(24*60), &t);
89 h = t.ifa[3];
90 m = floor(t.ifa[4]);
91
92 mer = "AM";
93 if(h >= 12) {
94 mer = "PM";
95 h -= 12;
96 }
97 if(h == 0)
98 h = 12;
99 numb(h);
100 if(m < 10) {
101 if(m == 0) {
102 print("%s exactly ...", mer);
103 return;
104 }
105 print("O ");
106 }
107 numb(m);
108 print("%s ...", mer);
109 return;
110 }
111 /* hour minute second */
112 dtsetup(d, &t);
113 h = t.ifa[3];
114 m = floor(t.ifa[4]);
115 s = floor((t.ifa[4]-m) * 60);
116 print("%.2d:%.2d:%.2d %.*s", h, m, s, utfnlen(t.tz, 3), t.tz);
117 }
118
119 char* unit[] =
120 {
121 "zero",
122 "one",
123 "two",
124 "three",
125 "four",
126 "five",
127 "six",
128 "seven",
129 "eight",
130 "nine",
131 "ten",
132 "eleven",
133 "twelve",
134 "thirteen",
135 "fourteen",
136 "fifteen",
137 "sixteen",
138 "seventeen",
139 "eighteen",
140 "nineteen"
141 };
142 char* decade[] =
143 {
144 "twenty",
145 "thirty",
146 "forty",
147 "fifty",
148 "sixty",
149 "seventy",
150 "eighty",
151 "ninety"
152 };
153
154 void
pstime(double d)155 pstime(double d)
156 {
157
158 setime(d);
159
160 semi = 0;
161 motion = 0;
162 rad = 1.e9;
163 lambda = 0;
164 beta = 0;
165
166 // uses lambda, beta, rad, motion
167 // sets alpha, delta, rp
168
169 helio();
170
171 // uses alpha, delta, rp
172 // sets ra, decl, lha, decl2, az, el
173
174 geo();
175
176 print(" %R %D %D %4.0f", lha, nlat, awlong, elev/3.28084);
177 }
178
179 void
numb(int n)180 numb(int n)
181 {
182
183 if(n >= 100) {
184 print("%d ", n);
185 return;
186 }
187 if(n >= 20) {
188 print("%s ", decade[n/10 - 2]);
189 n %= 10;
190 if(n == 0)
191 return;
192 }
193 print("%s ", unit[n]);
194 }
195
196 double
tzone(double y,Tim * z)197 tzone(double y, Tim *z)
198 {
199 double t, l1, l2;
200 Tm t1, t2;
201
202 /*
203 * get a rough approximation to unix mean time
204 */
205 t = (y - 25567.5) * 86400;
206
207 /*
208 * if outside unix conversions,
209 * just call it GMT
210 */
211 if(t < 0 || t > 2.1e9)
212 return y;
213
214 /*
215 * convert by both local and gmt
216 */
217 t1 = *localtime((long)t);
218 t2 = *gmtime((long)t);
219
220 /*
221 * pick up year crossings
222 */
223 if(t1.yday == 0 && t2.yday > 1)
224 t1.yday = t2.yday+1;
225 if(t2.yday == 0 && t1.yday > 1)
226 t2.yday = t1.yday+1;
227
228 /*
229 * convert times to days
230 */
231 l1 = t1.yday + t1.hour/24. + t1.min/1440. + t1.sec/86400.;
232 l2 = t2.yday + t2.hour/24. + t2.min/1440. + t2.sec/86400.;
233
234 /*
235 * return difference
236 */
237 strncpy(z->tz, t1.zone, sizeof(z->tz));
238 return y + (l2 - l1);
239 }
240
241 int dmo[12] =
242 {
243 0,
244 31,
245 59,
246 90,
247 120,
248 151,
249 181,
250 212,
251 243,
252 273,
253 304,
254 334
255 };
256
257 /*
258 * input date conversion
259 * output is done by zero crossing
260 * on this input conversion.
261 */
262 double
convdate(Tim * t)263 convdate(Tim *t)
264 {
265 double y, d;
266 int m;
267
268 y = t->ifa[0];
269 m = t->ifa[1];
270 d = t->ifa[2];
271
272 /*
273 * normalize the month
274 */
275 while(m < 1) {
276 m += 12;
277 y -= 1;
278 }
279 while(m > 12) {
280 m -= 12;
281 y += 1;
282 }
283
284 /*
285 * bc correction
286 */
287 if(y < 0)
288 y += 1;
289
290 /*
291 * normal conversion
292 */
293 y += 4712;
294 if(fmod(y, 4) == 0 && m > 2)
295 d += 1;
296 y = y*365 + floor((y+3)/4) + dmo[m-1] + d - 1;
297
298 /*
299 * gregorian change
300 */
301 if(y > 2361232)
302 y -= floor((y-1794167)/36524.220) -
303 floor((y-1721117)/146100);
304 y += t->ifa[3]/24 + t->ifa[4]/1440 - 2415020.5;
305
306 /*
307 * kitchen clock correction
308 */
309 strncpy(t->tz, "GMT", sizeof(t->tz));
310 if(flags['k'])
311 y = tzone(y, t);
312 return y;
313 }
314