Annotation of OpenXM_contrib/gnuplot/time.c, Revision 1.1
1.1 ! maekawa 1: #ifndef lint
! 2: static char *RCSid = "$Id: time.c,v 1.11 1998/04/14 00:16:27 drd Exp $";
! 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);
! 229: date++;
! 230: tm->tm_year += 1900;
! 231: break;
! 232:
! 233: case 'Y':
! 234: s = read_int(s, 4, &tm->tm_year);
! 235: date++;
! 236: /* tm->tm_year -= 1900; */
! 237: /* HOE tm->tm_year %= 100; */
! 238: break;
! 239:
! 240: case 'j':
! 241: s = read_int(s, 3, &tm->tm_yday);
! 242: tm->tm_yday--;
! 243: date++;
! 244: yday++;
! 245: break;
! 246:
! 247: case 'H':
! 248: s = read_int(s, 2, &tm->tm_hour);
! 249: break;
! 250:
! 251: case 'M':
! 252: s = read_int(s, 2, &tm->tm_min);
! 253: break;
! 254:
! 255: case 'S':
! 256: s = read_int(s, 2, &tm->tm_sec);
! 257: break;
! 258:
! 259: default:
! 260: int_warn("Bad time format in string", NO_CARET);
! 261: }
! 262: fmt++;
! 263: }
! 264:
! 265: FPRINTF((stderr, "read date-time : %d/%d/%d:%d:%d:%d\n", tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec));
! 266:
! 267: /* now check the date/time entered, normalising if necessary
! 268: * read_int cannot read a -ve number, but can read %m=0 then decrement
! 269: * it to -1
! 270: */
! 271:
! 272: #define S (tm->tm_sec)
! 273: #define M (tm->tm_min)
! 274: #define H (tm->tm_hour)
! 275:
! 276: if (S >= 60) {
! 277: M += S / 60;
! 278: S %= 60;
! 279: }
! 280: if (M >= 60) {
! 281: H += M / 60;
! 282: M %= 60;
! 283: }
! 284: if (H >= 24) {
! 285: if (yday)
! 286: tm->tm_yday += H / 24;
! 287: tm->tm_mday += H / 24;
! 288: H %= 24;
! 289: }
! 290: #undef S
! 291: #undef M
! 292: #undef H
! 293:
! 294: FPRINTF((stderr, "normalised time : %d/%d/%d:%d:%d:%d\n", tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec));
! 295:
! 296: if (date) {
! 297: if (yday) {
! 298:
! 299: if (tm->tm_yday < 0)
! 300: int_error("Illegal day of year", NO_CARET);
! 301:
! 302: /* we just set month to jan, day to yday, and let the
! 303: * normalising code do the work.
! 304: */
! 305:
! 306: tm->tm_mon = 0;
! 307: /* yday is 0->365, day is 1->31 */
! 308: tm->tm_mday = tm->tm_yday + 1;
! 309: }
! 310: if (tm->tm_mon < 0) {
! 311: int_error("illegal month", NO_CARET);
! 312: return (NULL);
! 313: }
! 314: if (tm->tm_mday < 1) {
! 315: int_error("illegal day of month", NO_CARET);
! 316: return (NULL);
! 317: }
! 318: if (tm->tm_mon > 11) {
! 319: tm->tm_year += tm->tm_mon / 12;
! 320: tm->tm_mon %= 12;
! 321: } {
! 322: int days_in_month;
! 323: while (tm->tm_mday > (days_in_month = (mndday[tm->tm_mon] + (tm->tm_mon == 1 && (gdysize(tm->tm_year) > 365))))) {
! 324: if (++tm->tm_mon == 12) {
! 325: ++tm->tm_year;
! 326: tm->tm_mon = 0;
! 327: }
! 328: tm->tm_mday -= days_in_month;
! 329: }
! 330: }
! 331: }
! 332: return (s);
! 333: }
! 334:
! 335: int gstrftime(s, bsz, fmt, l_clock)
! 336: char *s;
! 337: int bsz;
! 338: char *fmt;
! 339: double l_clock;
! 340: {
! 341: struct tm tm;
! 342:
! 343: ggmtime(&tm, l_clock);
! 344: #if 0
! 345: if ((tm.tm_zone = (char *) malloc(strlen(xtm->tm_zone) + 1)))
! 346: strcpy(tm.tm_zone, xtm->tm_zone);
! 347: /* printf("zone: %s - %s\n",tm.tm_zone,xtm->tm_zone); */
! 348: #endif
! 349:
! 350: return (xstrftime(s, bsz, fmt, &tm));
! 351: }
! 352:
! 353:
! 354: /* some shorthands : check that there is space in the output string
! 355: * Odd-looking defn is dangling-else-safe
! 356: */
! 357: #define CHECK_SPACE(n) if ( (l+(n)) <= bsz) ; else return 0
! 358:
! 359: /* copy a fixed string, checking that there's room */
! 360: #define COPY_STRING(z) CHECK_SPACE(strlen(z)) ; strcpy(s, z)
! 361:
! 362: /* format a string, using default spec if none given
! 363: * w and z are width and zero-flag
! 364: * dw and dz are the defaults for these
! 365: * In fact, CHECK_SPACE(w) is not a sufficient test, since
! 366: * sprintf("%2d", 365) outputs three characters
! 367: */
! 368:
! 369: #define FORMAT_STRING(dz, dw, x) \
! 370: if (w==0) { w=(dw); if (!z) z=(dz); } \
! 371: CHECK_SPACE(w); \
! 372: sprintf(s, z ? "%0*d" : "%*d", w, (x) )
! 373:
! 374: static int xstrftime(str, bsz, fmt, tm)
! 375: char *str; /* output buffer */
! 376: int bsz; /* space available */
! 377: char *fmt;
! 378: struct tm *tm;
! 379: {
! 380: int l = 0; /* chars written so far */
! 381:
! 382: char *s = str;
! 383:
! 384: memset(s, '\0', bsz);
! 385:
! 386: while (*fmt != '\0') {
! 387: if (*fmt != '%') {
! 388: if (l >= bsz)
! 389: return (0);
! 390: *s++ = *fmt++;
! 391: l++;
! 392: } else {
! 393:
! 394: /* set up format modifiers */
! 395: int w = 0;
! 396: int z = 0;
! 397: if (*++fmt == '0') {
! 398: z = 1;
! 399: ++fmt;
! 400: }
! 401: while (*fmt >= '0' && *fmt <= '9') {
! 402: w = w * 10 + (*fmt - '0');
! 403: ++fmt;
! 404: }
! 405:
! 406: switch (*fmt++) {
! 407: case '%':
! 408: CHECK_SPACE(1);
! 409: *s = '%';
! 410: break;
! 411:
! 412: case 'a':
! 413: COPY_STRING(abbrev_day_names[tm->tm_wday]);
! 414: break;
! 415:
! 416: case 'A':
! 417: COPY_STRING(full_day_names[tm->tm_wday]);
! 418: break;
! 419:
! 420: case 'b':
! 421: case 'h':
! 422: COPY_STRING(abbrev_month_names[tm->tm_mon]);
! 423: break;
! 424:
! 425: case 'B':
! 426: COPY_STRING(full_month_names[tm->tm_mon]);
! 427: break;
! 428:
! 429:
! 430: #if 0
! 431: /* %x not currently supported, so neither is c */
! 432: case 'c':
! 433: if (!xstrftime(s, bsz - l, "%x %X", tm))
! 434: return (0);
! 435: break;
! 436: #endif
! 437:
! 438: case 'd':
! 439: FORMAT_STRING(1, 2, tm->tm_mday); /* %02d */
! 440: break;
! 441:
! 442: case 'D':
! 443: if (!xstrftime(s, bsz - l, "%m/%d/%y", tm))
! 444: return (0);
! 445: break;
! 446:
! 447: case 'H':
! 448: FORMAT_STRING(1, 2, tm->tm_hour); /* %02d */
! 449: break;
! 450:
! 451: case 'I':
! 452: FORMAT_STRING(1, 2, tm->tm_hour % 12); /* %02d */
! 453: break;
! 454:
! 455: case 'j':
! 456: FORMAT_STRING(1, 3, tm->tm_yday + 1); /* %03d */
! 457: break;
! 458:
! 459: /* not in linux strftime man page. Not really needed now */
! 460: case 'k':
! 461: FORMAT_STRING(0, 2, tm->tm_hour); /* %2d */
! 462: break;
! 463:
! 464: case 'l':
! 465: FORMAT_STRING(0, 2, tm->tm_hour % 12); /* %2d */
! 466: break;
! 467:
! 468: case 'm':
! 469: FORMAT_STRING(1, 2, tm->tm_mon + 1); /* %02d */
! 470: break;
! 471:
! 472: case 'M':
! 473: FORMAT_STRING(1, 2, tm->tm_min); /* %02d */
! 474: break;
! 475:
! 476: case 'p':
! 477: CHECK_SPACE(2);
! 478: strcpy(s, (tm->tm_hour < 12) ? "am" : "pm");
! 479: break;
! 480:
! 481: case 'r':
! 482: if (!xstrftime(s, bsz - l, "%I:%M:%S %p", tm))
! 483: return (0);
! 484: break;
! 485:
! 486: case 'R':
! 487: if (!xstrftime(s, bsz - l, "%H:%M", tm))
! 488: return (0);
! 489: break;
! 490:
! 491: case 'S':
! 492: FORMAT_STRING(1, 2, tm->tm_sec); /* %02d */
! 493: break;
! 494:
! 495: case 'T':
! 496: if (!xstrftime(s, bsz - l, "%H:%M:%S", tm))
! 497: return (0);
! 498: break;
! 499:
! 500: case 'W': /* mon 1 day of week */
! 501: {
! 502: int week;
! 503: if (tm->tm_yday <= tm->tm_wday) {
! 504: week = 1;
! 505:
! 506: if ((tm->tm_mday - tm->tm_yday) > 4) {
! 507: week = 52;
! 508: }
! 509: if (tm->tm_yday == tm->tm_wday && tm->tm_wday == 0)
! 510: week = 52;
! 511:
! 512: } else {
! 513:
! 514: /* sun prev week */
! 515: int bw = tm->tm_yday - tm->tm_wday;
! 516:
! 517: if (tm->tm_wday > 0)
! 518: bw += 7; /* sun end of week */
! 519:
! 520: week = (int) bw / 7;
! 521:
! 522: if ((bw % 7) > 2) /* jan 1 is before friday */
! 523: week++;
! 524: }
! 525: FORMAT_STRING(1, 2, week); /* %02d */
! 526: break;
! 527: }
! 528:
! 529: case 'U': /* sun 1 day of week */
! 530: {
! 531: int week, bw;
! 532:
! 533: if (tm->tm_yday <= tm->tm_wday) {
! 534: week = 1;
! 535: if ((tm->tm_mday - tm->tm_yday) > 4) {
! 536: week = 52;
! 537: }
! 538: } else {
! 539: /* sat prev week */
! 540: bw = tm->tm_yday - tm->tm_wday - 1;
! 541: if (tm->tm_wday >= 0)
! 542: bw += 7; /* sat end of week */
! 543: week = (int) bw / 7;
! 544: if ((bw % 7) > 1) { /* jan 1 is before friday */
! 545: week++;
! 546: }
! 547: }
! 548: FORMAT_STRING(1, 2, week); /* %02d */
! 549: break;
! 550: }
! 551:
! 552: case 'w': /* day of week, sun=0 */
! 553: FORMAT_STRING(1, 2, tm->tm_wday); /* %02d */
! 554: break;
! 555:
! 556: case 'y':
! 557: FORMAT_STRING(1, 2, tm->tm_year % 100); /* %02d */
! 558: break;
! 559:
! 560: case 'Y':
! 561: FORMAT_STRING(1, 4, tm->tm_year); /* %04d */
! 562: break;
! 563:
! 564: #if 0
! 565: case 'Z':
! 566: COPY_STRING(tm->tm_zone);
! 567: break;
! 568: #endif
! 569: } /* switch */
! 570:
! 571: while (*s != '\0') {
! 572: s++;
! 573: l++;
! 574: }
! 575: }
! 576: }
! 577: return (l);
! 578: }
! 579:
! 580:
! 581:
! 582: /* time_t */
! 583: double gtimegm(tm)
! 584: struct tm *tm;
! 585: {
! 586: register int i;
! 587: /* returns sec from year ZERO_YEAR, defined in plot.h */
! 588: double dsec;
! 589:
! 590: dsec = 0;
! 591: if (tm->tm_year < ZERO_YEAR) {
! 592: for (i = tm->tm_year; i < ZERO_YEAR; i++) {
! 593: dsec -= (double) gdysize(i);
! 594: }
! 595: } else {
! 596: for (i = ZERO_YEAR; i < tm->tm_year; i++) {
! 597: dsec += (double) gdysize(i);
! 598: }
! 599: }
! 600: if (tm->tm_mday > 0) {
! 601: for (i = 0; i < tm->tm_mon; i++) {
! 602: dsec += (double) mndday[i] + (i == 1 && (gdysize(tm->tm_year) > 365));
! 603: }
! 604: dsec += (double) tm->tm_mday - 1;
! 605: } else {
! 606: dsec += (double) tm->tm_yday;
! 607: }
! 608: dsec *= (double) 24;
! 609:
! 610: dsec += tm->tm_hour;
! 611: dsec *= 60.0;
! 612: dsec += tm->tm_min;
! 613: dsec *= 60.0;
! 614: dsec += tm->tm_sec;
! 615:
! 616: FPRINTF((stderr, "broken-down time : %d/%d/%d:%d:%d:%d = %g seconds\n", tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec, dsec));
! 617:
! 618: return (dsec);
! 619: }
! 620:
! 621: int ggmtime(tm, l_clock)
! 622: struct tm *tm;
! 623: /* time_t l_clock; */
! 624: double l_clock;
! 625: {
! 626: /* l_clock is relative to ZERO_YEAR, jan 1, 00:00:00,defined in plot.h */
! 627: int i, days;
! 628:
! 629: /* dodgy way of doing wday - i hope it works ! */
! 630:
! 631: int wday = JAN_FIRST_WDAY; /* eg 6 for 2000 */
! 632:
! 633: FPRINTF((stderr, "%g seconds = ", l_clock));
! 634:
! 635: tm->tm_year = ZERO_YEAR;
! 636: tm->tm_mday = tm->tm_yday = tm->tm_mon = tm->tm_hour = tm->tm_min = tm->tm_sec = 0;
! 637: if (l_clock < 0) {
! 638: while (l_clock < 0) {
! 639: int days_in_year = gdysize(--tm->tm_year);
! 640: l_clock += days_in_year * DAY_SEC; /* 24*3600 */
! 641: /* adding 371 is noop in modulo 7 arithmetic, but keeps wday +ve */
! 642: wday += 371 - days_in_year;
! 643: }
! 644: } else {
! 645: for (;;) {
! 646: int days_in_year = gdysize(tm->tm_year);
! 647: if (l_clock < days_in_year * DAY_SEC)
! 648: break;
! 649: l_clock -= days_in_year * DAY_SEC;
! 650: tm->tm_year++;
! 651: /* only interested in result modulo 7, but %7 is expensive */
! 652: wday += (days_in_year - 364);
! 653: }
! 654: }
! 655: tm->tm_yday = (int) (l_clock / DAY_SEC);
! 656: l_clock -= tm->tm_yday * DAY_SEC;
! 657: tm->tm_hour = (int) l_clock / 3600;
! 658: l_clock -= tm->tm_hour * 3600;
! 659: tm->tm_min = (int) l_clock / 60;
! 660: l_clock -= tm->tm_min * 60;
! 661: tm->tm_sec = (int) l_clock;
! 662:
! 663: days = tm->tm_yday;
! 664:
! 665: /* wday%7 should be day of week of first day of year */
! 666: tm->tm_wday = (wday + days) % 7;
! 667:
! 668: while (days >= (i = mndday[tm->tm_mon] + (tm->tm_mon == 1 && (gdysize(tm->tm_year) > 365)))) {
! 669: days -= i;
! 670: tm->tm_mon++;
! 671: }
! 672: tm->tm_mday = days + 1;
! 673:
! 674: FPRINTF((stderr, "broken-down time : %d/%d/%d:%d:%d:%d\n", tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec));
! 675:
! 676: return (0);
! 677: }
! 678:
! 679:
! 680:
! 681:
! 682: #else /* USE_SYSTEM_TIME */
! 683:
! 684: /* define gnu time routines in terms of system time routines */
! 685:
! 686: int gstrftime(buf, bufsz, fmt, l_clock)
! 687: char *buf;
! 688: int bufsz;
! 689: char *fmt;
! 690: double l_clock;
! 691: {
! 692: time_t t = (time_t) l_clock;
! 693: return strftime(buf, bufsz, fmt, gmtime(&t));
! 694: }
! 695:
! 696: double gtimegm(tm)
! 697: struct tm *tm;
! 698: {
! 699: return (double) mktime(tm);
! 700: }
! 701:
! 702: int ggmtime(tm, l_clock)
! 703: struct tm *tm;
! 704: double l_clock;
! 705: {
! 706: time_t t = (time_t) l_clock;
! 707: struct tm *m = gmtime(&t);
! 708: *tm = *m; /* can any non-ansi compilers not do this ? */
! 709: }
! 710:
! 711: #define NOTHING
! 712: #define LETTER(L, width, field, extra) \
! 713: case L: s=read_int(s,width,&tm->field); extra; continue
! 714:
! 715: /* supplemental routine gstrptime() to read a formatted time */
! 716:
! 717: char *
! 718: gstrptime(s, fmt, tm)
! 719: char *s;
! 720: char *fmt;
! 721: struct tm *tm;
! 722: {
! 723: FPRINTF((stderr, "gstrptime(\"%s\", \"%s\")\n", s, fmt));
! 724:
! 725: /* linux does not appear to like years before 1902
! 726: * NT complains if its before 1970
! 727: * initialise fields to midnight, 1st Jan, 1970 (for relative times)
! 728: */
! 729: tm->tm_sec = tm->tm_min = tm->tm_hour = 0;
! 730: tm->tm_mday = 1;
! 731: tm->tm_mon = 0;
! 732: tm->tm_year = 70;
! 733: /* oops - it goes wrong without this */
! 734: tm->tm_isdst = 0;
! 735:
! 736: for (; *fmt && *s; ++fmt) {
! 737: if (*fmt != '%') {
! 738: if (*s != *fmt)
! 739: return s;
! 740: ++s;
! 741: continue;
! 742: }
! 743: assert(*fmt == '%');
! 744:
! 745: switch (*++fmt) {
! 746: case 0:
! 747: /* uh oh - % is last character in format */
! 748: return s;
! 749: case '%':
! 750: /* literal % */
! 751: if (*s++ != '%')
! 752: return s - 1;
! 753: continue;
! 754:
! 755: LETTER('d', 2, tm_mday, NOTHING);
! 756: LETTER('m', 2, tm_mon, NOTHING);
! 757: LETTER('y', 2, tm_year, NOTHING);
! 758: LETTER('Y', 4, tm_year, tm->tm_year -= 1900);
! 759: LETTER('H', 2, tm_hour, NOTHING);
! 760: LETTER('M', 2, tm_min, NOTHING);
! 761: LETTER('S', 2, tm_sec, NOTHING);
! 762:
! 763: default:
! 764: int_error("incorrect time format character", NO_CARET);
! 765: }
! 766: }
! 767:
! 768: 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));
! 769: /* mktime range-checks the time */
! 770:
! 771: if (mktime(tm) == -1) {
! 772: FPRINTF((stderr, "mktime() was not happy\n"));
! 773: int_error("Invalid date/time [mktime() did not like it]", NO_CARET);
! 774: }
! 775: 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));
! 776:
! 777: return s;
! 778: }
! 779:
! 780:
! 781: #endif /* USE_SYSTEM_TIME */
! 782:
! 783:
! 784: #ifdef TEST_TIME
! 785:
! 786: char *abbrev_month_names[] =
! 787: {"jan", "feb", "mar", "apr", "may", "jun", "jul",
! 788: "aug", "sep", "oct", "nov", "dec"};
! 789: char *full_month_names[] =
! 790: {"January", "February", "March", "April", "May",
! 791: "June", "July", "August", "September", "October", "November", "December"};
! 792:
! 793: char *abbrev_day_names[] =
! 794: {"sun", "mon", "tue", "wed", "thu", "fri", "sat"};
! 795: char *full_day_names[] =
! 796: {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
! 797:
! 798:
! 799:
! 800: /* either print current time using supplied format, or read
! 801: * supplied time using supplied format
! 802: */
! 803:
! 804:
! 805: int main(argc,argv)
! 806: int argc;
! 807: char *argv[];
! 808: {
! 809: char output[80];
! 810:
! 811: if (argc < 2) {
! 812: fputs("usage : test 'format' ['time']\n", stderr);
! 813: exit(EXIT_FAILURE);
! 814: }
! 815: if (argc == 2) {
! 816: struct timeb now;
! 817: struct tm *tm;
! 818: ftime(&now);
! 819: tm = gmtime(&now.time);
! 820: xstrftime(output, 80, argv[1], tm);
! 821: puts(output);
! 822: } else {
! 823: struct tm tm;
! 824: gstrptime(argv[2], argv[1], &tm);
! 825: puts(asctime(&tm));
! 826: }
! 827: exit(EXIT_SUCCESS);
! 828: }
! 829:
! 830: #endif /* TEST_TIME */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>