|
|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 7672 (0x1df8)
Types: TextFile
Notes: UNIX file
Names: »ctime.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
└─⟦f4b8d8c84⟧ UNIX Filesystem
└─⟦this⟧ »libc/gen/ctime.c«
/*
* 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(<ime);
/*
* 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);
}