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