1*12974Ssam /* @(#)ctime.c 4.2 (Berkeley) 06/10/83 */ 21959Swnj /* 31959Swnj * This routine converts time as follows. 41959Swnj * The epoch is 0000 Jan 1 1970 GMT. 51959Swnj * The argument time is in seconds since then. 61959Swnj * The localtime(t) entry returns a pointer to an array 71959Swnj * containing 81959Swnj * seconds (0-59) 91959Swnj * minutes (0-59) 101959Swnj * hours (0-23) 111959Swnj * day of month (1-31) 121959Swnj * month (0-11) 131959Swnj * year-1970 141959Swnj * weekday (0-6, Sun is 0) 151959Swnj * day of the year 161959Swnj * daylight savings flag 171959Swnj * 181959Swnj * The routine calls the system to determine the local 191959Swnj * timezone and whether Daylight Saving Time is permitted locally. 201959Swnj * (DST is then determined by the current US standard rules) 211959Swnj * There is a table that accounts for the peculiarities 221959Swnj * undergone by daylight time in 1974-1975. 231959Swnj * 241959Swnj * The routine does not work 251959Swnj * in Saudi Arabia which runs on Solar time. 261959Swnj * 271959Swnj * asctime(tvec)) 281959Swnj * where tvec is produced by localtime 291959Swnj * returns a ptr to a character string 301959Swnj * that has the ascii time in the form 311959Swnj * Thu Jan 01 00:00:00 1970n0\\ 321959Swnj * 01234567890123456789012345 331959Swnj * 0 1 2 341959Swnj * 351959Swnj * ctime(t) just calls localtime, then asctime. 361959Swnj */ 371959Swnj 381959Swnj #include <time.h> 391959Swnj #include <sys/types.h> 401959Swnj #include <sys/timeb.h> 411959Swnj 421959Swnj static char cbuf[26]; 431959Swnj static int dmsize[12] = 441959Swnj { 451959Swnj 31, 461959Swnj 28, 471959Swnj 31, 481959Swnj 30, 491959Swnj 31, 501959Swnj 30, 511959Swnj 31, 521959Swnj 31, 531959Swnj 30, 541959Swnj 31, 551959Swnj 30, 561959Swnj 31 571959Swnj }; 581959Swnj 591959Swnj /* 601959Swnj * The following table is used for 1974 and 1975 and 611959Swnj * gives the day number of the first day after the Sunday of the 621959Swnj * change. 631959Swnj */ 64*12974Ssam struct dstab { 65*12974Ssam int dayyr; 661959Swnj int daylb; 671959Swnj int dayle; 681959Swnj }; 691959Swnj 70*12974Ssam static struct dstab usdaytab[] = { 71*12974Ssam 1974, 5, 333, /* 1974: Jan 6 - last Sun. in Nov */ 72*12974Ssam 1975, 58, 303, /* 1975: Last Sun. in Feb - last Sun in Oct */ 73*12974Ssam 0, 119, 303, /* all other years: end Apr - end Oct */ 74*12974Ssam }; 75*12974Ssam static struct dstab ausdaytab[] = { 76*12974Ssam 1970, 400, 0, /* 1970: no daylight saving at all */ 77*12974Ssam 1971, 303, 0, /* 1971: daylight saving from Oct 31 */ 78*12974Ssam 1972, 303, 58, /* 1972: Jan 1 -> Feb 27 & Oct 31 -> dec 31 */ 79*12974Ssam 0, 303, 65, /* others: -> Mar 7, Oct 31 -> */ 80*12974Ssam }; 81*12974Ssam 82*12974Ssam static struct dayrules { 83*12974Ssam int dst_type; /* number obtained from system */ 84*12974Ssam int dst_hrs; /* hours to add when dst on */ 85*12974Ssam struct dstab * dst_rules; /* one of the above */ 86*12974Ssam enum {STH,NTH} dst_hemi; /* southern, northern hemisphere */ 87*12974Ssam } dayrules [] = { 88*12974Ssam DST_USA, 1, usdaytab, NTH, 89*12974Ssam DST_AUST, 1, ausdaytab, STH, 90*12974Ssam -1, 91*12974Ssam }; 92*12974Ssam 931959Swnj struct tm *gmtime(); 941959Swnj char *ct_numb(); 951959Swnj struct tm *localtime(); 961959Swnj char *ctime(); 971959Swnj char *ct_num(); 981959Swnj char *asctime(); 991959Swnj 1001959Swnj char * 1011959Swnj ctime(t) 102*12974Ssam unsigned long *t; 1031959Swnj { 1041959Swnj return(asctime(localtime(t))); 1051959Swnj } 1061959Swnj 1071959Swnj struct tm * 1081959Swnj localtime(tim) 109*12974Ssam unsigned long *tim; 1101959Swnj { 1111959Swnj register int dayno; 1121959Swnj register struct tm *ct; 113*12974Ssam register dalybeg, daylend; 114*12974Ssam register struct dayrules *dr; 115*12974Ssam register struct dstab *ds; 116*12974Ssam int year; 117*12974Ssam unsigned long copyt; 118*12974Ssam struct timeval curtime; 119*12974Ssam struct timezone zone; 1201959Swnj 121*12974Ssam gettimeofday(&curtime, &zone); 122*12974Ssam copyt = *tim - (unsigned long)zone.tz_minuteswest*60; 1231959Swnj ct = gmtime(©t); 1241959Swnj dayno = ct->tm_yday; 125*12974Ssam for (dr = dayrules; dr->dst_type >= 0; dr++) 126*12974Ssam if (dr->dst_type == zone.tz_dsttime) 127*12974Ssam break; 128*12974Ssam if (dr->dst_type >= 0) { 129*12974Ssam year = ct->tm_year + 1900; 130*12974Ssam for (ds = dr->dst_rules; ds->dayyr; ds++) 131*12974Ssam if (ds->dayyr == year) 132*12974Ssam break; 133*12974Ssam dalybeg = ds->daylb; /* first Sun after dst starts */ 134*12974Ssam daylend = ds->dayle; /* first Sun after dst ends */ 135*12974Ssam dalybeg = sunday(ct, dalybeg); 136*12974Ssam daylend = sunday(ct, daylend); 137*12974Ssam switch (dr->dst_hemi) { 138*12974Ssam case NTH: 139*12974Ssam if (!( 140*12974Ssam (dayno>dalybeg || (dayno==dalybeg && ct->tm_hour>=2)) && 141*12974Ssam (dayno<daylend || (dayno==daylend && ct->tm_hour<1)) 142*12974Ssam )) 143*12974Ssam return(ct); 144*12974Ssam break; 145*12974Ssam case STH: 146*12974Ssam if (!( 147*12974Ssam (dayno>dalybeg || (dayno==dalybeg && ct->tm_hour>=2)) || 148*12974Ssam (dayno<daylend || (dayno==daylend && ct->tm_hour<2)) 149*12974Ssam )) 150*12974Ssam return(ct); 151*12974Ssam break; 152*12974Ssam default: 153*12974Ssam return(ct); 154*12974Ssam } 155*12974Ssam copyt += dr->dst_hrs*60*60; 1561959Swnj ct = gmtime(©t); 1571959Swnj ct->tm_isdst++; 1581959Swnj } 1591959Swnj return(ct); 1601959Swnj } 1611959Swnj 1621959Swnj /* 1631959Swnj * The argument is a 0-origin day number. 1641959Swnj * The value is the day number of the first 1651959Swnj * Sunday on or after the day. 1661959Swnj */ 1671959Swnj static 1681959Swnj sunday(t, d) 1691959Swnj register struct tm *t; 1701959Swnj register int d; 1711959Swnj { 1721959Swnj if (d >= 58) 1731959Swnj d += dysize(t->tm_year) - 365; 1741959Swnj return(d - (d - t->tm_yday + t->tm_wday + 700) % 7); 1751959Swnj } 1761959Swnj 1771959Swnj struct tm * 1781959Swnj gmtime(tim) 179*12974Ssam unsigned long *tim; 1801959Swnj { 1811959Swnj register int d0, d1; 182*12974Ssam unsigned long hms, day; 1831959Swnj register int *tp; 1841959Swnj static struct tm xtime; 1851959Swnj 1861959Swnj /* 1871959Swnj * break initial number into days 1881959Swnj */ 1891959Swnj hms = *tim % 86400; 1901959Swnj day = *tim / 86400; 1911959Swnj if (hms<0) { 1921959Swnj hms += 86400; 1931959Swnj day -= 1; 1941959Swnj } 1951959Swnj tp = (int *)&xtime; 1961959Swnj 1971959Swnj /* 1981959Swnj * generate hours:minutes:seconds 1991959Swnj */ 2001959Swnj *tp++ = hms%60; 2011959Swnj d1 = hms/60; 2021959Swnj *tp++ = d1%60; 2031959Swnj d1 /= 60; 2041959Swnj *tp++ = d1; 2051959Swnj 2061959Swnj /* 2071959Swnj * day is the day number. 2081959Swnj * generate day of the week. 2091959Swnj * The addend is 4 mod 7 (1/1/1970 was Thursday) 2101959Swnj */ 2111959Swnj 2121959Swnj xtime.tm_wday = (day+7340036)%7; 2131959Swnj 2141959Swnj /* 2151959Swnj * year number 2161959Swnj */ 2171959Swnj if (day>=0) for(d1=70; day >= dysize(d1); d1++) 2181959Swnj day -= dysize(d1); 2191959Swnj else for (d1=70; day<0; d1--) 2201959Swnj day += dysize(d1-1); 2211959Swnj xtime.tm_year = d1; 2221959Swnj xtime.tm_yday = d0 = day; 2231959Swnj 2241959Swnj /* 2251959Swnj * generate month 2261959Swnj */ 2271959Swnj 2281959Swnj if (dysize(d1)==366) 2291959Swnj dmsize[1] = 29; 2301959Swnj for(d1=0; d0 >= dmsize[d1]; d1++) 2311959Swnj d0 -= dmsize[d1]; 2321959Swnj dmsize[1] = 28; 2331959Swnj *tp++ = d0+1; 2341959Swnj *tp++ = d1; 2351959Swnj xtime.tm_isdst = 0; 2361959Swnj return(&xtime); 2371959Swnj } 2381959Swnj 2391959Swnj char * 2401959Swnj asctime(t) 2411959Swnj struct tm *t; 2421959Swnj { 2431959Swnj register char *cp, *ncp; 2441959Swnj register int *tp; 2451959Swnj 2461959Swnj cp = cbuf; 2471959Swnj for (ncp = "Day Mon 00 00:00:00 1900\n"; *cp++ = *ncp++;); 2481959Swnj ncp = &"SunMonTueWedThuFriSat"[3*t->tm_wday]; 2491959Swnj cp = cbuf; 2501959Swnj *cp++ = *ncp++; 2511959Swnj *cp++ = *ncp++; 2521959Swnj *cp++ = *ncp++; 2531959Swnj cp++; 2541959Swnj tp = &t->tm_mon; 2551959Swnj ncp = &"JanFebMarAprMayJunJulAugSepOctNovDec"[(*tp)*3]; 2561959Swnj *cp++ = *ncp++; 2571959Swnj *cp++ = *ncp++; 2581959Swnj *cp++ = *ncp++; 2591959Swnj cp = ct_numb(cp, *--tp); 2601959Swnj cp = ct_numb(cp, *--tp+100); 2611959Swnj cp = ct_numb(cp, *--tp+100); 2621959Swnj cp = ct_numb(cp, *--tp+100); 2631959Swnj if (t->tm_year>=100) { 2641959Swnj cp[1] = '2'; 265*12974Ssam cp[2] = '0' + t->tm_year >= 200; 2661959Swnj } 2671959Swnj cp += 2; 2681959Swnj cp = ct_numb(cp, t->tm_year+100); 2691959Swnj return(cbuf); 2701959Swnj } 2711959Swnj 2721959Swnj dysize(y) 2731959Swnj { 2741959Swnj if((y%4) == 0) 2751959Swnj return(366); 2761959Swnj return(365); 2771959Swnj } 2781959Swnj 2791959Swnj static char * 2801959Swnj ct_numb(cp, n) 2811959Swnj register char *cp; 2821959Swnj { 2831959Swnj cp++; 2841959Swnj if (n>=10) 2851959Swnj *cp++ = (n/10)%10 + '0'; 2861959Swnj else 2871959Swnj *cp++ = ' '; 2881959Swnj *cp++ = n%10 + '0'; 2891959Swnj return(cp); 2901959Swnj } 291