Personal tools
You are here: Home Projects C++ Cfront releases Release 3.0.3 source libSC Time ctime time_comm.c
Document Actions

time_comm.c

by Michael L Powell last modified 2007-01-26 03:24

Click here to get the file

Size 9.3 kB - File type text/plain

File contents

/*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 <ctype.h>
#include <sys/types.h>
#include "mytime.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#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(&copyt);
/*
    cout 
	<< "gmtime(&copyt) 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(&copyt);
/*
	cout 
	    << "gmtime(&copyt) 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;
}
« April 2024 »
Su Mo Tu We Th Fr Sa
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
 

Powered by Plone CMS, the Open Source Content Management System

This site conforms to the following standards: