home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume22 / nn6.4 / part19 / pack_date.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-07  |  4.0 KB  |  191 lines

  1. /*
  2.  *    (c) Copyright 1990, Kim Fabricius Storm.  All rights reserved.
  3.  *
  4.  *    Calculate an approximate "time_stamp" value for a date
  5.  *    string.  The actual value is not at all critical,
  6.  *    as long as the "ordering" is ok.
  7.  *
  8.  *    The result is NOT a time_t value, i.e. ctime() will
  9.  *    not produce the original Date string.
  10.  *
  11.  *    The date must have format:  [...,] [D]D Mmm YY hh:mm:ss TZONE
  12.  *
  13.  *    Thanks to Wayne Davison for the timezone decoding code.
  14.  */
  15.  
  16. #include "config.h"
  17.  
  18. /* #define DATE_TEST /* never define this !! */
  19.  
  20. static long wtz(h, m, c)
  21. int  h, m;
  22. char c;
  23. {
  24.     if (c != 's') h--;        /* daylight savings */
  25.     return h*60L+m*30L;
  26. }
  27.  
  28. static long etz(h, m, c)
  29. int  h, m;
  30. char c;
  31. {
  32.     if (c == 's') h++;        /* summer time */
  33.     return -(h*60L+m*30L);
  34. }
  35.  
  36. #define TOLOWER(ch) (isupper(ch) ? tolower(ch) : (ch))
  37.  
  38. static long tzone(date)
  39. register char *date;
  40. {
  41.     char ch1, ch2, ch3, ch4;
  42.     long tz, wtz(), etz();
  43.  
  44.     while (*date && !isalpha(*date)) date++;
  45.     if (*date == NUL || *date == 'G') return 0;
  46.  
  47.     ch1 = TOLOWER(*date);
  48.     while (date++, (ch2 = TOLOWER(*date)) == '.')    /* p.s.t. -> pst */
  49.     ;
  50.     while (date++, (ch3 = TOLOWER(*date)) == '.')
  51.     ;
  52.     while (date++, (ch4 = TOLOWER(*date)) == '.')
  53.     ;
  54.     switch (ch1) {
  55.      case 'n':
  56.     tz = wtz(3,1,0); break;        /* Newfoundland: nst */
  57.      case 'a':
  58.     if (ch2 == 'e') {
  59.         tz = etz(10,0,ch4); break;    /* Australian Eastern: aest, aesst */
  60.     }
  61.     if (ch2 == 'c') {
  62.         tz = etz(9,1,ch4); break;    /* Australian Central: acst, acsst */
  63.     }
  64.     if (ch2 == 'w') {
  65.         tz = etz(8,1,ch4); break;    /* Australian Western: awst, awsst */
  66.     }
  67.     tz = wtz(4,0,ch2); break;    /* Atlantic: ast, adt */
  68.      case 'b':
  69.     tz = etz(1,0,0); break;        /* British summer: bst */
  70.      case 'c':
  71.     tz = wtz(6,0,ch2); break;    /* Central: cst, cdt */
  72.      case 'e':
  73.     if (ch2 == 'e') {
  74.         tz = etz(0,0,ch3); break;    /* European Eastern: eet, eest */
  75.     }
  76.     tz = wtz(5,0,ch2); break;    /* Eastern: est, edt */
  77.      case 'g':
  78.     tz = etz(0,0,0); break;        /* Greenwich: gmt */
  79.      case 'h':
  80.     tz = wtz(10,0,ch2); break;    /* Hawaii: hst, hdt */
  81.      case 'j':
  82.     tz = etz(9,0,0); break;        /* Japan: jst */
  83.      case 'm':
  84.     if (ch2 == 'e') {
  85.         tz = etz(1,0,ch3); break;    /* Middle European: met, mest */
  86.     }
  87.     tz = wtz(7,0,ch2); break;    /* Mountain: mst, mdt */
  88.      case 'p':
  89.     tz = wtz(8,0,ch2); break;    /* Pacific: pst, pdt */
  90.      case 'w':
  91.     tz = etz(2,0,ch3); break;    /* Western European: wet, west */
  92.      case 'y':
  93.     tz = wtz(9,0,ch2); break;    /* Yukon: yst, ydt */
  94.      default:
  95.     tz = 0; break;        /* use GMT if we can't understand it */
  96.     }
  97.  
  98.     return tz;
  99. }
  100.  
  101. static next_int(dp)
  102. char **dp;
  103. {
  104.     register char *str = *dp;
  105.     register i;
  106.  
  107.     while (*str && !isdigit(*str)) str++;
  108.  
  109.     i = 0;
  110.     while (*str && isdigit(*str))
  111.     i = (i * 10) + *str++ - '0';
  112.  
  113.     *dp = str;
  114.     return i;
  115. }
  116.  
  117. time_stamp pack_date(date)
  118. char *date;
  119. {
  120.     register time_stamp res;
  121.     register int min, hour, day, mon, year;
  122.  
  123.     if (date == NULL || (day = next_int(&date)) == 0) return 0;
  124.  
  125.     while (*date && isspace(*date)) date++;
  126.  
  127.     switch (*date++) {
  128.      case 'J':
  129.     if (*date++ == 'a') { mon = 0; break; }
  130.     if (*date++ == 'n') { mon = 5; break; }
  131.     mon = 6; break;
  132.      case 'F':
  133.     mon = 1; break;
  134.      case 'M':
  135.     if (*++date == 'r') { mon = 2; break; }
  136.     mon = 4; break;
  137.      case 'A':
  138.     if (*date++ == 'p') { mon = 3; break; }
  139.     mon = 7; break;
  140.      case 'S':
  141.     mon = 8; break;
  142.      case 'O':
  143.     mon = 9; break;
  144.      case 'N':
  145.     mon = 10; break;
  146.      case 'D':
  147.     mon = 11; break;
  148.      default:
  149.     return 0;
  150.     }
  151.  
  152.     year = next_int(&date);
  153.     hour = next_int(&date);
  154.     min = next_int(&date);
  155.  
  156.     year -= 87;    /* base is 1987 */
  157.     if (year < 0) year += 100;
  158.  
  159.     res = (year * 12 + mon) * 31 + day - 1;
  160.     res *= 24 * 60;
  161.     res += (hour * 60) + min;
  162.  
  163.     return res + tzone(date);
  164. }
  165.  
  166.  
  167. #ifdef DATE_TEST
  168.  
  169.  
  170. main()
  171. {
  172.     char buffer[128];
  173.     char *dp;
  174.     unsigned long t;
  175.  
  176.     while (fgets(buffer, 128, stdin)) {
  177.     if (strncmp(buffer, "Date:", 5)) continue;
  178.  
  179.     dp = strchr(buffer, ':');
  180.     if (dp == NULL) continue;
  181.     dp++;
  182.     while (isspace(*dp)) dp++;
  183.     t = pack_date(dp);
  184.     printf("%lu\t%s\n", t, dp);
  185.     }
  186.  
  187.     exit(0);
  188. }
  189.  
  190. #endif
  191.