[BACK]Return to time.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gnuplot

Annotation of OpenXM_contrib/gnuplot/time.c, Revision 1.1.1.3

1.1       maekawa     1: #ifndef lint
1.1.1.3 ! ohara       2: static char *RCSid = "$Id: time.c,v 1.5.2.2 2002/01/31 21:28:05 lhecking Exp $";
1.1       maekawa     3: #endif
                      4:
                      5: /* GNUPLOT - time.c */
                      6:
                      7: /*[
                      8:  * Copyright 1986 - 1993, 1998   Thomas Williams, Colin Kelley
                      9:  *
                     10:  * Permission to use, copy, and distribute this software and its
                     11:  * documentation for any purpose with or without fee is hereby granted,
                     12:  * provided that the above copyright notice appear in all copies and
                     13:  * that both that copyright notice and this permission notice appear
                     14:  * in supporting documentation.
                     15:  *
                     16:  * Permission to modify the software is granted, but not the right to
                     17:  * distribute the complete modified source code.  Modifications are to
                     18:  * be distributed as patches to the released version.  Permission to
                     19:  * distribute binaries produced by compiling modified sources is granted,
                     20:  * provided you
                     21:  *   1. distribute the corresponding source modifications from the
                     22:  *    released version in the form of a patch file along with the binaries,
                     23:  *   2. add special version identification to distinguish your version
                     24:  *    in addition to the base release version number,
                     25:  *   3. provide your name and address as the primary contact for the
                     26:  *    support of your modified version, and
                     27:  *   4. retain our contact information in regard to use of the base
                     28:  *    software.
                     29:  * Permission to distribute the released version of the source code along
                     30:  * with corresponding source modifications in the form of a patch file is
                     31:  * granted with same provisions 2 through 4 for binary distributions.
                     32:  *
                     33:  * This software is provided "as is" without express or implied warranty
                     34:  * to the extent permitted by applicable law.
                     35: ]*/
                     36:
                     37:
                     38: /* some systems may not implement time very well ; in particular,
                     39:  * things might break as the year 2000 approaches.
                     40:  * This module either adds a routine gstrptime() to read a formatted time,
                     41:  * augmenting the standard suite of time routines provided by ansi,
                     42:  * or it completely replaces the whole lot with a new set of routines,
                     43:  * which count time relative to the year 2000. Default is to use the
                     44:  * new routines. define USE_SYSTEM_TIME to use the system routines, at your
                     45:  * own risk. One problem in particular is that not all systems allow
                     46:  * the time with integer value 0 to be represented symbolically, which
                     47:  * prevents use of relative times.
                     48:  */
                     49:
                     50:
                     51: #include "plot.h"
                     52:
                     53: /* build as a standalone test */
                     54:
                     55: #ifdef TEST_TIME
                     56:
                     57: # ifdef HAVE_SYS_TIMEB_H
                     58: #  include <sys/timeb.h>
                     59: #else
                     60: /* declare struct timeb */
                     61: extern int ftime(struct timeb *);
                     62: #endif
                     63:
                     64: # define int_error(x,y) fprintf(stderr, "Error: " x "\n")
                     65: # define int_warn(x,y) fprintf(stderr, "Warn: " x "\n")
                     66:
                     67: /* need (only) these from plot.h */
                     68: # define ZERO_YEAR     2000
                     69: /* 1st jan, 2000 is a Saturday (cal 1 2000 on unix) */
                     70: # define JAN_FIRST_WDAY 6
                     71:
                     72: /*  zero gnuplot (2000) - zero system (1970) */
                     73: # define SEC_OFFS_SYS  946684800.0
                     74:
                     75: /* avg, incl. leap year */
                     76: # define YEAR_SEC      31557600.0
                     77:
                     78: /* YEAR_SEC / 12 */
                     79: # define MON_SEC               2629800.0
                     80:
                     81: # define WEEK_SEC      604800.0
                     82: # define DAY_SEC               86400.0
                     83:
                     84: /*forward decls */
                     85: extern char *abbrev_month_names[];
                     86: extern char *full_month_names[];
                     87: extern char *abbrev_day_names[];
                     88: extern char *full_day_names[];
                     89:
                     90: #else /* TEST_TIME */
                     91:
                     92: # include "setshow.h"          /* for month names etc */
                     93:
                     94: #endif /* TEST_TIME */
                     95:
                     96: static char *read_int __PROTO((char *s, int nr, int *d));
                     97: static int gdysize __PROTO((int yr));
                     98:
                     99:
                    100: static char *
                    101:  read_int(s, nr, d)
                    102: char *s;
                    103: int nr, *d;
                    104: {
                    105:     int result = 0;
                    106:
                    107:     while (--nr >= 0 && *s >= '0' && *s <= '9')
                    108:        result = result * 10 + (*s++ - '0');
                    109:
                    110:     *d = result;
                    111:     return (s);
                    112: }
                    113:
                    114:
                    115:
                    116: #ifndef USE_SYSTEM_TIME
                    117:
                    118: /* a new set of routines to completely replace the ansi ones
                    119:  * Use at your own risk
                    120:  */
                    121:
                    122:
                    123: static int mndday[12] =
                    124: {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
                    125:
                    126: static int xstrftime __PROTO((char *buf, int bufsz, char *fmt, struct tm * tm));
                    127:
                    128: /* days in year */
                    129: static int gdysize(yr)
                    130: int yr;
                    131: {
                    132:
                    133:     if (!(yr % 4)) {
                    134:        if ((!(yr % 100)) && yr % 400)
                    135:            return (365);
                    136:        return (366);
                    137:     }
                    138:     return (365);
                    139: }
                    140:
                    141:
                    142: /* new strptime() and gmtime() to allow time to be read as 24 hour,
                    143:  * and spaces in the format string. time is converted to seconds from
                    144:  * year 2000.... */
                    145:
                    146: char *
                    147:  gstrptime(s, fmt, tm)
                    148: char *s;
                    149: char *fmt;
                    150: struct tm *tm;
                    151: {
                    152:     int yday, date;
                    153:
                    154:     date = yday = 0;
                    155:     tm->tm_mday = 1;
                    156:     tm->tm_mon = tm->tm_hour = tm->tm_min = tm->tm_sec = 0;
                    157:     /* make relative times work (user-defined tic step) */
                    158:     tm->tm_year = ZERO_YEAR;
                    159:
                    160:     /* we do not yet calculate wday or yday, so make them illegal
                    161:      * [but yday will be read by %j]
                    162:      */
                    163:
                    164:     tm->tm_yday = tm->tm_wday = -1;
                    165:
                    166:     while (*fmt) {
                    167:        if (*fmt != '%') {
                    168:            if (*fmt == ' ') {
                    169:                /* space in format means zero or more spaces in input */
                    170:                while (*s == ' ')
                    171:                    ++s;
                    172:                ++fmt;
                    173:                continue;
                    174:            } else if (*fmt == *s) {
                    175:                ++s;
                    176:                ++fmt;
                    177:                continue;
                    178:            } else
                    179:                break;          /* literal match has failed */
                    180:        }
                    181:        /* we are processing a percent escape */
                    182:
                    183:        switch (*++fmt) {
                    184:        case 'b':               /* abbreviated month name */
                    185:            {
                    186:                int m;
                    187:                for (m = 0; m < 12; ++m)
                    188:                    if (strnicmp(s, abbrev_month_names[m], strlen(abbrev_month_names[m])) == 0) {
                    189:                        s += strlen(abbrev_month_names[m]);
                    190:                        goto found_abbrev_mon;
                    191:                    }
                    192:                /* get here => not found */
                    193:                int_warn("Bad abbreviated month name", NO_CARET);
                    194:                m = 0;
                    195:              found_abbrev_mon:
                    196:                tm->tm_mon = m;
                    197:                break;
                    198:            }
                    199:
                    200:        case 'B':               /* full month name */
                    201:            {
                    202:                int m;
                    203:                for (m = 0; m < 12; ++m)
                    204:                    if (strnicmp(s, full_month_names[m], strlen(full_month_names[m])) == 0) {
                    205:                        s += strlen(full_month_names[m]);
                    206:                        goto found_full_mon;
                    207:                    }
                    208:                /* get here => not found */
                    209:                int_warn("Bad full month name", NO_CARET);
                    210:                m = 0;
                    211:              found_full_mon:
                    212:                tm->tm_mon = m;
                    213:                break;
                    214:            }
                    215:
                    216:        case 'd':               /* read a day of month */
                    217:            s = read_int(s, 2, &tm->tm_mday);
                    218:            date++;
                    219:            break;
                    220:
                    221:        case 'm':               /* month number */
                    222:            s = read_int(s, 2, &tm->tm_mon);
                    223:            date++;
                    224:            --tm->tm_mon;
                    225:            break;
                    226:
                    227:        case 'y':               /* year number */
                    228:            s = read_int(s, 2, &tm->tm_year);
1.1.1.2   maekawa   229:            /* In line with the current UNIX98 specification by
                    230:             * The Open Group and major Unix vendors,
                    231:             * two-digit years 69-99 refer to the 20th century, and
                    232:             * values in the range 00-68 refer to the 21st century.
                    233:             */
                    234:            if (tm->tm_year <= 68)
                    235:                tm->tm_year += 100;
1.1       maekawa   236:            date++;
                    237:            tm->tm_year += 1900;
                    238:            break;
                    239:
                    240:        case 'Y':
                    241:            s = read_int(s, 4, &tm->tm_year);
                    242:            date++;
                    243:            break;
                    244:
                    245:        case 'j':
                    246:            s = read_int(s, 3, &tm->tm_yday);
                    247:            tm->tm_yday--;
                    248:            date++;
                    249:            yday++;
                    250:            break;
                    251:
                    252:        case 'H':
                    253:            s = read_int(s, 2, &tm->tm_hour);
                    254:            break;
                    255:
                    256:        case 'M':
                    257:            s = read_int(s, 2, &tm->tm_min);
                    258:            break;
                    259:
                    260:        case 'S':
                    261:            s = read_int(s, 2, &tm->tm_sec);
                    262:            break;
                    263:
1.1.1.3 ! ohara     264:        /* read EPOCH data
        !           265:         * EPOCH is the std. unixtimeformat seconds since 01.01.1970 UTC
        !           266:         * actualy i would need a read_long (or what time_t is else)
        !           267:         *  aktualy this is not my idea       i got if from
        !           268:         * AlunDa Penguin Jones (21.11.97)
        !           269:         * but changed %t to %s because of strftime
        !           270:         * and fixed the localtime() into gmtime()
        !           271:         * maybe we should use ggmtime() ? but who choose double ????
        !           272:         * Walter Harms <WHarms@bfs.de> 26 Mar 2000
        !           273:         */
        !           274:
        !           275:        case 's':
        !           276:            {
        !           277:                /* time_t when; */
        !           278:                int when;
        !           279:                struct tm *tmwhen;
        !           280:                s = read_int(s, 10, &when);
        !           281:                tmwhen = gmtime((time_t*)&when);
        !           282:                tmwhen->tm_year += 1900;
        !           283:                *tm = *tmwhen;
        !           284:                break;
        !           285:            }
        !           286:
1.1       maekawa   287:        default:
                    288:            int_warn("Bad time format in string", NO_CARET);
                    289:        }
                    290:        fmt++;
                    291:     }
                    292:
1.1.1.3 ! ohara     293:     FPRINTF((stderr, "read date-time : %02d/%02d/%d:%02d:%02d:%02d\n", tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec));
1.1       maekawa   294:
                    295:     /* now check the date/time entered, normalising if necessary
                    296:      * read_int cannot read a -ve number, but can read %m=0 then decrement
                    297:      * it to -1
                    298:      */
                    299:
                    300: #define S (tm->tm_sec)
                    301: #define M (tm->tm_min)
                    302: #define H (tm->tm_hour)
                    303:
                    304:     if (S >= 60) {
                    305:        M += S / 60;
                    306:        S %= 60;
                    307:     }
                    308:     if (M >= 60) {
                    309:        H += M / 60;
                    310:        M %= 60;
                    311:     }
                    312:     if (H >= 24) {
                    313:        if (yday)
                    314:            tm->tm_yday += H / 24;
                    315:        tm->tm_mday += H / 24;
                    316:        H %= 24;
                    317:     }
                    318: #undef S
                    319: #undef M
                    320: #undef H
                    321:
1.1.1.3 ! ohara     322:     FPRINTF((stderr, "normalised time : %02d/%02d/%d:%02d:%02d:%02d\n", tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec));
1.1       maekawa   323:
                    324:     if (date) {
                    325:        if (yday) {
                    326:
                    327:            if (tm->tm_yday < 0)
                    328:                int_error("Illegal day of year", NO_CARET);
                    329:
                    330:            /* we just set month to jan, day to yday, and let the
                    331:             * normalising code do the work.
                    332:             */
                    333:
                    334:            tm->tm_mon = 0;
                    335:            /* yday is 0->365, day is 1->31 */
                    336:            tm->tm_mday = tm->tm_yday + 1;
                    337:        }
                    338:        if (tm->tm_mon < 0) {
                    339:            int_error("illegal month", NO_CARET);
                    340:            return (NULL);
                    341:        }
                    342:        if (tm->tm_mday < 1) {
                    343:            int_error("illegal day of month", NO_CARET);
                    344:            return (NULL);
                    345:        }
                    346:        if (tm->tm_mon > 11) {
                    347:            tm->tm_year += tm->tm_mon / 12;
                    348:            tm->tm_mon %= 12;
                    349:        } {
                    350:            int days_in_month;
                    351:            while (tm->tm_mday > (days_in_month = (mndday[tm->tm_mon] + (tm->tm_mon == 1 && (gdysize(tm->tm_year) > 365))))) {
                    352:                if (++tm->tm_mon == 12) {
                    353:                    ++tm->tm_year;
                    354:                    tm->tm_mon = 0;
                    355:                }
                    356:                tm->tm_mday -= days_in_month;
                    357:            }
                    358:        }
                    359:     }
                    360:     return (s);
                    361: }
                    362:
                    363: int gstrftime(s, bsz, fmt, l_clock)
                    364: char *s;
                    365: int bsz;
                    366: char *fmt;
                    367: double l_clock;
                    368: {
                    369:     struct tm tm;
                    370:
                    371:     ggmtime(&tm, l_clock);
                    372: #if 0
                    373:     if ((tm.tm_zone = (char *) malloc(strlen(xtm->tm_zone) + 1)))
                    374:        strcpy(tm.tm_zone, xtm->tm_zone);
                    375:     /* printf("zone: %s - %s\n",tm.tm_zone,xtm->tm_zone); */
                    376: #endif
                    377:
                    378:     return (xstrftime(s, bsz, fmt, &tm));
                    379: }
                    380:
                    381:
                    382: /* some shorthands : check that there is space in the output string
                    383:  * Odd-looking defn is dangling-else-safe
                    384:  */
                    385: #define CHECK_SPACE(n) if ( (l+(n)) <= bsz) ; else return 0
                    386:
                    387: /* copy a fixed string, checking that there's room */
                    388: #define COPY_STRING(z) CHECK_SPACE(strlen(z)) ; strcpy(s, z)
                    389:
                    390: /* format a string, using default spec if none given
                    391:  * w and z are width and zero-flag
                    392:  * dw and dz are the defaults for these
                    393:  * In fact, CHECK_SPACE(w) is not a sufficient test, since
                    394:  * sprintf("%2d", 365) outputs three characters
                    395:  */
                    396:
                    397: #define FORMAT_STRING(dz, dw, x)           \
                    398:   if (w==0) { w=(dw); if (!z) z=(dz); }    \
                    399:   CHECK_SPACE(w);                          \
                    400:   sprintf(s, z ? "%0*d" : "%*d", w, (x) )
                    401:
                    402: static int xstrftime(str, bsz, fmt, tm)
                    403: char *str;                     /* output buffer */
                    404: int bsz;                       /* space available */
                    405: char *fmt;
                    406: struct tm *tm;
                    407: {
                    408:     int l = 0;                 /* chars written so far */
                    409:
                    410:     char *s = str;
                    411:
                    412:     memset(s, '\0', bsz);
                    413:
                    414:     while (*fmt != '\0') {
                    415:        if (*fmt != '%') {
                    416:            if (l >= bsz)
                    417:                return (0);
                    418:            *s++ = *fmt++;
                    419:            l++;
                    420:        } else {
                    421:
                    422:            /* set up format modifiers */
                    423:            int w = 0;
                    424:            int z = 0;
                    425:            if (*++fmt == '0') {
                    426:                z = 1;
                    427:                ++fmt;
                    428:            }
                    429:            while (*fmt >= '0' && *fmt <= '9') {
                    430:                w = w * 10 + (*fmt - '0');
                    431:                ++fmt;
                    432:            }
                    433:
                    434:            switch (*fmt++) {
                    435:            case '%':
                    436:                CHECK_SPACE(1);
                    437:                *s = '%';
                    438:                break;
                    439:
                    440:            case 'a':
                    441:                COPY_STRING(abbrev_day_names[tm->tm_wday]);
                    442:                break;
                    443:
                    444:            case 'A':
                    445:                COPY_STRING(full_day_names[tm->tm_wday]);
                    446:                break;
                    447:
                    448:            case 'b':
                    449:            case 'h':
                    450:                COPY_STRING(abbrev_month_names[tm->tm_mon]);
                    451:                break;
                    452:
                    453:            case 'B':
                    454:                COPY_STRING(full_month_names[tm->tm_mon]);
                    455:                break;
                    456:
                    457:
                    458: #if 0
                    459:            /* %x not currently supported, so neither is c */
                    460:            case 'c':
                    461:                if (!xstrftime(s, bsz - l, "%x %X", tm))
                    462:                    return (0);
                    463:                break;
                    464: #endif
                    465:
                    466:            case 'd':
                    467:                FORMAT_STRING(1, 2, tm->tm_mday);       /* %02d */
                    468:                break;
                    469:
                    470:            case 'D':
                    471:                if (!xstrftime(s, bsz - l, "%m/%d/%y", tm))
                    472:                    return (0);
                    473:                break;
                    474:
                    475:            case 'H':
                    476:                FORMAT_STRING(1, 2, tm->tm_hour);       /* %02d */
                    477:                break;
                    478:
                    479:            case 'I':
                    480:                FORMAT_STRING(1, 2, tm->tm_hour % 12);  /* %02d */
                    481:                break;
                    482:
                    483:            case 'j':
                    484:                FORMAT_STRING(1, 3, tm->tm_yday + 1);   /* %03d */
                    485:                break;
                    486:
                    487:                /* not in linux strftime man page. Not really needed now */
                    488:            case 'k':
                    489:                FORMAT_STRING(0, 2, tm->tm_hour);       /* %2d */
                    490:                break;
                    491:
                    492:            case 'l':
                    493:                FORMAT_STRING(0, 2, tm->tm_hour % 12);  /* %2d */
                    494:                break;
                    495:
                    496:            case 'm':
                    497:                FORMAT_STRING(1, 2, tm->tm_mon + 1);    /* %02d */
                    498:                break;
                    499:
                    500:            case 'M':
                    501:                FORMAT_STRING(1, 2, tm->tm_min);        /* %02d */
                    502:                break;
                    503:
                    504:            case 'p':
                    505:                CHECK_SPACE(2);
                    506:                strcpy(s, (tm->tm_hour < 12) ? "am" : "pm");
                    507:                break;
                    508:
                    509:            case 'r':
                    510:                if (!xstrftime(s, bsz - l, "%I:%M:%S %p", tm))
                    511:                    return (0);
                    512:                break;
                    513:
                    514:            case 'R':
                    515:                if (!xstrftime(s, bsz - l, "%H:%M", tm))
                    516:                    return (0);
                    517:                break;
                    518:
                    519:            case 'S':
                    520:                FORMAT_STRING(1, 2, tm->tm_sec);        /* %02d */
                    521:                break;
                    522:
                    523:            case 'T':
                    524:                if (!xstrftime(s, bsz - l, "%H:%M:%S", tm))
                    525:                    return (0);
                    526:                break;
                    527:
                    528:            case 'W':           /* mon 1 day of week */
                    529:                {
                    530:                    int week;
                    531:                    if (tm->tm_yday <= tm->tm_wday) {
                    532:                        week = 1;
                    533:
                    534:                        if ((tm->tm_mday - tm->tm_yday) > 4) {
                    535:                            week = 52;
                    536:                        }
                    537:                        if (tm->tm_yday == tm->tm_wday && tm->tm_wday == 0)
                    538:                            week = 52;
                    539:
                    540:                    } else {
                    541:
                    542:                        /* sun prev week */
                    543:                        int bw = tm->tm_yday - tm->tm_wday;
                    544:
                    545:                        if (tm->tm_wday > 0)
                    546:                            bw += 7;    /* sun end of week */
                    547:
                    548:                        week = (int) bw / 7;
                    549:
                    550:                        if ((bw % 7) > 2)       /* jan 1 is before friday */
                    551:                            week++;
                    552:                    }
                    553:                    FORMAT_STRING(1, 2, week);  /* %02d */
                    554:                    break;
                    555:                }
                    556:
                    557:            case 'U':           /* sun 1 day of week */
                    558:                {
                    559:                    int week, bw;
                    560:
                    561:                    if (tm->tm_yday <= tm->tm_wday) {
                    562:                        week = 1;
                    563:                        if ((tm->tm_mday - tm->tm_yday) > 4) {
                    564:                            week = 52;
                    565:                        }
                    566:                    } else {
                    567:                        /* sat prev week */
                    568:                        bw = tm->tm_yday - tm->tm_wday - 1;
                    569:                        if (tm->tm_wday >= 0)
                    570:                            bw += 7;    /* sat end of week */
                    571:                        week = (int) bw / 7;
                    572:                        if ((bw % 7) > 1) {     /* jan 1 is before friday */
                    573:                            week++;
                    574:                        }
                    575:                    }
                    576:                    FORMAT_STRING(1, 2, week);  /* %02d */
                    577:                    break;
                    578:                }
                    579:
                    580:            case 'w':           /* day of week, sun=0 */
                    581:                FORMAT_STRING(1, 2, tm->tm_wday);       /* %02d */
                    582:                break;
                    583:
                    584:            case 'y':
                    585:                FORMAT_STRING(1, 2, tm->tm_year % 100);         /* %02d */
                    586:                break;
                    587:
                    588:            case 'Y':
                    589:                FORMAT_STRING(1, 4, tm->tm_year);       /* %04d */
                    590:                break;
                    591:
                    592: #if 0
                    593:            case 'Z':
                    594:                COPY_STRING(tm->tm_zone);
                    595:                break;
                    596: #endif
                    597:            }                   /* switch */
                    598:
                    599:            while (*s != '\0') {
                    600:                s++;
                    601:                l++;
                    602:            }
                    603:        }
                    604:     }
                    605:     return (l);
                    606: }
                    607:
                    608:
                    609:
                    610: /* time_t  */
                    611: double gtimegm(tm)
                    612: struct tm *tm;
                    613: {
                    614:     register int i;
                    615:     /* returns sec from year ZERO_YEAR, defined in plot.h */
                    616:     double dsec;
                    617:
                    618:     dsec = 0;
                    619:     if (tm->tm_year < ZERO_YEAR) {
                    620:        for (i = tm->tm_year; i < ZERO_YEAR; i++) {
                    621:            dsec -= (double) gdysize(i);
                    622:        }
                    623:     } else {
                    624:        for (i = ZERO_YEAR; i < tm->tm_year; i++) {
                    625:            dsec += (double) gdysize(i);
                    626:        }
                    627:     }
                    628:     if (tm->tm_mday > 0) {
                    629:        for (i = 0; i < tm->tm_mon; i++) {
                    630:            dsec += (double) mndday[i] + (i == 1 && (gdysize(tm->tm_year) > 365));
                    631:        }
                    632:        dsec += (double) tm->tm_mday - 1;
                    633:     } else {
                    634:        dsec += (double) tm->tm_yday;
                    635:     }
                    636:     dsec *= (double) 24;
                    637:
                    638:     dsec += tm->tm_hour;
                    639:     dsec *= 60.0;
                    640:     dsec += tm->tm_min;
                    641:     dsec *= 60.0;
                    642:     dsec += tm->tm_sec;
                    643:
1.1.1.3 ! ohara     644:     FPRINTF((stderr, "broken-down time : %02d/%02d/%d:%02d:%02d:%02d = %g seconds\n", tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec, dsec));
1.1       maekawa   645:
                    646:     return (dsec);
                    647: }
                    648:
                    649: int ggmtime(tm, l_clock)
                    650: struct tm *tm;
                    651: /* time_t l_clock; */
                    652: double l_clock;
                    653: {
                    654:     /* l_clock is relative to ZERO_YEAR, jan 1, 00:00:00,defined in plot.h */
                    655:     int i, days;
                    656:
                    657:     /* dodgy way of doing wday - i hope it works ! */
                    658:
                    659:     int wday = JAN_FIRST_WDAY; /* eg 6 for 2000 */
                    660:
                    661:     FPRINTF((stderr, "%g seconds = ", l_clock));
                    662:
                    663:     tm->tm_year = ZERO_YEAR;
                    664:     tm->tm_mday = tm->tm_yday = tm->tm_mon = tm->tm_hour = tm->tm_min = tm->tm_sec = 0;
                    665:     if (l_clock < 0) {
                    666:        while (l_clock < 0) {
                    667:            int days_in_year = gdysize(--tm->tm_year);
                    668:            l_clock += days_in_year * DAY_SEC;  /* 24*3600 */
                    669:            /* adding 371 is noop in modulo 7 arithmetic, but keeps wday +ve */
                    670:            wday += 371 - days_in_year;
                    671:        }
                    672:     } else {
                    673:        for (;;) {
                    674:            int days_in_year = gdysize(tm->tm_year);
                    675:            if (l_clock < days_in_year * DAY_SEC)
                    676:                break;
                    677:            l_clock -= days_in_year * DAY_SEC;
                    678:            tm->tm_year++;
                    679:            /* only interested in result modulo 7, but %7 is expensive */
                    680:            wday += (days_in_year - 364);
                    681:        }
                    682:     }
                    683:     tm->tm_yday = (int) (l_clock / DAY_SEC);
                    684:     l_clock -= tm->tm_yday * DAY_SEC;
                    685:     tm->tm_hour = (int) l_clock / 3600;
                    686:     l_clock -= tm->tm_hour * 3600;
                    687:     tm->tm_min = (int) l_clock / 60;
                    688:     l_clock -= tm->tm_min * 60;
                    689:     tm->tm_sec = (int) l_clock;
                    690:
                    691:     days = tm->tm_yday;
                    692:
                    693:     /* wday%7 should be day of week of first day of year */
                    694:     tm->tm_wday = (wday + days) % 7;
                    695:
                    696:     while (days >= (i = mndday[tm->tm_mon] + (tm->tm_mon == 1 && (gdysize(tm->tm_year) > 365)))) {
                    697:        days -= i;
                    698:        tm->tm_mon++;
                    699:     }
                    700:     tm->tm_mday = days + 1;
                    701:
1.1.1.3 ! ohara     702:     FPRINTF((stderr, "broken-down time : %02d/%02d/%d:%02d:%02d:%02d\n", tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec));
1.1       maekawa   703:
                    704:     return (0);
                    705: }
                    706:
                    707:
                    708:
                    709:
                    710: #else /* USE_SYSTEM_TIME */
                    711:
                    712: /* define gnu time routines in terms of system time routines */
                    713:
                    714: int gstrftime(buf, bufsz, fmt, l_clock)
                    715: char *buf;
                    716: int bufsz;
                    717: char *fmt;
                    718: double l_clock;
                    719: {
                    720:     time_t t = (time_t) l_clock;
                    721:     return strftime(buf, bufsz, fmt, gmtime(&t));
                    722: }
                    723:
                    724: double gtimegm(tm)
                    725: struct tm *tm;
                    726: {
                    727:     return (double) mktime(tm);
                    728: }
                    729:
                    730: int ggmtime(tm, l_clock)
                    731: struct tm *tm;
                    732: double l_clock;
                    733: {
                    734:     time_t t = (time_t) l_clock;
                    735:     struct tm *m = gmtime(&t);
                    736:     *tm = *m;                  /* can any non-ansi compilers not do this ? */
                    737: }
                    738:
                    739: #define NOTHING
                    740: #define LETTER(L, width, field, extra) \
                    741:   case L: s=read_int(s,width,&tm->field); extra; continue
                    742:
                    743: /* supplemental routine gstrptime() to read a formatted time */
                    744:
                    745: char *
                    746:  gstrptime(s, fmt, tm)
                    747: char *s;
                    748: char *fmt;
                    749: struct tm *tm;
                    750: {
                    751:     FPRINTF((stderr, "gstrptime(\"%s\", \"%s\")\n", s, fmt));
                    752:
                    753:     /* linux does not appear to like years before 1902
                    754:      * NT complains if its before 1970
                    755:      * initialise fields to midnight, 1st Jan, 1970 (for relative times)
                    756:      */
                    757:     tm->tm_sec = tm->tm_min = tm->tm_hour = 0;
                    758:     tm->tm_mday = 1;
                    759:     tm->tm_mon = 0;
                    760:     tm->tm_year = 70;
                    761:     /* oops - it goes wrong without this */
                    762:     tm->tm_isdst = 0;
                    763:
                    764:     for (; *fmt && *s; ++fmt) {
                    765:        if (*fmt != '%') {
                    766:            if (*s != *fmt)
                    767:                return s;
                    768:            ++s;
                    769:            continue;
                    770:        }
                    771:        assert(*fmt == '%');
                    772:
                    773:        switch (*++fmt) {
                    774:        case 0:
                    775:            /* uh oh - % is last character in format */
                    776:            return s;
                    777:        case '%':
                    778:            /* literal % */
                    779:            if (*s++ != '%')
                    780:                return s - 1;
                    781:            continue;
                    782:
                    783:            LETTER('d', 2, tm_mday, NOTHING);
                    784:            LETTER('m', 2, tm_mon, NOTHING);
                    785:            LETTER('y', 2, tm_year, NOTHING);
                    786:            LETTER('Y', 4, tm_year, tm->tm_year -= 1900);
                    787:            LETTER('H', 2, tm_hour, NOTHING);
                    788:            LETTER('M', 2, tm_min, NOTHING);
                    789:            LETTER('S', 2, tm_sec, NOTHING);
                    790:
                    791:        default:
                    792:            int_error("incorrect time format character", NO_CARET);
                    793:        }
                    794:     }
                    795:
                    796:     FPRINTF((stderr, "Before mktime : %d/%d/%d:%d:%d:%d\n", tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec));
                    797:     /* mktime range-checks the time */
                    798:
                    799:     if (mktime(tm) == -1) {
                    800:        FPRINTF((stderr, "mktime() was not happy\n"));
                    801:        int_error("Invalid date/time [mktime() did not like it]", NO_CARET);
                    802:     }
                    803:     FPRINTF((stderr, "After mktime : %d/%d/%d:%d:%d:%d\n", tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec));
                    804:
                    805:     return s;
                    806: }
                    807:
                    808:
                    809: #endif /* USE_SYSTEM_TIME */
                    810:
                    811:
                    812: #ifdef TEST_TIME
                    813:
                    814: char *abbrev_month_names[] =
                    815: {"jan", "feb", "mar", "apr", "may", "jun", "jul",
                    816:  "aug", "sep", "oct", "nov", "dec"};
                    817: char *full_month_names[] =
                    818: {"January", "February", "March", "April", "May",
                    819: "June", "July", "August", "September", "October", "November", "December"};
                    820:
                    821: char *abbrev_day_names[] =
                    822: {"sun", "mon", "tue", "wed", "thu", "fri", "sat"};
                    823: char *full_day_names[] =
                    824: {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
                    825:
                    826:
                    827:
                    828: /* either print current time using supplied format, or read
                    829:  * supplied time using supplied format
                    830:  */
                    831:
                    832:
                    833: int main(argc,argv)
                    834: int argc;
                    835: char *argv[];
                    836: {
                    837:     char output[80];
                    838:
                    839:     if (argc < 2) {
                    840:        fputs("usage : test 'format' ['time']\n", stderr);
                    841:        exit(EXIT_FAILURE);
                    842:     }
                    843:     if (argc == 2) {
                    844:        struct timeb now;
                    845:        struct tm *tm;
                    846:        ftime(&now);
                    847:        tm = gmtime(&now.time);
                    848:        xstrftime(output, 80, argv[1], tm);
                    849:        puts(output);
                    850:     } else {
                    851:        struct tm tm;
                    852:        gstrptime(argv[2], argv[1], &tm);
                    853:        puts(asctime(&tm));
                    854:     }
                    855:     exit(EXIT_SUCCESS);
                    856: }
                    857:
                    858: #endif /* TEST_TIME */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>