|
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 - 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); }