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 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 37 dtsetup(double d, Tim *t) 38 { 39 double v; 40 41 t->ifa[0] = floor(1900 + d/365.2425); 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 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 /* year month day */ 72 print("%4d %2d %2d", 73 (int)t.ifa[0], 74 (int)t.ifa[1], 75 (int)t.ifa[2]); 76 } 77 78 void 79 ptime(double d) 80 { 81 int h, m, s; 82 char *mer; 83 Tim t; 84 85 if(flags['s']) { 86 /* hour minute */ 87 dtsetup(d + .5/(24*60), &t); 88 h = t.ifa[3]; 89 m = floor(t.ifa[4]); 90 91 mer = "AM"; 92 if(h >= 12) { 93 mer = "PM"; 94 h -= 12; 95 } 96 if(h == 0) 97 h = 12; 98 numb(h); 99 if(m < 10) { 100 if(m == 0) { 101 print("%s exactly ...", mer); 102 return; 103 } 104 print("O "); 105 } 106 numb(m); 107 print("%s ...", mer); 108 return; 109 } 110 /* hour minute second */ 111 dtsetup(d, &t); 112 h = t.ifa[3]; 113 m = floor(t.ifa[4]); 114 s = floor((t.ifa[4]-m) * 60); 115 print("%.2d:%.2d:%.2d %.3s", h, m, s, t.tz); 116 } 117 118 char* unit[] = 119 { 120 "zero", 121 "one", 122 "two", 123 "three", 124 "four", 125 "five", 126 "six", 127 "seven", 128 "eight", 129 "nine", 130 "ten", 131 "eleven", 132 "twelve", 133 "thirteen", 134 "fourteen", 135 "fifteen", 136 "sixteen", 137 "seventeen", 138 "eighteen", 139 "nineteen" 140 }; 141 char* decade[] = 142 { 143 "twenty", 144 "thirty", 145 "forty", 146 "fifty", 147 "sixty", 148 "seventy", 149 "eighty", 150 "ninety" 151 }; 152 153 void 154 numb(int n) 155 { 156 157 if(n >= 100) { 158 print("%l ", n); 159 return; 160 } 161 if(n >= 20) { 162 print("%s ", decade[n/10 - 2]); 163 n %= 10; 164 if(n == 0) 165 return; 166 } 167 print("%s ", unit[n]); 168 } 169 170 double 171 tzone(double y, Tim *z) 172 { 173 double t, l1, l2; 174 Tm t1, t2; 175 176 /* 177 * get a rough approximation to unix mean time 178 */ 179 t = (y - 25567.5) * 86400; 180 181 /* 182 * if outside unix conversions, 183 * just call it GMT 184 */ 185 if(t < 0 || t > 2.1e9) 186 return y; 187 188 /* 189 * convert by both local and gmt 190 */ 191 t1 = *localtime((long)t); 192 t2 = *gmtime((long)t); 193 194 /* 195 * pick up year crossings 196 */ 197 if(t1.yday == 0 && t2.yday > 1) 198 t1.yday = t2.yday+1; 199 if(t2.yday == 0 && t1.yday > 1) 200 t2.yday = t1.yday+1; 201 202 /* 203 * convert times to days 204 */ 205 l1 = t1.yday + t1.hour/24. + t1.min/1440. + t1.sec/86400.; 206 l2 = t2.yday + t2.hour/24. + t2.min/1440. + t2.sec/86400.; 207 208 /* 209 * return difference 210 */ 211 strncpy(z->tz, t1.zone, sizeof(z->tz)); 212 return y + (l2 - l1); 213 } 214 215 int dmo[12] = 216 { 217 0, 218 31, 219 59, 220 90, 221 120, 222 151, 223 181, 224 212, 225 243, 226 273, 227 304, 228 334 229 }; 230 231 /* 232 * input date conversion 233 * output is done by zero crossing 234 * on this input conversion. 235 */ 236 double 237 convdate(Tim *t) 238 { 239 double y, d; 240 int m; 241 242 y = t->ifa[0]; 243 m = t->ifa[1]; 244 d = t->ifa[2]; 245 246 /* 247 * normalize the month 248 */ 249 while(m < 1) { 250 m += 12; 251 y -= 1; 252 } 253 while(m > 12) { 254 m -= 12; 255 y += 1; 256 } 257 258 /* 259 * bc correction 260 */ 261 if(y < 0) 262 y += 1; 263 264 /* 265 * normal conversion 266 */ 267 y += 4712; 268 if(fmod(y, 4) == 0 && m > 2) 269 d += 1; 270 y = y*365 + floor((y+3)/4) + dmo[m-1] + d - 1; 271 272 /* 273 * gregorian change 274 */ 275 if(y > 2361232) 276 y -= floor((y-1794167)/36525) - 277 floor((y-1721117)/146100); 278 y += t->ifa[3]/24 + t->ifa[4]/1440 - 2415020.5; 279 280 /* 281 * kitchen clock correction 282 */ 283 strncpy(t->tz, "GMT", sizeof(t->tz)); 284 if(flags['k']) 285 y = tzone(y, t); 286 return y; 287 } 288