Annotation of coherent/b/lib/libc/gen/ctime.c, revision 1.1.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.