1*13582Ssam #ifndef lint 2*13582Ssam static char sccsid[] = "@(#)ctime.c 4.3 (Berkeley) 07/01/83"; 3*13582Ssam #endif 41959Swnj /* 51959Swnj * This routine converts time as follows. 61959Swnj * The epoch is 0000 Jan 1 1970 GMT. 71959Swnj * The argument time is in seconds since then. 81959Swnj * The localtime(t) entry returns a pointer to an array 91959Swnj * containing 101959Swnj * seconds (0-59) 111959Swnj * minutes (0-59) 121959Swnj * hours (0-23) 131959Swnj * day of month (1-31) 141959Swnj * month (0-11) 151959Swnj * year-1970 161959Swnj * weekday (0-6, Sun is 0) 171959Swnj * day of the year 181959Swnj * daylight savings flag 191959Swnj * 201959Swnj * The routine calls the system to determine the local 211959Swnj * timezone and whether Daylight Saving Time is permitted locally. 221959Swnj * (DST is then determined by the current US standard rules) 231959Swnj * There is a table that accounts for the peculiarities 241959Swnj * undergone by daylight time in 1974-1975. 251959Swnj * 261959Swnj * The routine does not work 271959Swnj * in Saudi Arabia which runs on Solar time. 281959Swnj * 291959Swnj * asctime(tvec)) 301959Swnj * where tvec is produced by localtime 311959Swnj * returns a ptr to a character string 321959Swnj * that has the ascii time in the form 331959Swnj * Thu Jan 01 00:00:00 1970n0\\ 341959Swnj * 01234567890123456789012345 351959Swnj * 0 1 2 361959Swnj * 371959Swnj * ctime(t) just calls localtime, then asctime. 381959Swnj */ 391959Swnj 40*13582Ssam #include <sys/time.h> 411959Swnj #include <sys/types.h> 421959Swnj #include <sys/timeb.h> 431959Swnj 441959Swnj static char cbuf[26]; 451959Swnj static int dmsize[12] = 461959Swnj { 471959Swnj 31, 481959Swnj 28, 491959Swnj 31, 501959Swnj 30, 511959Swnj 31, 521959Swnj 30, 531959Swnj 31, 541959Swnj 31, 551959Swnj 30, 561959Swnj 31, 571959Swnj 30, 581959Swnj 31 591959Swnj }; 601959Swnj 611959Swnj /* 621959Swnj * The following table is used for 1974 and 1975 and 631959Swnj * gives the day number of the first day after the Sunday of the 641959Swnj * change. 651959Swnj */ 6612974Ssam struct dstab { 6712974Ssam int dayyr; 681959Swnj int daylb; 691959Swnj int dayle; 701959Swnj }; 711959Swnj 7212974Ssam static struct dstab usdaytab[] = { 7312974Ssam 1974, 5, 333, /* 1974: Jan 6 - last Sun. in Nov */ 7412974Ssam 1975, 58, 303, /* 1975: Last Sun. in Feb - last Sun in Oct */ 7512974Ssam 0, 119, 303, /* all other years: end Apr - end Oct */ 7612974Ssam }; 7712974Ssam static struct dstab ausdaytab[] = { 7812974Ssam 1970, 400, 0, /* 1970: no daylight saving at all */ 7912974Ssam 1971, 303, 0, /* 1971: daylight saving from Oct 31 */ 8012974Ssam 1972, 303, 58, /* 1972: Jan 1 -> Feb 27 & Oct 31 -> dec 31 */ 8112974Ssam 0, 303, 65, /* others: -> Mar 7, Oct 31 -> */ 8212974Ssam }; 8312974Ssam 8412974Ssam static struct dayrules { 8512974Ssam int dst_type; /* number obtained from system */ 8612974Ssam int dst_hrs; /* hours to add when dst on */ 8712974Ssam struct dstab * dst_rules; /* one of the above */ 8812974Ssam enum {STH,NTH} dst_hemi; /* southern, northern hemisphere */ 8912974Ssam } dayrules [] = { 9012974Ssam DST_USA, 1, usdaytab, NTH, 9112974Ssam DST_AUST, 1, ausdaytab, STH, 9212974Ssam -1, 9312974Ssam }; 9412974Ssam 951959Swnj struct tm *gmtime(); 961959Swnj char *ct_numb(); 971959Swnj struct tm *localtime(); 981959Swnj char *ctime(); 991959Swnj char *ct_num(); 1001959Swnj char *asctime(); 1011959Swnj 1021959Swnj char * 1031959Swnj ctime(t) 10412974Ssam unsigned long *t; 1051959Swnj { 1061959Swnj return(asctime(localtime(t))); 1071959Swnj } 1081959Swnj 1091959Swnj struct tm * 1101959Swnj localtime(tim) 11112974Ssam unsigned long *tim; 1121959Swnj { 1131959Swnj register int dayno; 1141959Swnj register struct tm *ct; 11512974Ssam register dalybeg, daylend; 11612974Ssam register struct dayrules *dr; 11712974Ssam register struct dstab *ds; 11812974Ssam int year; 11912974Ssam unsigned long copyt; 12012974Ssam struct timeval curtime; 12112974Ssam struct timezone zone; 1221959Swnj 12312974Ssam gettimeofday(&curtime, &zone); 12412974Ssam copyt = *tim - (unsigned long)zone.tz_minuteswest*60; 1251959Swnj ct = gmtime(©t); 1261959Swnj dayno = ct->tm_yday; 12712974Ssam for (dr = dayrules; dr->dst_type >= 0; dr++) 12812974Ssam if (dr->dst_type == zone.tz_dsttime) 12912974Ssam break; 13012974Ssam if (dr->dst_type >= 0) { 13112974Ssam year = ct->tm_year + 1900; 13212974Ssam for (ds = dr->dst_rules; ds->dayyr; ds++) 13312974Ssam if (ds->dayyr == year) 13412974Ssam break; 13512974Ssam dalybeg = ds->daylb; /* first Sun after dst starts */ 13612974Ssam daylend = ds->dayle; /* first Sun after dst ends */ 13712974Ssam dalybeg = sunday(ct, dalybeg); 13812974Ssam daylend = sunday(ct, daylend); 13912974Ssam switch (dr->dst_hemi) { 14012974Ssam case NTH: 14112974Ssam if (!( 14212974Ssam (dayno>dalybeg || (dayno==dalybeg && ct->tm_hour>=2)) && 14312974Ssam (dayno<daylend || (dayno==daylend && ct->tm_hour<1)) 14412974Ssam )) 14512974Ssam return(ct); 14612974Ssam break; 14712974Ssam case STH: 14812974Ssam if (!( 14912974Ssam (dayno>dalybeg || (dayno==dalybeg && ct->tm_hour>=2)) || 15012974Ssam (dayno<daylend || (dayno==daylend && ct->tm_hour<2)) 15112974Ssam )) 15212974Ssam return(ct); 15312974Ssam break; 15412974Ssam default: 15512974Ssam return(ct); 15612974Ssam } 15712974Ssam copyt += dr->dst_hrs*60*60; 1581959Swnj ct = gmtime(©t); 1591959Swnj ct->tm_isdst++; 1601959Swnj } 1611959Swnj return(ct); 1621959Swnj } 1631959Swnj 1641959Swnj /* 1651959Swnj * The argument is a 0-origin day number. 1661959Swnj * The value is the day number of the first 1671959Swnj * Sunday on or after the day. 1681959Swnj */ 1691959Swnj static 1701959Swnj sunday(t, d) 1711959Swnj register struct tm *t; 1721959Swnj register int d; 1731959Swnj { 1741959Swnj if (d >= 58) 1751959Swnj d += dysize(t->tm_year) - 365; 1761959Swnj return(d - (d - t->tm_yday + t->tm_wday + 700) % 7); 1771959Swnj } 1781959Swnj 1791959Swnj struct tm * 1801959Swnj gmtime(tim) 18112974Ssam unsigned long *tim; 1821959Swnj { 1831959Swnj register int d0, d1; 18412974Ssam unsigned long hms, day; 1851959Swnj register int *tp; 1861959Swnj static struct tm xtime; 1871959Swnj 1881959Swnj /* 1891959Swnj * break initial number into days 1901959Swnj */ 1911959Swnj hms = *tim % 86400; 1921959Swnj day = *tim / 86400; 1931959Swnj if (hms<0) { 1941959Swnj hms += 86400; 1951959Swnj day -= 1; 1961959Swnj } 1971959Swnj tp = (int *)&xtime; 1981959Swnj 1991959Swnj /* 2001959Swnj * generate hours:minutes:seconds 2011959Swnj */ 2021959Swnj *tp++ = hms%60; 2031959Swnj d1 = hms/60; 2041959Swnj *tp++ = d1%60; 2051959Swnj d1 /= 60; 2061959Swnj *tp++ = d1; 2071959Swnj 2081959Swnj /* 2091959Swnj * day is the day number. 2101959Swnj * generate day of the week. 2111959Swnj * The addend is 4 mod 7 (1/1/1970 was Thursday) 2121959Swnj */ 2131959Swnj 2141959Swnj xtime.tm_wday = (day+7340036)%7; 2151959Swnj 2161959Swnj /* 2171959Swnj * year number 2181959Swnj */ 2191959Swnj if (day>=0) for(d1=70; day >= dysize(d1); d1++) 2201959Swnj day -= dysize(d1); 2211959Swnj else for (d1=70; day<0; d1--) 2221959Swnj day += dysize(d1-1); 2231959Swnj xtime.tm_year = d1; 2241959Swnj xtime.tm_yday = d0 = day; 2251959Swnj 2261959Swnj /* 2271959Swnj * generate month 2281959Swnj */ 2291959Swnj 2301959Swnj if (dysize(d1)==366) 2311959Swnj dmsize[1] = 29; 2321959Swnj for(d1=0; d0 >= dmsize[d1]; d1++) 2331959Swnj d0 -= dmsize[d1]; 2341959Swnj dmsize[1] = 28; 2351959Swnj *tp++ = d0+1; 2361959Swnj *tp++ = d1; 2371959Swnj xtime.tm_isdst = 0; 2381959Swnj return(&xtime); 2391959Swnj } 2401959Swnj 2411959Swnj char * 2421959Swnj asctime(t) 2431959Swnj struct tm *t; 2441959Swnj { 2451959Swnj register char *cp, *ncp; 2461959Swnj register int *tp; 2471959Swnj 2481959Swnj cp = cbuf; 2491959Swnj for (ncp = "Day Mon 00 00:00:00 1900\n"; *cp++ = *ncp++;); 2501959Swnj ncp = &"SunMonTueWedThuFriSat"[3*t->tm_wday]; 2511959Swnj cp = cbuf; 2521959Swnj *cp++ = *ncp++; 2531959Swnj *cp++ = *ncp++; 2541959Swnj *cp++ = *ncp++; 2551959Swnj cp++; 2561959Swnj tp = &t->tm_mon; 2571959Swnj ncp = &"JanFebMarAprMayJunJulAugSepOctNovDec"[(*tp)*3]; 2581959Swnj *cp++ = *ncp++; 2591959Swnj *cp++ = *ncp++; 2601959Swnj *cp++ = *ncp++; 2611959Swnj cp = ct_numb(cp, *--tp); 2621959Swnj cp = ct_numb(cp, *--tp+100); 2631959Swnj cp = ct_numb(cp, *--tp+100); 2641959Swnj cp = ct_numb(cp, *--tp+100); 2651959Swnj if (t->tm_year>=100) { 2661959Swnj cp[1] = '2'; 26712974Ssam cp[2] = '0' + t->tm_year >= 200; 2681959Swnj } 2691959Swnj cp += 2; 2701959Swnj cp = ct_numb(cp, t->tm_year+100); 2711959Swnj return(cbuf); 2721959Swnj } 2731959Swnj 2741959Swnj dysize(y) 2751959Swnj { 2761959Swnj if((y%4) == 0) 2771959Swnj return(366); 2781959Swnj return(365); 2791959Swnj } 2801959Swnj 2811959Swnj static char * 2821959Swnj ct_numb(cp, n) 2831959Swnj register char *cp; 2841959Swnj { 2851959Swnj cp++; 2861959Swnj if (n>=10) 2871959Swnj *cp++ = (n/10)%10 + '0'; 2881959Swnj else 2891959Swnj *cp++ = ' '; 2901959Swnj *cp++ = n%10 + '0'; 2911959Swnj return(cp); 2921959Swnj } 293