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

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

unix.superglobalmegacorp.com

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