home *** CD-ROM | disk | FTP | other *** search
/ Unix System Administration Handbook 1997 October / usah_oct97.iso / news / cnews.tar / libc / getabsdate.c < prev    next >
C/C++ Source or Header  |  1991-12-10  |  3KB  |  155 lines

  1. /*
  2.  * getabsdate - parse almost any absolute date getdate(3) can (& some it can't)
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include <ctype.h>
  7. #include <string.h>
  8. #include <time.h>
  9. #include <sys/types.h>
  10. #include <sys/timeb.h>
  11. #include "dateconv.h"
  12. #include "datetok.h"
  13.  
  14. #define MAXDATEFIELDS 25
  15.  
  16. /* imports */
  17. extern int parsetime();
  18.  
  19. /* forwards */
  20. int prsabsdate();
  21.  
  22. /* exports */
  23. extern int dtok_numparsed;
  24.  
  25. /*
  26.  * parse and convert absolute date in timestr (the normal interface)
  27.  */
  28. time_t
  29. getabsdate(timestr, now)
  30. char *timestr;
  31. struct timeb *now;
  32. {
  33.     int tz = 0;
  34.     struct tm date;
  35.  
  36.     return prsabsdate(timestr, now, &date, &tz) < 0? -1:
  37.         dateconv(&date, tz);
  38. }
  39.  
  40. /*
  41.  * just parse the absolute date in timestr and get back a broken-out date.
  42.  */
  43. int
  44. prsabsdate(timestr, now, tm, tzp)
  45. char *timestr;
  46. struct timeb *now;
  47. register struct tm *tm;
  48. int *tzp;
  49. {
  50.     register int nf;
  51.     char *fields[MAXDATEFIELDS];
  52.     static char delims[] = "- \t\n/,";
  53.  
  54.     nf = split(timestr, fields, MAXDATEFIELDS, delims+1);
  55.     if (nf > MAXDATEFIELDS)
  56.         return -1;
  57.     if (tryabsdate(fields, nf, now, tm, tzp) < 0) {
  58.         register char *p = timestr;
  59.  
  60.         /*
  61.          * could be a DEC-date; glue it all back together, split it
  62.          * with dash as a delimiter and try again.  Yes, this is a
  63.          * hack, but so are DEC-dates.
  64.          */
  65.         while (--nf > 0) {
  66.             while (*p++ != '\0')
  67.                 ;
  68.             p[-1] = ' ';
  69.         }
  70.         nf = split(timestr, fields, MAXDATEFIELDS, delims);
  71.         if (nf > MAXDATEFIELDS)
  72.             return -1;
  73.         if (tryabsdate(fields, nf, now, tm, tzp) < 0)
  74.             return -1;
  75.     }
  76.     return 0;
  77. }
  78.  
  79. /*
  80.  * try to parse pre-split timestr as an absolute date
  81.  */
  82. int
  83. tryabsdate(fields, nf, now, tm, tzp)
  84. char *fields[];
  85. int nf;
  86. struct timeb *now;
  87. register struct tm *tm;
  88. int *tzp;
  89. {
  90.     register int i;
  91.     register datetkn *tp;
  92.     register long flg = 0, ty;
  93.     int mer = HR24, bigval = -1;
  94.     struct timeb ftz;
  95.  
  96.     if (now == NULL) {        /* default to local time (zone) */
  97.         now = &ftz;
  98.         (void) ftime(now);
  99.     }
  100.     *tzp = now->timezone;
  101.  
  102.     tm->tm_mday = tm->tm_mon = tm->tm_year = -1;    /* mandatory */
  103.     tm->tm_hour = tm->tm_min = tm->tm_sec = 0;
  104.     tm->tm_isdst = 0;
  105.     dtok_numparsed = 0;
  106.  
  107.     for (i = 0; i < nf; i++) {
  108.         if (fields[i][0] == '\0')
  109.             continue;
  110.         tp = datetoktype(fields[i], &bigval);
  111.         ty = (1L << tp->type) & ~(1L << IGNORE);
  112.         if (flg&ty)
  113.             return -1;        /* repeated type */
  114.         flg |= ty;
  115.         switch (tp->type) {
  116.         case YEAR:
  117.             tm->tm_year = bigval;
  118.             /* convert 4-digit year to 1900 origin */
  119.             if (tm->tm_year >= 1900)
  120.                 tm->tm_year -= 1900;
  121.             break;
  122.         case DAY:
  123.             tm->tm_mday = bigval;
  124.             break;
  125.         case MONTH:
  126.             tm->tm_mon = tp->value - 1; /* convert to zero-origin */
  127.             break;
  128.         case TIME:
  129.             if (parsetime(fields[i], tm) < 0)
  130.                 return -1;
  131.             break;
  132.         case DTZ:
  133. #if 0
  134.             tm->tm_isdst++;
  135. #endif
  136.             /* FALLTHROUGH */
  137.         case TZ:
  138.             *tzp = FROMVAL(tp);
  139.             break;
  140.         case IGNORE:
  141.             break;
  142.         case AMPM:
  143.             mer = tp->value;
  144.             break;
  145.         default:
  146.             return -1;    /* bad token type: CANTHAPPEN */
  147.         }
  148.     }
  149.     if (tm->tm_year == -1 || tm->tm_mon == -1 || tm->tm_mday == -1)
  150.         return -1;        /* missing component */
  151.     if (mer == PM)
  152.         tm->tm_hour += 12;
  153.     return 0;
  154. }
  155.