/*ident "@(#)Time:ctime/time_comm.c 3.1" */ /****************************************************************************** * * C++ Standard Components, Release 3.0. * * Copyright (c) 1991, 1992 AT&T and Unix System Laboratories, Inc. * Copyright (c) 1988, 1989, 1990 AT&T. All Rights Reserved. * * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T and Unix System * Laboratories, Inc. The copyright notice above does not evidence * any actual or intended publication of such source code. * ******************************************************************************/ // Functions common to ctime(3C) and cftime(3C) #include #include #include "mytime.h" #include #include #include #define SEC_IN_DAY (24 * 60 * 60) #define MAXTZNAME 3 /* The year_size macro is good for the years [1901-2099]. */ #define year_size(A) (((A) % 4) ? 365 : 366) // global ctime(3) variables time_t timezone_ATTLC = 0; time_t altzone_ATTLC = 0; int daylight_ATTLC = 0; static char gmt[4] = "GMT"; static char bbb[4] = " "; char *tzname_ATTLC[] = { gmt, bbb }; // In the original, the following were static variables. // We make the external so that we can simulate multiple // concurrent timezones: time_t start_dst_ATTLC ; // Start date of alternate time zone time_t end_dst_ATTLC; // End date of alternate time zone // local functions static char* getzname(char* p,char* tz); static char* gettime(char* p,time_t* timez,int f); static char* getdigit(char* ptr,int* d); static int getdst(char* p,time_t* s,time_t* e); static int sunday(register struct tm* t, long d); static void set_TZ(void); // The following functions used to be local to this file: //static void getusa(long* s,long* e,struct tm* t); //static tm * gmtime(time_t*); static short month_size[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; struct tm * localtime_ATTLC(time_t* tim){ register struct tm* ct; long daybegin, dayend; time_t copyt, curr; // We are faking multiple timezones by setting the // global ctime variables directly prior to calling // localtime(); we must therefore prevent localtime() // from calling tzset(), which reads the TZ variable // and sets up the global ctime variables based on // its contents. // // tzset(); /* cout << "enter localtime with *tim, timezone=" << *tim << ", " << timezone_ATTLC << "\n" ; */ copyt = *tim - timezone_ATTLC; ct = gmtime_ATTLC(©t); /* cout << "gmtime(©t) returns\n" << " ct->tm_sec=" << ct->tm_sec << "\n" << " ct->tm_min=" << ct->tm_min << "\n" << " ct->tm_hour=" << ct->tm_hour << "\n" << " ct->tm_mday=" << ct->tm_mday << "\n" << " ct->tm_mon=" << ct->tm_mon << "\n" << " ct->tm_year=" << ct->tm_year << "\n" << " ct->tm_wday=" << ct->tm_wday << "\n" << " ct->tm_yday=" << ct->tm_yday << "\n" << " ct->tm_isdst=" << ct->tm_isdst << "\n" ; */ if( !daylight_ATTLC ){ return(ct); } curr = ( ct->tm_yday*SEC_IN_DAY + ct->tm_hour*3600 + ct->tm_min*60 + ct->tm_sec ); // cout << "in localtime, curr=" << curr << "\n"; if ( start_dst_ATTLC == 0 && end_dst_ATTLC == 0){ getusa_ATTLC(&daybegin, &dayend, ct); /* cout << "in localtime, getusa returns daybegin=" << daybegin << ", dayend=" << dayend << "\n" ; */ }else{ daybegin = start_dst_ATTLC; dayend = end_dst_ATTLC; } if( curr >= daybegin && curr < dayend ){ copyt = *tim - altzone_ATTLC; /* cout << "in localtime, recompute copyt=" << copyt << "\n" ; */ ct = gmtime_ATTLC(©t); /* cout << "gmtime(©t) returns\n" << " ct->tm_sec=" << ct->tm_sec << "\n" << " ct->tm_min=" << ct->tm_min << "\n" << " ct->tm_hour=" << ct->tm_hour << "\n" << " ct->tm_mday=" << ct->tm_mday << "\n" << " ct->tm_mon=" << ct->tm_mon << "\n" << " ct->tm_year=" << ct->tm_year << "\n" << " ct->tm_wday=" << ct->tm_wday << "\n" << " ct->tm_yday=" << ct->tm_yday << "\n" << " ct->tm_isdst=" << ct->tm_isdst << "\n" ; */ ct->tm_isdst = 1; } //fprintf(stderr, "localtime 2 returns %d\n", (int)ct->tm_hour); return(ct); } struct tm * gmtime_ATTLC(time_t* tim){ register int d0, d1; long hms, day; static struct tm xtime; // Break initial number into days hms = *tim % SEC_IN_DAY; day = *tim / SEC_IN_DAY; if( hms < 0 ){ hms += SEC_IN_DAY; day -= 1; } // Generate hours:minutes:seconds xtime.tm_sec = (int)(hms % 60); d1 = (int)(hms / 60); xtime.tm_min = d1 % 60; d1 /= 60; xtime.tm_hour = d1; // Generate day of the week. // The addend is 4 mod 7 (1/1/1970 was Thursday) xtime.tm_wday = (int)((day + 7340036L) % 7); // Generate year number if( day >= 0 ){ for(d1=70; day >= year_size(d1); d1++){ day -= year_size(d1); } }else{ for(d1=70; day < 0; d1--){ day += year_size(d1-1); } } xtime.tm_year = d1; xtime.tm_yday = d0 = (int)day; // Generate month if(year_size(d1) == 366){ month_size[1] = 29; } for(d1 = 0; d0 >= month_size[d1]; d1++){ d0 -= month_size[d1]; } month_size[1] = 28; xtime.tm_mday = d0 + 1; xtime.tm_mon = d1; xtime.tm_isdst = 0; return(&xtime); } void tzset_ATTLC(){ set_TZ(); char *ptr; if ( (ptr = getenv("TZ")) == NULL){ return; } // Get main time zone name and difference from GMT if( ((ptr = getzname(ptr,tzname_ATTLC[0])) == 0) || ((ptr = gettime(ptr,&timezone_ATTLC,1)) == 0) ){ return; } altzone_ATTLC = timezone_ATTLC - 3600; start_dst_ATTLC = end_dst_ATTLC = 0; daylight_ATTLC = 0; // Get alternate time zone name if( (ptr = getzname(ptr,tzname_ATTLC[1])) == 0 ){ return; } daylight_ATTLC = 1; // If the difference between alternate time zone and // GMT is not given, use one hour as default. if( *ptr == '\0' ){ return; } if( *ptr != ';' ){ if( (ptr = gettime(ptr,&altzone_ATTLC,1)) == 0 || *ptr != ';' ){ return; } } getdst(ptr + 1,&start_dst_ATTLC, &end_dst_ATTLC); } static char * getzname(char* p,char* tz){ int n = MAXTZNAME; if( !isalpha(*p) ){ return(0); } do{ *tz++ = *p ; }while( --n > 0 && isalpha(*++p) ); while( isalpha(*p) ){ p++; } while( --n >= 0 ){ *tz++ = ' '; // Pad with blanks } return(p); } static char* gettime(char* p,time_t* timez,int f){ register time_t t = 0; int d, sign = 0; d = 0; if( f ){ if( (sign = (*p == '-')) || (*p == '+') ){ p++; } } if( (p = getdigit(p,&d)) != 0 ){ t = d * 60 * 60; if( *p == ':' ){ if( (p = getdigit(p+1,&d)) != 0 ){ t += d * 60; if( *p == ':' ){ if( (p = getdigit(p+1,&d)) != 0 ){ t += d; } } } } } if( sign ){ *timez = -t; }else{ *timez = t; } return(p); } static char* getdigit(char* ptr,int* d){ if( !isdigit(*ptr) ){ return(0); } *d = 0; do{ *d *= 10; *d += *ptr - '0'; }while( (isdigit(*++ptr)) ); return(ptr); } static int getdst(char* p,time_t* s,time_t* e){ int lsd,led; time_t st,et; st = et = 0; // Default for start and end time is 00:00:00 if( (p = getdigit(p,&lsd)) == 0 ){ return(0); } lsd -= 1; // keep julian count in sync with date 1-366 if( (*p == '/') && ((p = gettime(p+1,&st,0)) == 0) ){ return(0); } if( *p == ',' ){ if( (p = getdigit(p+1,&led)) == 0 ){ return(0); } led -= 1; // keep julian count in sync with date 1-366 if( (*p == '/') && ((p = gettime(p+1,&et,0)) == 0) ){ return(0); } } // Convert the time into seconds *s = (long)(lsd * SEC_IN_DAY + st); *e = (long)(led * SEC_IN_DAY + et - (timezone_ATTLC - altzone_ATTLC)); return(1); } void getusa_ATTLC(long* s,long* e,struct tm* t){ static struct { int yrbgn; int daylb; int dayle; } daytab[] = { 87, 96, 303, // new legislation - 1st Sun in April 76, 119, 303, 75, 58, 303, // 1975: Last Sun in Feb - last Sun in Oct 74, 5, 333, // 1974: Jan 6 - last Sun. in Nov 69, 119, 303, // some timezones have legal times in 1969 -10000, 119, 303, // treat the distant past under current rules }; int i = 0; while( t->tm_year < daytab[i].yrbgn ){ // can't be less than 69 i++; } *s = daytab[i].daylb; // fall through the loop when in correct interval *e = daytab[i].dayle; *s = sunday(t, *s); *e = sunday(t, *e); *s = (long)(*s * SEC_IN_DAY +2*60*60); *e = (long)(*e * SEC_IN_DAY +60*60); } static int sunday(register struct tm* t, long d){ if( d >= 58 ){ d += year_size(t->tm_year) - 365; } return (int)(d - (d - t->tm_yday + t->tm_wday + 700) % 7); } static void set_TZ(void) { char *p; if ((p = getenv("TZ")) == NULL) { return; } if (strcmp(p, "US/Eastern") == 0) { putenv("TZ=EST5EDT"); return; } if (strcmp(p, "US/Central") == 0) { putenv("TZ=CST6CDT"); return; } if (strcmp(p, "US/Mountain") == 0) { putenv("TZ=MST7MDT"); return; } if (strcmp(p, "US/Pacific") == 0) { putenv("TZ=PST8PDT"); return; } if (strcmp(p, "CA/Yukon") == 0) { putenv("TZ=YST9YDT"); return; } if (strcmp(p, "US/Hawaii") == 0) { putenv("TZ=HST10"); return; } return; }