DataMuseum.dk

Presents historical artifacts from the history of:

Commodore CBM-900

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Commodore CBM-900

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download

⟦391c34314⟧ TextFile

    Length: 7672 (0x1df8)
    Types: TextFile
    Notes: UNIX file
    Names: »ctime.c«

Derivation

└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
    └─⟦f4b8d8c84⟧ UNIX V7 Filesystem
        └─ ⟦this⟧ »libc/gen/ctime.c« 

TextFile

/*
 * Convert time to ascii representation
 *
 * Pseudo system-5, employs TIMEZONE environment for gmt offset,
 * timezone abbreviations, and daylight savings time information.
 *	TIMEZONE=SSS:mmm:DDD:n.d.m:n.d.m:h:m
 * SSS - Standard timezone abbreviation
 * mmm - minutes west of GMT
 * DDD - Daylight timezone abbreviation
 * n.d.m - n'th occurrence of d'th day of week in m'th month of
 *	start and end of daylight savings time.  Negative n indicates
 *	counting backwards from end of month.  Days and months from 1 to n.
 * h - Hour of change from standard to daylight.
 * m - Minutes of adjustment at change.
 * Example - Central standard in current US conventions:
 *	TIMEZONE=CST:3600:CDT:-1.1.4:-1.1.10:2:60
 * Only the first two fields are required.
 * If no daylight timezone is specified, then no daylight conversion is done.
 * If no dates for daylight are given, they default to 83-05-10 US standard.
 * If no hour of daylight time change is specified, it defaults to 2AM.
 * If no minutes of adjustment is specified, it defaults to 60.
 */


#include <time.h>
#include <timeb.h>


#define	HR	60
#define	FEB	1
#define	APR	3
#define	SUNDAY	0
#define	OCT	9
#define	NWDAY	7		/* Number of weekdays */
#define	NMON	12		/* Number of months */
#define	todigit(c) ((c)+'0')

long	timezone = 0L;
char	tzname[2][16] = { "GMT", "" };
static	struct	dsttimes {
	int dst_month, dst_day, dst_occur;
} dsttimes[2] = {
	{ -1, SUNDAY, APR },	/* Last sunday in april */
	{ -1, SUNDAY, OCT }	/* Last sunday in october */
};
static	int	dsthour = 2;
static	int	dstadjust = HR;
static	char	timestr[] = "AAA AAA DD DD:DD:DD DDDD\n";
static	struct	tm	tm;

static	char *daynames[] = {
	"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
};

static	char	months[3*NMON] = "JanFebMarAprMayJunJulAugSepOctNovDec";

/*
 * Days per month
 * Indexed by month (january is 0).
 */
static	char	dpm[] = {
	31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
};

void
settz()
{
	extern char *getenv();
	register char *cp1, *cp2;

	if ((cp1 = getenv("TIMEZONE")) == ((char *)0))
		return;
	timezone = 0;

	/* Read primary timezone name and nul terminate */
	cp2 = tzname[0];
	while (*cp1 && *cp1 != ':' && cp2 < &tzname[0][15])
		*cp2++ = *cp1++;
	*cp2++ = 0;
	while (*cp1 && *cp1++ != ':');

	/* Read timezone offset and convert to seconds */
	timezone = (long)atoi(cp1) * 60L;
	while (*cp1 && *cp1++ != ':');

	/* Read daylight timezone name and nul terminate */
	cp2 = tzname[1];
	while (*cp1 && *cp1 != ':' && cp2 < &tzname[1][15])
		*cp2++ = *cp1++;
	*cp2++ = 0;
	while (*cp1 && *cp1++ != ':');

	/* Exit if no daylight time */
	if (tzname[1][0] == 0)
		return;

	/* Set default dst parameters */
	dsttimes[0].dst_month = APR;
	dsttimes[0].dst_day = SUNDAY;
	dsttimes[0].dst_occur = -1;
	dsttimes[1].dst_month = OCT;
	dsttimes[1].dst_day = SUNDAY;
	dsttimes[1].dst_occur = -1;
	dsthour = 2;
	dstadjust = HR;

	/* Get optional start of daylight time */
	if (*cp1) {
		dsttimes[0].dst_occur = atoi(cp1);
		while (*cp1 && *cp1++ != '.');
		dsttimes[0].dst_day = atoi(cp1)-1;
		while (*cp1 && *cp1++ != '.');
		dsttimes[0].dst_month = atoi(cp1)-1;
		while (*cp1 && *cp1++ != ':');
	}

	/* Get optional end of daylight time */
	if (*cp1) {
		dsttimes[1].dst_occur = atoi(cp1);
		while (*cp1 && *cp1++ != '.');
		dsttimes[1].dst_day = atoi(cp1)-1;
		while (*cp1 && *cp1++ != '.');
		dsttimes[1].dst_month = atoi(cp1)-1;
		while (*cp1 && *cp1++ != ':');
	}

	/* Get optional hour of daylight time advance */
	if (*cp1) {
		dsthour = atoi(cp1);
		while (*cp1 && *cp1++ != ':');
	}

	/* Get optional minutes of adjustment */
	if (*cp1)
		dstadjust = atoi(cp1);
}

/*
 * Most common interface, returns a static string
 * which is a printable version of the time and date.
 */
char *
ctime(tp)
long *tp;
{
	return (asctime(localtime(tp)));
}

/*
 * Do what gmtime does for the local timezone.
 * And correct for daylight time.
 */
struct tm *
localtime(tp)
long *tp;
{
	long ltime;

	settz();
	ltime = *tp - timezone;
	gmtime(&ltime);
	/*
	 * If necessary, adjust for daylight saving time.
	 */
	if (isdaylight()) {
		tm.tm_isdst = 1;
		tm.tm_min += dstadjust;
		while (tm.tm_min >= 60) {
			tm.tm_min -= 60;
			tm.tm_hour += 1;
		}
		if (tm.tm_hour > 23) {
			tm.tm_hour -= 24;
			tm.tm_wday = (tm.tm_wday+NWDAY+1)%NWDAY;
			++tm.tm_yday;
			if (++tm.tm_mday > dpm[tm.tm_mon]) {
				tm.tm_mday = 1;
				++tm.tm_mon;
			}
		}
	} else
		tm.tm_isdst = 0;
	return (&tm);
}

/*
 * Returns a printable version of the time
 * which has been broken down as in the tm structure.
 */
char *
asctime(tmp)
struct tm *tmp;
{
	register char *cp, *xp;
	register unsigned i;

	cp = timestr;
	/*
	 * Day of week
	 */
	if ((i = tmp->tm_wday) >= NWDAY)
		i = 0;
	xp = daynames[i];
	while (*xp)
		*cp++ = *xp++;
	*cp++ = ' ';
	/*
	 * Month
	 */
	if ((i = tmp->tm_mon) >= NMON)
		i = 0;
	xp = &months[i*3];
	*cp++ = *xp++;
	*cp++ = *xp++;
	*cp++ = *xp++;
	*cp++ = ' ';
	/*
	 * Day of month
	 */
	if ((i = tmp->tm_mday) >= 10)
		*cp++ = todigit(i/10);
	else
		*cp++ = ' ';
	*cp++ = todigit(i%10);
	*cp++ = ' ';
	/*
	 * Hours:mins:seconds
	 */
	*cp++ = todigit((i = tmp->tm_hour)/10);
	*cp++ = todigit(i%10);
	*cp++ = ':';
	*cp++ = todigit((i = tmp->tm_min)/10);
	*cp++ = todigit(i%10);
	*cp++ = ':';
	*cp++ = todigit((i = tmp->tm_sec)/10);
	*cp++ = todigit(i%10);
	*cp++ = ' ';
	/*
	 * Year
	 */
	i = tmp->tm_year + 1900;
	*cp++ = todigit(i/1000);
	i = i%1000;
	*cp++ = todigit(i/100);
	i = i%100;
	*cp++ = todigit(i/10);
	*cp++ = todigit(i%10);
	*cp++ = '\n';
	*cp++ = '\0';
	return (timestr);
}

/*
 * Do conversions for Greenwich Mean Time to
 * the tm structure.
 */
struct tm *
gmtime(tp)
long *tp;
{
	long xtime;
	unsigned days;
	long secs;
	int year;
	int ydays;
	int wday;
	register char *mp;

	if ((xtime = *tp) < 0)
		xtime = 0;
	days = xtime/(60L*60L*24L);
	secs = xtime%(60L*60L*24L);
	tm.tm_hour = secs/(60L*60L);
	secs = secs%(60L*60L);
	tm.tm_min = secs/60;
	tm.tm_sec = secs%60;
	/*
	 * Start at Thursday (wday=4) Jan 1, 1970 (the Epoch)
	 * and calculate from there.
	 */
	wday = (4+days)%NWDAY;
	year = 1970;
	for (;;) {
		ydays = isleap(year) ? 366 : 365;
		if (days < ydays)
			break;
		year++;
		days -= ydays;
	}
	tm.tm_year = year-1900;
	tm.tm_yday = days;
	tm.tm_wday = wday;
	/*
	 * Setup february's #days now.
	 */
	if (isleap(year))
		dpm[FEB] = 29;
	else
		dpm[FEB] = 28;
	for (mp = &dpm[0]; mp < &dpm[NMON] && days >= *mp; mp++)
		days -= *mp;
	tm.tm_mon = mp-dpm;
	tm.tm_mday = days+1;
	return (&tm);
}

/*
 * Return 1 on leap years; 0 otherwise.
 */
static
isleap(yr)
register yr;
{
	if (yr%4000 == 0)
		return (0);
	if (yr%400==0 || (yr%100!=0 && yr%4==0))
		return (1);
	return (0);
}

/*
 * Check for daylight savings time.
 */
static
isdaylight()
{
	register int xday;

	if (tzname[1][0] == 0)		/* No name, no daylight time */
		return (0);
	if (tm.tm_mon < dsttimes[0].dst_month)
		return (0);
	else if (tm.tm_mon == dsttimes[0].dst_month) {
		xday = nthday(&dsttimes[0]);
		if (tm.tm_mday != xday)
			return (tm.tm_mday > xday);
		return (tm.tm_hour >= dsthour);
	} else if (tm.tm_mon < dsttimes[1].dst_month)
		return (1);
	else if (tm.tm_mon == dsttimes[1].dst_month) {
		xday = nthday(&dsttimes[1]);
		if (tm.tm_mday != xday)
			return (tm.tm_mday < xday);
		return (tm.tm_hour < dsthour-1);
	}
	return (0);
}

static
nthday(dp)
register struct dsttimes *dp;
{
	register int nthday;
	register int nth;

	nthday = tm.tm_mday - tm.tm_wday + dp->dst_day;
	if ((nth = dp->dst_occur) > 0) {
		while (nthday > 0)
			nthday -= 7;
		do
			nthday += 7;
		while (--nth > 0);
	} else {
		while (nthday < dpm[tm.tm_mon])
			nthday += 7;
		do
			nthday -= 7;
		while (++nth < 0);
	}
	return (nthday);
}