1 #ifndef lint 2 static char sccsid[] = "@(#)ctime.c 4.3 (Berkeley) 07/01/83"; 3 #endif 4 /* 5 * This routine converts time as follows. 6 * The epoch is 0000 Jan 1 1970 GMT. 7 * The argument time is in seconds since then. 8 * The localtime(t) entry returns a pointer to an array 9 * containing 10 * seconds (0-59) 11 * minutes (0-59) 12 * hours (0-23) 13 * day of month (1-31) 14 * month (0-11) 15 * year-1970 16 * weekday (0-6, Sun is 0) 17 * day of the year 18 * daylight savings flag 19 * 20 * The routine calls the system to determine the local 21 * timezone and whether Daylight Saving Time is permitted locally. 22 * (DST is then determined by the current US standard rules) 23 * There is a table that accounts for the peculiarities 24 * undergone by daylight time in 1974-1975. 25 * 26 * The routine does not work 27 * in Saudi Arabia which runs on Solar time. 28 * 29 * asctime(tvec)) 30 * where tvec is produced by localtime 31 * returns a ptr to a character string 32 * that has the ascii time in the form 33 * Thu Jan 01 00:00:00 1970n0\\ 34 * 01234567890123456789012345 35 * 0 1 2 36 * 37 * ctime(t) just calls localtime, then asctime. 38 */ 39 40 #include <sys/time.h> 41 #include <sys/types.h> 42 #include <sys/timeb.h> 43 44 static char cbuf[26]; 45 static int dmsize[12] = 46 { 47 31, 48 28, 49 31, 50 30, 51 31, 52 30, 53 31, 54 31, 55 30, 56 31, 57 30, 58 31 59 }; 60 61 /* 62 * The following table is used for 1974 and 1975 and 63 * gives the day number of the first day after the Sunday of the 64 * change. 65 */ 66 struct dstab { 67 int dayyr; 68 int daylb; 69 int dayle; 70 }; 71 72 static struct dstab usdaytab[] = { 73 1974, 5, 333, /* 1974: Jan 6 - last Sun. in Nov */ 74 1975, 58, 303, /* 1975: Last Sun. in Feb - last Sun in Oct */ 75 0, 119, 303, /* all other years: end Apr - end Oct */ 76 }; 77 static struct dstab ausdaytab[] = { 78 1970, 400, 0, /* 1970: no daylight saving at all */ 79 1971, 303, 0, /* 1971: daylight saving from Oct 31 */ 80 1972, 303, 58, /* 1972: Jan 1 -> Feb 27 & Oct 31 -> dec 31 */ 81 0, 303, 65, /* others: -> Mar 7, Oct 31 -> */ 82 }; 83 84 static struct dayrules { 85 int dst_type; /* number obtained from system */ 86 int dst_hrs; /* hours to add when dst on */ 87 struct dstab * dst_rules; /* one of the above */ 88 enum {STH,NTH} dst_hemi; /* southern, northern hemisphere */ 89 } dayrules [] = { 90 DST_USA, 1, usdaytab, NTH, 91 DST_AUST, 1, ausdaytab, STH, 92 -1, 93 }; 94 95 struct tm *gmtime(); 96 char *ct_numb(); 97 struct tm *localtime(); 98 char *ctime(); 99 char *ct_num(); 100 char *asctime(); 101 102 char * 103 ctime(t) 104 unsigned long *t; 105 { 106 return(asctime(localtime(t))); 107 } 108 109 struct tm * 110 localtime(tim) 111 unsigned long *tim; 112 { 113 register int dayno; 114 register struct tm *ct; 115 register dalybeg, daylend; 116 register struct dayrules *dr; 117 register struct dstab *ds; 118 int year; 119 unsigned long copyt; 120 struct timeval curtime; 121 struct timezone zone; 122 123 gettimeofday(&curtime, &zone); 124 copyt = *tim - (unsigned long)zone.tz_minuteswest*60; 125 ct = gmtime(©t); 126 dayno = ct->tm_yday; 127 for (dr = dayrules; dr->dst_type >= 0; dr++) 128 if (dr->dst_type == zone.tz_dsttime) 129 break; 130 if (dr->dst_type >= 0) { 131 year = ct->tm_year + 1900; 132 for (ds = dr->dst_rules; ds->dayyr; ds++) 133 if (ds->dayyr == year) 134 break; 135 dalybeg = ds->daylb; /* first Sun after dst starts */ 136 daylend = ds->dayle; /* first Sun after dst ends */ 137 dalybeg = sunday(ct, dalybeg); 138 daylend = sunday(ct, daylend); 139 switch (dr->dst_hemi) { 140 case NTH: 141 if (!( 142 (dayno>dalybeg || (dayno==dalybeg && ct->tm_hour>=2)) && 143 (dayno<daylend || (dayno==daylend && ct->tm_hour<1)) 144 )) 145 return(ct); 146 break; 147 case STH: 148 if (!( 149 (dayno>dalybeg || (dayno==dalybeg && ct->tm_hour>=2)) || 150 (dayno<daylend || (dayno==daylend && ct->tm_hour<2)) 151 )) 152 return(ct); 153 break; 154 default: 155 return(ct); 156 } 157 copyt += dr->dst_hrs*60*60; 158 ct = gmtime(©t); 159 ct->tm_isdst++; 160 } 161 return(ct); 162 } 163 164 /* 165 * The argument is a 0-origin day number. 166 * The value is the day number of the first 167 * Sunday on or after the day. 168 */ 169 static 170 sunday(t, d) 171 register struct tm *t; 172 register int d; 173 { 174 if (d >= 58) 175 d += dysize(t->tm_year) - 365; 176 return(d - (d - t->tm_yday + t->tm_wday + 700) % 7); 177 } 178 179 struct tm * 180 gmtime(tim) 181 unsigned long *tim; 182 { 183 register int d0, d1; 184 unsigned long hms, day; 185 register int *tp; 186 static struct tm xtime; 187 188 /* 189 * break initial number into days 190 */ 191 hms = *tim % 86400; 192 day = *tim / 86400; 193 if (hms<0) { 194 hms += 86400; 195 day -= 1; 196 } 197 tp = (int *)&xtime; 198 199 /* 200 * generate hours:minutes:seconds 201 */ 202 *tp++ = hms%60; 203 d1 = hms/60; 204 *tp++ = d1%60; 205 d1 /= 60; 206 *tp++ = d1; 207 208 /* 209 * day is the day number. 210 * generate day of the week. 211 * The addend is 4 mod 7 (1/1/1970 was Thursday) 212 */ 213 214 xtime.tm_wday = (day+7340036)%7; 215 216 /* 217 * year number 218 */ 219 if (day>=0) for(d1=70; day >= dysize(d1); d1++) 220 day -= dysize(d1); 221 else for (d1=70; day<0; d1--) 222 day += dysize(d1-1); 223 xtime.tm_year = d1; 224 xtime.tm_yday = d0 = day; 225 226 /* 227 * generate month 228 */ 229 230 if (dysize(d1)==366) 231 dmsize[1] = 29; 232 for(d1=0; d0 >= dmsize[d1]; d1++) 233 d0 -= dmsize[d1]; 234 dmsize[1] = 28; 235 *tp++ = d0+1; 236 *tp++ = d1; 237 xtime.tm_isdst = 0; 238 return(&xtime); 239 } 240 241 char * 242 asctime(t) 243 struct tm *t; 244 { 245 register char *cp, *ncp; 246 register int *tp; 247 248 cp = cbuf; 249 for (ncp = "Day Mon 00 00:00:00 1900\n"; *cp++ = *ncp++;); 250 ncp = &"SunMonTueWedThuFriSat"[3*t->tm_wday]; 251 cp = cbuf; 252 *cp++ = *ncp++; 253 *cp++ = *ncp++; 254 *cp++ = *ncp++; 255 cp++; 256 tp = &t->tm_mon; 257 ncp = &"JanFebMarAprMayJunJulAugSepOctNovDec"[(*tp)*3]; 258 *cp++ = *ncp++; 259 *cp++ = *ncp++; 260 *cp++ = *ncp++; 261 cp = ct_numb(cp, *--tp); 262 cp = ct_numb(cp, *--tp+100); 263 cp = ct_numb(cp, *--tp+100); 264 cp = ct_numb(cp, *--tp+100); 265 if (t->tm_year>=100) { 266 cp[1] = '2'; 267 cp[2] = '0' + t->tm_year >= 200; 268 } 269 cp += 2; 270 cp = ct_numb(cp, t->tm_year+100); 271 return(cbuf); 272 } 273 274 dysize(y) 275 { 276 if((y%4) == 0) 277 return(366); 278 return(365); 279 } 280 281 static char * 282 ct_numb(cp, n) 283 register char *cp; 284 { 285 cp++; 286 if (n>=10) 287 *cp++ = (n/10)%10 + '0'; 288 else 289 *cp++ = ' '; 290 *cp++ = n%10 + '0'; 291 return(cp); 292 } 293