Annotation of coherent/d/lib/libc/gen/ctime.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Convert time to ascii representation
        !             3:  *
        !             4:  * Pseudo system-5, employs TIMEZONE environment for gmt offset,
        !             5:  * timezone abbreviations, and daylight savings time information.
        !             6:  *     TIMEZONE=SSS:mmm:DDD:n.d.m:n.d.m:h:m
        !             7:  * SSS - Standard timezone abbreviation up to 31 characters long
        !             8:  * mmm - minutes west of GMT
        !             9:  * DDD - Daylight timezone abbreviation also 31 characters
        !            10:  * n.d.m - n'th occurrence of d'th day of week in m'th month of
        !            11:  *     start and end of daylight savings time.  Negative n indicates
        !            12:  *     counting backwards from end of month.  Zero n indicates absolute date,
        !            13:  *     d'th day of m'th month.  Days and months from 1 to n.
        !            14:  * h - Hour of change from standard to daylight.
        !            15:  * m - Minutes of adjustment at change.
        !            16:  * Example - Central standard in current US conventions:
        !            17:  *     TIMEZONE=CST:3600:CDT:-1.1.4:-1.1.10:2:60
        !            18:  * Only the first two fields are required.
        !            19:  * If no daylight timezone is specified, then no daylight conversion is done.
        !            20:  * If no dates for daylight are given, they default to 83-05-10 US standard.
        !            21:  * If no hour of daylight time change is specified, it defaults to 2AM.
        !            22:  * If no minutes of adjustment is specified, it defaults to 60.
        !            23:  * These defaults can be changed by overwriting tzdstdef[].
        !            24:  */
        !            25: 
        !            26: 
        !            27: #include <time.h>
        !            28: #include <sys/timeb.h>
        !            29: 
        !            30: 
        !            31: #define        FEB     1
        !            32: #define        NWDAY   7               /* Number of weekdays */
        !            33: #define        NMON    12              /* Number of months */
        !            34: #define        todigit(c) ((c)+'0')
        !            35: 
        !            36: long   timezone = 0L;
        !            37: char   tzname[2][32] = { "GMT", "" };
        !            38: char   tzdstdef[] = "1.1.4:-1.1.10:2:60......";
        !            39: static struct  dsttimes {
        !            40:        char dst_month, dst_day, dst_occur;
        !            41: } dsttimes[2] = {
        !            42:        {  1, 0, 3 },   /* First sunday in april */
        !            43:        { -1, 0, 9 }    /* Last sunday in october */
        !            44: };
        !            45: static char    dsthour = 2;
        !            46: static char    timestr[] = "AAA AAA DD DD:DD:DD DDDD\n";
        !            47: static char daynames[3*NWDAY+1] = "SunMonTueWedThuFriSat";
        !            48: static char months[3*NMON+1] = "JanFebMarAprMayJunJulAugSepOctNovDec";
        !            49: static char dpm[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
        !            50: static int     dstadjust = 60*60;      /* In seconds */
        !            51: static struct  tm      tm;
        !            52: 
        !            53: /* Set the timezone parameters, once is enough */
        !            54: void
        !            55: settz()
        !            56: {
        !            57:        extern char *getenv();
        !            58:        register char *cp1, *cp2;
        !            59:        static int settz = 0;
        !            60: 
        !            61:        if (settz++ > 0)
        !            62:                return;
        !            63:        if ((cp1 = getenv("TIMEZONE")) == ((char *)0))
        !            64:                return;
        !            65:        timezone = 0;
        !            66: 
        !            67:        /* Read primary timezone name and nul terminate */
        !            68:        cp2 = tzname[0];
        !            69:        while (*cp1 && *cp1 != ':' && cp2 < &tzname[0][31])
        !            70:                *cp2++ = *cp1++;
        !            71:        *cp2++ = 0;
        !            72:        while (*cp1 && *cp1++ != ':');
        !            73: 
        !            74:        /* Read timezone offset and convert to seconds */
        !            75:        timezone = (long)atoi(cp1) * 60L;
        !            76:        while (*cp1 && *cp1++ != ':');
        !            77: 
        !            78:        /* Read daylight timezone name and nul terminate */
        !            79:        cp2 = tzname[1];
        !            80:        while (*cp1 && *cp1 != ':' && cp2 < &tzname[1][31])
        !            81:                *cp2++ = *cp1++;
        !            82:        *cp2++ = 0;
        !            83:        while (*cp1 && *cp1++ != ':');
        !            84: 
        !            85:        /* Exit if no daylight time */
        !            86:        if (tzname[1][0] == 0)
        !            87:                return;
        !            88: 
        !            89:        /* Set default dst parameters */
        !            90:        setdst(tzdstdef);
        !            91: 
        !            92:        /* Set supplied dst parameters */
        !            93:        setdst(cp1);
        !            94: }
        !            95: 
        !            96: /* Parse and set dst parameters */
        !            97: static
        !            98: setdst(cp1) register char *cp1;
        !            99: {
        !           100:        /* Get optional start of daylight time */
        !           101:        if (*cp1) {
        !           102:                dsttimes[0].dst_occur = atoi(cp1);
        !           103:                while (*cp1 && *cp1++ != '.');
        !           104:                dsttimes[0].dst_day = atoi(cp1)-1;
        !           105:                while (*cp1 && *cp1++ != '.');
        !           106:                dsttimes[0].dst_month = atoi(cp1)-1;
        !           107:                while (*cp1 && *cp1++ != ':');
        !           108:        }
        !           109: 
        !           110:        /* Get optional end of daylight time */
        !           111:        if (*cp1) {
        !           112:                dsttimes[1].dst_occur = atoi(cp1);
        !           113:                while (*cp1 && *cp1++ != '.');
        !           114:                dsttimes[1].dst_day = atoi(cp1)-1;
        !           115:                while (*cp1 && *cp1++ != '.');
        !           116:                dsttimes[1].dst_month = atoi(cp1)-1;
        !           117:                while (*cp1 && *cp1++ != ':');
        !           118:        }
        !           119: 
        !           120:        /* Get optional hour of daylight time advance */
        !           121:        if (*cp1) {
        !           122:                dsthour = atoi(cp1);
        !           123:                while (*cp1 && *cp1++ != ':');
        !           124:        }
        !           125: 
        !           126:        /* Get optional minutes of adjustment */
        !           127:        if (*cp1)
        !           128:                dstadjust = atoi(cp1) * 60;
        !           129: }
        !           130: 
        !           131: /*
        !           132:  * Most common interface, returns a static string
        !           133:  * which is a printable version of the time and date.
        !           134:  */
        !           135: char *
        !           136: ctime(tp)
        !           137: long *tp;
        !           138: {
        !           139:        return (asctime(localtime(tp)));
        !           140: }
        !           141: 
        !           142: /*
        !           143:  * Do what gmtime does for the local timezone.
        !           144:  * And correct for daylight time.
        !           145:  */
        !           146: struct tm *
        !           147: localtime(tp)
        !           148: long *tp;
        !           149: {
        !           150:        long ltime;
        !           151: 
        !           152:        settz();
        !           153:        ltime = *tp - timezone;
        !           154:        gmtime(&ltime);
        !           155:        /*
        !           156:         * If necessary, adjust for daylight saving time.
        !           157:         */
        !           158:        if (isdaylight()) {
        !           159:                ltime = *tp - timezone + dstadjust;
        !           160:                gmtime(&ltime);
        !           161:                tm.tm_isdst = (dstadjust != 0);
        !           162:        } else
        !           163:                tm.tm_isdst = 0;
        !           164:        return (&tm);
        !           165: }
        !           166: 
        !           167: /*
        !           168:  * Returns a printable version of the time
        !           169:  * which has been broken down as in the tm structure.
        !           170:  */
        !           171: char *
        !           172: asctime(tmp)
        !           173: struct tm *tmp;
        !           174: {
        !           175:        register char *cp, *xp;
        !           176:        register unsigned i;
        !           177: 
        !           178:        cp = timestr;
        !           179:        /*
        !           180:         * Day of week
        !           181:         */
        !           182:        if ((i = tmp->tm_wday) >= NWDAY)
        !           183:                i = 0;
        !           184:        xp = &daynames[i*3];
        !           185:        *cp++ = *xp++;
        !           186:        *cp++ = *xp++;
        !           187:        *cp++ = *xp++;
        !           188:        *cp++ = ' ';
        !           189:        /*
        !           190:         * Month
        !           191:         */
        !           192:        if ((i = tmp->tm_mon) >= NMON)
        !           193:                i = 0;
        !           194:        xp = &months[i*3];
        !           195:        *cp++ = *xp++;
        !           196:        *cp++ = *xp++;
        !           197:        *cp++ = *xp++;
        !           198:        *cp++ = ' ';
        !           199:        /*
        !           200:         * Day of month
        !           201:         */
        !           202:        if ((i = tmp->tm_mday) >= 10)
        !           203:                *cp++ = todigit(i/10);
        !           204:        else
        !           205:                *cp++ = ' ';
        !           206:        *cp++ = todigit(i%10);
        !           207:        *cp++ = ' ';
        !           208:        /*
        !           209:         * Hours:mins:seconds
        !           210:         */
        !           211:        *cp++ = todigit((i = tmp->tm_hour)/10);
        !           212:        *cp++ = todigit(i%10);
        !           213:        *cp++ = ':';
        !           214:        *cp++ = todigit((i = tmp->tm_min)/10);
        !           215:        *cp++ = todigit(i%10);
        !           216:        *cp++ = ':';
        !           217:        *cp++ = todigit((i = tmp->tm_sec)/10);
        !           218:        *cp++ = todigit(i%10);
        !           219:        *cp++ = ' ';
        !           220:        /*
        !           221:         * Year
        !           222:         */
        !           223:        i = tmp->tm_year + 1900;
        !           224:        *cp++ = todigit(i/1000);
        !           225:        i = i%1000;
        !           226:        *cp++ = todigit(i/100);
        !           227:        i = i%100;
        !           228:        *cp++ = todigit(i/10);
        !           229:        *cp++ = todigit(i%10);
        !           230:        *cp++ = '\n';
        !           231:        *cp++ = '\0';
        !           232:        return (timestr);
        !           233: }
        !           234: 
        !           235: /*
        !           236:  * Do conversions for Greenwich Mean Time to
        !           237:  * the tm structure.
        !           238:  */
        !           239: struct tm *
        !           240: gmtime(tp)
        !           241: long *tp;
        !           242: {
        !           243:        long xtime;
        !           244:        unsigned days;
        !           245:        long secs;
        !           246:        int year;
        !           247:        int ydays;
        !           248:        int wday;
        !           249:        register char *mp;
        !           250: 
        !           251:        if ((xtime = *tp) < 0)
        !           252:                xtime = 0;
        !           253:        days = xtime/(60L*60L*24L);
        !           254:        secs = xtime%(60L*60L*24L);
        !           255:        tm.tm_hour = secs/(60L*60L);
        !           256:        secs = secs%(60L*60L);
        !           257:        tm.tm_min = secs/60;
        !           258:        tm.tm_sec = secs%60;
        !           259:        /*
        !           260:         * Start at Thursday (wday=4) Jan 1, 1970 (the Epoch)
        !           261:         * and calculate from there.
        !           262:         */
        !           263:        wday = (4+days)%NWDAY;
        !           264:        year = 1970;
        !           265:        for (;;) {
        !           266:                ydays = isleap(year) ? 366 : 365;
        !           267:                if (days < ydays)
        !           268:                        break;
        !           269:                year++;
        !           270:                days -= ydays;
        !           271:        }
        !           272:        tm.tm_year = year-1900;
        !           273:        tm.tm_yday = days;
        !           274:        tm.tm_wday = wday;
        !           275:        /*
        !           276:         * Setup february's #days now.
        !           277:         */
        !           278:        if (isleap(year))
        !           279:                dpm[FEB] = 29;
        !           280:        else
        !           281:                dpm[FEB] = 28;
        !           282:        for (mp = &dpm[0]; mp < &dpm[NMON] && days >= *mp; mp++)
        !           283:                days -= *mp;
        !           284:        tm.tm_mon = mp-dpm;
        !           285:        tm.tm_mday = days+1;
        !           286:        return (&tm);
        !           287: }
        !           288: 
        !           289: /*
        !           290:  * Return 1 on leap years; 0 otherwise.
        !           291:  */
        !           292: static
        !           293: isleap(yr)
        !           294: register yr;
        !           295: {
        !           296:        if (yr%4000 == 0)
        !           297:                return (0);
        !           298:        if (yr%400==0 || (yr%100!=0 && yr%4==0))
        !           299:                return (1);
        !           300:        return (0);
        !           301: }
        !           302: 
        !           303: /*
        !           304:  * Check for daylight savings time.
        !           305:  */
        !           306: static
        !           307: isdaylight()
        !           308: {
        !           309:        register int xday;
        !           310: 
        !           311:        if (tzname[1][0] == 0)          /* No name, no daylight time */
        !           312:                return (0);
        !           313:        if (tm.tm_mon < dsttimes[0].dst_month)
        !           314:                return (0);
        !           315:        else if (tm.tm_mon == dsttimes[0].dst_month) {
        !           316:                xday = nthday(&dsttimes[0]);
        !           317:                if (tm.tm_mday != xday)
        !           318:                        return (tm.tm_mday > xday);
        !           319:                return (tm.tm_hour >= dsthour);
        !           320:        } else if (tm.tm_mon < dsttimes[1].dst_month)
        !           321:                return (1);
        !           322:        else if (tm.tm_mon == dsttimes[1].dst_month) {
        !           323:                xday = nthday(&dsttimes[1]);
        !           324:                if (tm.tm_mday != xday)
        !           325:                        return (tm.tm_mday < xday);
        !           326:                return (tm.tm_hour < dsthour-1);
        !           327:        }
        !           328:        return (0);
        !           329: }
        !           330: 
        !           331: static
        !           332: nthday(dp)
        !           333: register struct dsttimes *dp;
        !           334: {
        !           335:        register int nthday;
        !           336:        register int nth;
        !           337: 
        !           338:        if ((nth = dp->dst_occur) == 0)
        !           339:                return dp->dst_day;
        !           340:        nthday = tm.tm_mday - tm.tm_wday + dp->dst_day;
        !           341:        if (nth > 0) {
        !           342:                while (nthday > 0)
        !           343:                        nthday -= 7;
        !           344:                do
        !           345:                        nthday += 7;
        !           346:                while (--nth > 0);
        !           347:        } else {
        !           348:                while (nthday < dpm[tm.tm_mon])
        !           349:                        nthday += 7;
        !           350:                do
        !           351:                        nthday -= 7;
        !           352:                while (++nth < 0);
        !           353:        }
        !           354:        return (nthday);
        !           355: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.