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